PowerShell / SecretStore

MIT License
158 stars 24 forks source link

Getting "Padding is invalid and cannot be removed" when trying to use store in local session when it was set up with remoting #62

Closed LeonarddeR closed 3 years ago

LeonarddeR commented 3 years ago

I set up the secret store under a user with PowerShell remoting. However, when running PowerShell under that user, either in a local session or with right clicking on the Windows PowerShell shortcut and choosing run as different user, I'm getting "Padding is invalid and cannot be removed" whatever I do. This also happens the other way around, i.e. when the secret store was set up in a local session and I'm trying to access it in a PowerShell remoting session.

LeonarddeR commented 3 years ago

Possibly related to #53, though the use case seems different there.

PaulHigin commented 3 years ago

...and choosing run as different user

Both SecretManagement and SecretStore are currently configured to a specific user context (see documentation for more information). If you start PowerShell (either locally or remotely) as a different user, you will need to configure SecretManagement and SecretStore for that user. I don't know what your repro steps are, but when I try simple examples of configuring SecretStore both locally and remotely with the same user account, it works as expected for me.

However, neither SecretManagement and SecretStore will work for Windows built-in accounts, because the configurations both rely on user context 'LocalAppData' for file locations, which aren't available for built-in accounts. I am working on better errors for these cases, but in the longer run we plan to implement machine scope ('AllUsers') for SecretManagement and SecretStore, where any user can register and manipulate secrets machine wide.

LeonarddeR commented 3 years ago

I don't know what your repro steps are, but when I try simple examples of configuring SecretStore both locally and remotely with the same user account, it works as expected for me.

Interesting, as for me, it does not.

I have three different use cases to create a secret store for user b, while I'm logged in as user a on my local system. Note that I"m in a domain.

  1. As user a, remote to the system with Enter-PSSession <machine> -Credential (get-credential) providing the credentials for user b
  2. As user a, Use mstsc to RDP to the server with credentials of user b and start PowerShell as normal
  3. As user a, use mstsc to rdp to the server with credentials of user a. In the start menu, richt click PowerShell, choose run as different users and provide credentials as user b.

In case 1, I'm getting the padding error when trying to access the store from case 2 and 3. In case 3, I'm getting the padding error from case 1. Case 2 is able to access a store created in case 3. I haven't tried case 2 as a first step just yet.

PaulHigin commented 3 years ago

I'll need to try and repro this. Are you using the default SecretStore configuration, requiring a password?

PaulHigin commented 3 years ago

I am still unable to repro this. I have installed and run SecretManagement/SecretStore on a fresh VM via PowerShell remoting, and it works as expected from: a) Within the PowerShell remoting session b) From an rdp session c) From a different local account running PowerShell with 'runas' from an alternate account into the test account

The error you are getting suggests the SecretStore file is corrupt (incorrect format). This can happen with different versions of the Microsoft.PowerShell.SecretStore module. The release version of SecretStore (1.0) is not compatible with older preview versions. Use Get-Module -list to check which versions are installed. PowerShell 7 and WindowsPowerShell may install in different locations so run it under both shell instances.

