locked
Powershell Encrypted password file RRS feed

  • Question

  • We have a problem with several scripts which demand authentication. We have a set of scripts that runs some tests and send the result by mail. Our Exchange environment is set up to use authentication for SMTP. In order to authenticate towards Exchange the credentials are kept in a password encrypted file. The problem is that for some reason the password encrypted file becomes unreadable for the script in which authentication fails. 

    It left me scratching my baldy head. We set the encrypted File, run the script in the service account's environment, and everything runs as expected. We create a scheduled task accoringly (with a service account), test the scheduled task which completes successfully as well. However a few days later the scheduled taks start failing, and every time it is the script that fails to open encrypted file. 

    password file:

    $credential = Get-Credential
    $credential.Password | ConvertFrom-SecureString | Set-Content c:\System\scripts\$($FN).txt

    Script

    $password = Get-content $path\securestringpw.txt | convertto-securestring
    $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password

    The scripts runs good for a day or 2, and then starts failing:

    convertto-securestring : Key not valid for use in specified state.
    At C:\System\Scripts\Mailboxdatabase_Report.ps1:13 char:62
    + $password = Get-content $path\securestringpwd.txt | convertto-securestr ...
    +                                                              ~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [ConvertTo-SecureString], CryptographicException
        + FullyQualifiedErrorId : ImportSecureString_InvalidArgument_CryptographicError,Microsoft.PowerShell.Commands.Conv
       ertToSecureStringCommand
    
    new-object : Exception calling ".ctor" with "2" argument(s): "Cannot process argument because the value of argument "pa
    ssword" is null. Change the value of argument "password" to a non-null value."
    At C:\System\Scripts\Report.ps1:14 char:9
    + $cred = new-object -typename System.Management.Automation.PSCredential -argument ...
    nobody is modifying the password file and antivirus is excluded to the password file location. All the scripts run from the same location, which is a Windows Server 2012r2 server which is used for infrastructure management tasks.


    Answers provided are coming from personal experience, and come with no warranty of success. I as everybody else do make mistakes. Each scheduled script uses its own dedicated password file.


    • Edited by Killerbe Wednesday, December 2, 2015 10:32 AM added information
    Wednesday, December 2, 2015 10:30 AM

Answers

  • Ok, i think i have found the root cause of the issue.

    I discovered that the service account was logged in with a temporarily profile and not a full profile.

    This management server is a terminal server (WS2012r2) which is used to provide access to all our tools which are used by the various IT departments. This management server is virtualized and saw that some users as the service account got a temp profile, instead of a normal profile.

    The reason why the users got a temporarily profile, seemed to be related to two causes:

    1. The Vmware tools where not loaded anymore which presumably caused driver issue's?
    2. Windows UPD's, It seems that the disks fail to load when a user has a connection to the desktop and has a session to a RemoteApp on that server at the same time. In this case the UPD can not be linked on the second session in which the user receives a temporarily profile. 

    http://ryanmangansitblog.com/2014/04/09/rds-2012-r2-apps-and-sessions-using-upd-issue/

    If the service account has a valid profile, everything works as expected.


    Answers provided are coming from personal experience, and come with no warranty of success. I as everybody else do make mistakes.

    • Marked as answer by Bill_Stewart Tuesday, January 12, 2016 9:04 PM
    Thursday, December 10, 2015 1:11 PM