Get-Module -list Microsoft.PowerShell.SecretStore

    Directory: C:\Users\user\Documents\PowerShell\Modules

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Binary     1.0.0      Microsoft.PowerShell.SecretStore    {Unlock-SecretStore, Set-SecretStorePassword, Get-SecretSt...
Get-Module -list Microsoft.PowerShell.SecretStore | select path

Path
----
C:\Users\user\Documents\PowerShell\Modules\Microsoft.PowerShell.SecretStore\1.0.0\Microsoft.P...

After you uninstall any older versions of the module, run the Reset-SecretStore command under your test account. This will delete all secrets but also reset SecretStore to a good state, with the default configuration. You can also specify configuration settings with the command. You can pass in the password to use or have the command prompt you for it.

Reset-SecretStore -Force -PassThru
WARNING: !!This operation completely removes all SecretStore module secrets and resets configuration settings to new
values!!
Creating a new Microsoft.PowerShell.SecretStore vault. A password is required by the current store configuration.
Enter password:
***********
Enter password again for verification:
***********

      Scope Authentication PasswordTimeout Interaction
      ----- -------------- --------------- -----------
CurrentUser       Password             900      Prompt
LeonarddeR commented 3 years ago

I just installed secret store and secret management on a fresh system that didn't have it before, and there the problem also occurs. It doesn't matter whether I have a password protected store or not. When the store is protected, the padding error pops up after I try to unlock it. Note that this is PowerShell 5.1.

PaulHigin commented 3 years ago

Did you try running Reset-SecretStore command after getting the error?

There is not a lot of information in your repro. What kind of PowerShell remoting connection are you making? Is it to a default endpoint? Or is it to a custom endpoint using a Windows built-in account? SecretManagement/SecretStore does not currently work with built-in accounts, but only with interactive accounts with user profile.

LeonarddeR commented 3 years ago

I'm sorry. Here are the most compact steps to reproduce i can come up with.

First, in a local PowerShell session:

PS C:\WINDOWS\system32> enter-pssession MyMachine
[MyMachine]: PS C:\Users\MyUser\Documents> Reset-SecretStore
WARNING: !!This operation completely removes all SecretStore module secrets and resets configuration settings to new
values!!

Reset SecretStore
Are you sure you want to erase all secrets in SecretStore and reset configuration settings to default?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [?] Help (default is "N"): y
Creating a new Microsoft.PowerShell.SecretStore vault. A password is required by the current store configuration.
Enter password:
WARNING: A script or application on the remote computer MyMachine is asking to read a line securely. Enter sensitive
information, such as your credentials, only if you trust the remote computer and the application or script that is
requesting it.
****
Enter password again for verification:
WARNING: A script or application on the remote computer MyMachine is asking to read a line securely. Enter sensitive
information, such as your credentials, only if you trust the remote computer and the application or script that is
requesting it.
****
[MyMachine]: PS C:\Users\MyUser\Documents> Unlock-SecretStore
WARNING: A script or application on the remote computer MyMachine is sending a prompt request. When you are prompted,
enter sensitive information, such as credentials or passwords, only if you trust the remote computer and the
application or script that is requesting the data.

cmdlet Unlock-SecretStore at command pipeline position 1
Supply values for the following parameters:
Password: ****
[MyMachine]: PS C:\Users\MyUser\Documents>

Then, after connecting to the same machine with mstsc and starting PowerShell:

PS H:\> Unlock-SecretStore

cmdlet Unlock-SecretStore at command pipeline position 1
Supply values for the following parameters:
Password: ***
Unlock-SecretStore : Padding is invalid and cannot be removed.
At line:1 char:1
+ Unlock-SecretStore
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Unlock-SecretStore], CryptographicException
    + FullyQualifiedErrorId : System.Security.Cryptography.CryptographicException,Microsoft.PowerShell.SecretStore.Unl
   ockSecretStoreCommand

PS H:\>

I also ensured that only version 1.0 of the SecretStore and SecretVault modules are installed.

LeonarddeR commented 3 years ago

I think I've found the actual cause of this issue. It looks like the username of the logged in user is treated case sensitively. Therefore if your user name is john and at logon, you specify it first time as john and second time as John, the padding is invalid issue occurs.

You can reproduce this by running PowerShell as a different user, specifying the user name with different casing.

PaulHigin commented 3 years ago

Thanks for the extra information. Sounds like a bug and will take a look.

PaulHigin commented 3 years ago

@leonardder This does seem like something that would cause a encryption failure, but for all OS platforms I use the UserName is treated as case sensitive. So it is impossible to log into the same account with a user name with different casing. It is treated as a separate account. So I am unable to repro.

Please include all relevant information, including the platform you are running on, the remoting system you are using, and exact steps needed to repro.

OneUser1 commented 3 years ago

@leonardder Have you managed to fix your issue dealing with the username? You referenced my issue #53 at the beginning. What I also experienced is that it seemed to depend on from where I created the SecretStore and how I access it after the creation. Sounds similar.

Now your post was very helpful as I tested the behaviour with your hint regarding case-sensitivity. I could reporduce the issue doing the following (citing @leonardder from above):

@leonardder What version of Windows are you using?

As you can see from in my issue it was not clear to me/us where the problem came from. Unfortunately the problem just re-occured out of nothing and without having changed anything within the last weeks. Well, I am not aware that something has changed - it is possible that I changed the username when saving the scheduled task we are using and this made the error possible again.

PaulHigin commented 3 years ago

Thanks @OneUser1, so it seems the issue is with 'RunAs'. The location of the file is based on UserA but the current account context is UserB, and so is not decrypted correctly. I am not sure yet how this can be addressed but I can now move forward with a repro and investigation.

OneUser1 commented 3 years ago

@PaulHigin I am not sure whether I understand you correctly but in scenario 1 and scenario 2 use the account of UserB. UserA is not involved expect being the account used to start mstsc. Did you mean that also?

PaulHigin commented 3 years ago

Platform: W2k8 R2 server (Build: 6.1.7601.65536, PS v5.1.14409.1018)

Ok, I see how RunAs dialog will take the typed in user name in any case, and try to resolve it to a case sensitive username. So for me on Windows10, 'paultest' is resolved to the correct case sensitive 'PaulTest' user name. SecretStore is using the dynamic environment variable %USERNAME% for the current user name, and for me on Windows10 it is always in the correct case ('PaulTest').

But I suspect this is not true for W2k8 R2, and the environment variable user name is set to the typed in user name and not the resolved user name, and that this bug has since been fixed.

I need to think about whether we should try to fix this. Using the correct case sensitive user name for encryption is arguably more secure.

OneUser1 commented 3 years ago

Thanks for your repro. Where do you lookup the user name when testing? In my tests I always got the username exactly as typed in the RunAs dialog (using $env:username). Where do you see the username getting resolved to the correct case sensitive one?

PaulHigin commented 3 years ago

The code accesses the current user name environment variable via .NET, System.Environment.UserName. I always see it with the correct case in my Windows10 environment. I suspect you are only seeing it, with typed-in case, in your older W2k8 R2 environment, and that this was a bug fixed in later releases.

OneUser1 commented 3 years ago

Hm, I am not able to reproduce that.. I am doing the following to test that:

What I understood from your comment was that in both cases the correct case sensitive username should be returned. This is the exact same behaviour as on the W2k8 R2 system. Or maybe my tests are not performed correctly?

PaulHigin commented 3 years ago

I have a slightly more up to date system, and I have a different experience. Microsoft Windows 10.0.19043 So I wonder if this was fixed recently.

In any case, I have an idea for a fix that I will work on.

OneUser1 commented 3 years ago

I thought that during my other issue #53 there was no problem with the username but I double-checked it now. Result: My Win10 does experience the same error when the username does not match the one which created the secret store. Win10: 10.0.18363.0 PS: 5.1.18362.1593

Great - let me know when it is fixed👍🏻

PaulHigin commented 3 years ago

The easiest and simplest fix is to use the 'WindowsIdentity.GetCurrent()' API to get the current UserName, and not rely on the environment variable. This should ensure the correct UserName and casing. The change will go in the next (1.0.4) release.

OneUser1 commented 3 years ago

@PaulHigin Do you have any update on this bug for me? Can you maybe estimate when 1.0.4 will be released? Would be nice to hear from you. Thanks in advance!

PaulHigin commented 3 years ago

We haven't triaged the issues yet for release targets, but since there is only one bug fix (this one), I'll get a release out with the fix today or tomorrow.

PaulHigin commented 3 years ago

I forgot but I already had a PR ready to go, so that is checked in and I ran an automated release. So the new version is now available:

https://www.powershellgallery.com/packages/Microsoft.PowerShell.SecretStore/1.0.4

OneUser1 commented 3 years ago

Thanks for the fix and your fast answer. I will test this version of the module and come back to you with the result.

OneUser1 commented 3 years ago

@PaulHigin I installed the version of the module on the W2k8R2 server but the error keeps happening. Secret store and script were not changed until now. When using the "correct" spelling of the username, the secret store can be unlocked. To me the behaviour is the same as with v0.9.2 which we used before.

Is it possible that the existing secret store has a spelling of the username that is now conflicting with the one retrieved by the API you mentioned above?

PaulHigin commented 3 years ago

Sorry for not being clear. You will need to reset the SecretStore (Reset-SecretStore), and re-add your secrets, because the old existing store is encrypted with the old user name and casing. The fix ensures that going forward the username casing will be correct and consistent, but you have to start out with the correct casing when first creating the store.