All replies

  • Encrypted files cannot be moved between accounts. 


    \_(ツ)_/

    Wednesday, December 2, 2015 12:04 PM
  • It is not used between different accounts either. All scripts run under one specific service account on the same server. The file is encrypted using that service account. 

    Answers provided are coming from personal experience, and come with no warranty of success. I as everybody else do make mistakes.

    Wednesday, December 2, 2015 12:48 PM
  • Something is preventing the password file from being read.  Look at the error message.


    \_(ツ)_/

    Wednesday, December 2, 2015 1:11 PM
  • yes, i thought the file is locked by another process inwhich i suspected the antivirus of locking the password file. However this is not the case. Have checked the security on the file and only administrators and system have write access. All users have read access.

    Answers provided are coming from personal experience, and come with no warranty of success. I as everybody else do make mistakes.

    Wednesday, December 2, 2015 3:46 PM
  • Key not valid for use in specified state.

    This error means that you cannot decrypt (ConvertTo-SecureString) using a different user account than the account used to encrypt to the encrypted standard string. The following article gives the details:

    Windows IT Pro: Resetting the Local Administrator Password on Computers


    -- Bill Stewart [Bill_Stewart]

    Wednesday, December 2, 2015 5:03 PM
  • Well it is the same account and it works for a couple of hours after recreating the password file.

    I open powershell on the computer using the account which is used to run the script (Run as different User)

    Create the pasword file.

    $credential = Get-Credential
    $credential.Password | ConvertFrom-SecureString | Set-Content c:\System\scripts\$($FN).txt

    Then i create a scheduled tasks which runs as the same service account.

    Run the scheduled Task to test if it works, and it runs beautifully.

    So i expect to be set. Next day, no mail. What when wrong? Open powershell again as the service account and the run the script again. The script fails because it cannot decrypt the password file. How can a different account be used then?

    convertto-securestring : Key not valid for use in specified state.
    At C:\System\Scripts\Mailboxdatabase_Report.ps1:13 char:62
    + $password = Get-content $path\securestringpwd.txt | convertto-securestr ...
    +                                                              ~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [ConvertTo-SecureString], CryptographicException
        + FullyQualifiedErrorId : ImportSecureString_InvalidArgument_CryptographicError,Microsoft.PowerShell.Commands.Conv
       ertToSecureStringCommand
    
    new-object : Exception calling ".ctor" with "2" argument(s): "Cannot process argument because the value of argument "pa
    ssword" is null. Change the value of argument "password" to a non-null value."
    At C:\System\Scripts\Report.ps1:14 char:9
    + $cred = new-object -typename System.Management.Automation.PSCredential -argument ...
    The password file nor the script have been moved or modified. The script sits on the same machine where the password file is created, stored and used. The script run in the environment of the service account as we do not want to run scripts under our management accounts.  


    Answers provided are coming from personal experience, and come with no warranty of success. I as everybody else do make mistakes.

    Thursday, December 3, 2015 3:15 PM
  • Well it is the same account...

    ...

    The script run in the environment of the service account as we do not want to run scripts under our management accounts.

    I don't know whether these two statements are contradictory, but if you want to be able to convert a encrypted standard string in a text file to a SecureString object (ConvertTo-SecureString), you must use the exact same exact that was used to encrypt the SecureString (ConvertFrom-SecureString).

    This means that in your case you must log on as the service account when you use ConvertFrom-SecureString to create the encrypted standard string password file. Otherwise you will get the "Key not valid for use in specified state" error.


    -- Bill Stewart [Bill_Stewart]

    Thursday, December 3, 2015 3:39 PM
  • Also, please try using the following script to create the encrypted standard string password file:


    #requires -version 2
    
    param(
      [parameter(Mandatory=$true)] [String] $EncryptedPasswordFilename
    )
    
    Function ConvertTo-String {
      param(
        [System.Security.SecureString] $secureString
      )
      $marshal = [System.Runtime.InteropServices.Marshal]
      try {
        $intPtr = $marshal::SecureStringToBSTR($secureString)
        $string = $marshal::PtrToStringAuto($intPtr)
      }
      finally {
        if ( $intPtr ) {
          $marshal::ZeroFreeBSTR($intPtr)
        }
      }
      $string
    }
    
    while ( $true ) {
      $pwd1 = Read-Host "Enter password" -AsSecureString
      $pwd2 = Read-Host "Confirm password" -AsSecureString
      if ( (ConvertTo-String $pwd1) -ceq (ConvertTo-String $pwd2) ) {
        break
      }
      Write-Host "`r`nPasswords don't match`r`n"
    }
    
    if ( ConvertTo-String $pwd1 ) {
      ConvertFrom-SecureString $pwd1 | Out-File $EncryptedPasswordFilename -Encoding ASCII
    }
    

    The script requires a filename parameter and writes the encrypted standard string to the specified file.


    -- Bill Stewart [Bill_Stewart]

    Thursday, December 3, 2015 3:46 PM
  • The service account is not used when logging on to the server (RDP), when we log on to the server we use our administrative account (accounttracing). Then I open powershell (run as different user), where i specify the credentials of the service account. Powershell opens, running under the credentials of the service account.

    I run the command which are used to store the password (which are actually stored in a script (storecred.ps1)), in the powershell windows which is running under the priviliges of the service account (Run as). The password file is created in the designated directory. Then i run the report.ps1 in the same powershell windows which is still running as the service account. Everything works and the mail is received in the mailbox.

    Then i schedule the task, using task scheduler, and schedule that task to run with the priviliges of the service account. The service account has the priviliges to logon as a batch job. Run the scheduled task and recieve the mail. This means that the password file creation, script and sheduled task are all running under the credentials of the service account. We do not log on as the service account to the computer. However my colegeau created a test script, password file and scheduled tasks under his administrative account (which was logged on), and we see the same behaviour with that account as well. therefore it seems that acctually logging on with the specified credentials, is not related to the issue at hand.

    I will try your script to create the password file, but see no difference besides the -encoding parameter.

    If the password stored in the password file is wrong then the scheduled task nor the  tests which ran as described previously would complete successfully. 

    I highly appreciate the help.

     

    Answers provided are coming from personal experience, and come with no warranty of success. I as everybody else do make mistakes.

    Thursday, December 3, 2015 4:26 PM
  • Reran the password operation using this script (passwordtest.txt), using the service account. Ran the report.ps1 script in the same session as where the password file was created. report was delivered to the mailbox. Closed the powershell session, and restarted a new powershell session, again with the credentials of the service account. Launched the Report.ps1 script, which fails again to unencrypt the password file.

    convertto-securestring : Key not valid for use in specified state.
    At C:\System\Scripts\Report1.ps1:13 char:62
    + $password = Get-content C:\System\Scripts\Passwordtest.txt | convertto-securestr ...
    +                                                              ~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [ConvertTo-SecureString], CryptographicException
        + FullyQualifiedErrorId : ImportSecureString_InvalidArgument_CryptographicError,Microsoft.PowerShell.Commands.Conv
       ertToSecureStringCommand
    It seems related to the profile, as soon as the profile under which the password is created is closed, the password can no longer be decripted?

     

    Answers provided are coming from personal experience, and come with no warranty of success. I as everybody else do make mistakes.


    • Edited by Killerbe Thursday, December 3, 2015 4:45 PM
    Thursday, December 3, 2015 4:44 PM
  • Found following article http://www.travisgan.com/2015/06/powershell-password-encryption.html, which kind of proves what i am doing is correct, wherefore it must be related to that the server/envoronment which it is running on. Will try my sripts on another server, and see if the issue is also display on that server.

    Answers provided are coming from personal experience, and come with no warranty of success. I as everybody else do make mistakes.


    • Edited by Killerbe Thursday, December 3, 2015 4:57 PM
    Thursday, December 3, 2015 4:55 PM
  • Instead of launching powershell.exe using alternate credentials, try logging onto the computer using the service account's credentials (not run as).


    -- Bill Stewart [Bill_Stewart]

    • Proposed as answer by Bill_Stewart Thursday, December 10, 2015 2:41 PM
    Thursday, December 3, 2015 5:32 PM
  • This is what my colegeau tried by running a test script under his personal account. Where the same issue is displayed. As soon as he closses the Powershell session the decryption of the password file fails.

    Answers provided are coming from personal experience, and come with no warranty of success. I as everybody else do make mistakes.

    Friday, December 4, 2015 10:58 AM
  • Hi Killerbe,

    sounds mysterious. Some time ago I wrote a function to encrypt credentials for a given account, called Encrypt-Credential. Why not give that a go? The main difference, between this script-function and what you have tried so far, is that the encryption is done as a scheduled task that runs under the specified account.

    While I believe it should work the way you are doing things, using this function eliminates the last difference between encryption and decryption modes.

    Cheers,
    Fred


    There's no place like 127.0.0.1

    Friday, December 4, 2015 1:17 PM
  • Not able to reproduce. I am using in production with no issues.

    -- Bill Stewart [Bill_Stewart]

    Friday, December 4, 2015 1:21 PM
  • Hi Killerbe,

    just wanted to say that the way you are using to encrypt the password is not the secured one 

    simply use the below script and it will decrypt your password again 

    $password = Get-Content "C:\TempFiles\MSOL.txt" | ConvertTo-SecureString
    $Ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($password)
    $result = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($Ptr)
    [System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($Ptr)
    $result 


    Please remember, if you see a post that helped you please click "Vote As Helpful" and if it answered your question, please click "Mark As Answer"

    Friday, December 4, 2015 9:36 PM
  • Ok, i think i have found the root cause of the issue.

    I discovered that the service account was logged in with a temporarily profile and not a full profile.

    This management server is a terminal server (WS2012r2) which is used to provide access to all our tools which are used by the various IT departments. This management server is virtualized and saw that some users as the service account got a temp profile, instead of a normal profile.

    The reason why the users got a temporarily profile, seemed to be related to two causes:

    1. The Vmware tools where not loaded anymore which presumably caused driver issue's?
    2. Windows UPD's, It seems that the disks fail to load when a user has a connection to the desktop and has a session to a RemoteApp on that server at the same time. In this case the UPD can not be linked on the second session in which the user receives a temporarily profile. 

    http://ryanmangansitblog.com/2014/04/09/rds-2012-r2-apps-and-sessions-using-upd-issue/

    If the service account has a valid profile, everything works as expected.


    Answers provided are coming from personal experience, and come with no warranty of success. I as everybody else do make mistakes.

    • Marked as answer by Bill_Stewart Tuesday, January 12, 2016 9:04 PM
    Thursday, December 10, 2015 1:11 PM
  • This is why I suggested to log on as the service account (not use "run as").

    -- Bill Stewart [Bill_Stewart]

    Thursday, December 10, 2015 2:41 PM