OneUser1 commented 3 years ago

Thanks for your answer. I used Reset-SecretStore to reset the store but the error still occurs as described before. Do I need to remove the folder in local appdata completely and setup a new secret store?

PaulHigin commented 3 years ago

Hmm, no you shouldn't have to, Reset-SecretStore should do everything for you. But you can try it. I assumed that the .NET WindowsIdentity API would return the correct current user name, but I did not test it on Win2K8. One other fix I could apply would be to always make the UserName used for encryption, single case. But this is a more involved change to make without breaking existing SecretStore installs. Can you confirm that this change does not work, even after a new creation of SecretStore?

OneUser1 commented 3 years ago

I did the following today to test the behaviour on the W2k8R2 server:

I then tested the behaviour on my Win10 client (10.0.18363.0) by only using Unlock-SecretStore - same result... on which build did it work for you?

Do you have an estimated time for your planned changes? Is it more like a week or four weeks? Thanks for your help!

PaulHigin commented 3 years ago

The main problem is that I have never repro'd this problem, and have only been making educated guesses. I am not able to repro the username case issue on any Win10 machine, and the fact that you see it there means there is some other problem. So now I am thinking there may be something in your script that is triggering the issue. Do you get the same error if you simply run 'Get-Secret' on the command line in the two cases above? Or is only when you run your script?

OneUser1 commented 3 years ago

I get the same error when running Get-Secret on these clients. I tested the behaviour with a Win10 machine (v10.0.19043.0). This machine did not produce the error. I could see that the $env:username was in the correct casing though I spelled it differently two times (according to our hypothesis this should work as well and it did). I was not able to let the client use the "incorrectly spelled" username.

Now I thought whether maybe a corporate policy is influencing the behaviour regarding the username. I added a local user to my corporate Win10 machine (v10.0.18363.0) and ran the same script to setup a secret vault. I then repeated the same test steps and I was not able to reproduce the issue with the local user. I tried the same on the W2k8R2 server. The result is the same: It works with a local user but not with an AD user - in both cases the username will be resolved correctly (it does not depend on how I spell it when running the PowerShell!). I will try to find out what might be the reason for this behaviour. Do you have any way to find out which policy could influence the "username resolving"? If so, please let me know... Thanks in advance.

PaulHigin commented 3 years ago

It works with a local user but not with an AD user

Thanks! I can now repro this. Previously I was using a local account, but I now do see the problem with my AD domain account, even on Win10. In addition, I can see that my fix in 1.0.4 does not solve the problem. The incorrectly cased user name is still returned.

So I'll have to go with a more complex fix. I'll make this high priority and let you know when I have something.

OneUser1 commented 3 years ago

Thank your very much for your effort! I am pretty glad that you can repro the issue! I thought it would be a complex problem in our environment. By the way: I did some more testing yesterday. When not having DC connectivity (and no Kerberos usage), even with a AD domain user the correct casing is returned (disconnecting VPN/wifi). When having DC connectivity, the client starts a request using the incorrectly spelled username and the DC returns the correct username in a Kerberos AS-Rep reply. Seems like PS (and cmd as well) does not use the name returned by the DC..

PaulHigin commented 3 years ago

@OneUser1 Ok, I have released 1.0.5 with the fix.

OneUser1 commented 3 years ago

@PaulHigin I was able to test the behaviour on my Win10 machine as follows:

Is that how it is intended to work? From the mentioned PR it seems for me that the reset should not be necessary. Please confirm that the reset is necessary before I will do this on the production system. Thanks.

PaulHigin commented 3 years ago

@OneUser1 I recommend that you reset the store in your scenario, and the fix will ensure consistent username character casing from that point on.

For most users, this will just work because account username character casing is consistent from the OS, and old data can be successfully read. But in your scenario, it is impossible to know what character casing was originally used to create the store, and if you log in by typing the user name with a different character casing, the data cannot be decrypted and you get the error.

OneUser1 commented 3 years ago

@PaulHigin Thanks for your answer. After resetting the secret store and recreating the entries I can confirm that you fixed the bug with your last changes! Thanks a lot for your effort. This issue can be closed.