Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SecureString in file "randomly" stops working

I developed a PowerShell script which processes certain files and transfers them via SFTP. To do so, it uses the SecureString type to read and decrypt the SFTP user credentials from an encrypted text file whenever the credentials are needed to authenticate to the SFTP server. This is required because I am not allowed to store the credentials as plain text in a file (or in the script itself) because it would otherwise not pass the next security audit.

In addition to the script there is a separate configuration script which must be run once to specify the sftp user credentials, encrypt them and save them to the text file. This is the (simplified) code of that configuration script:

Write-Output "Please enter the username of the SFTP user."
$username = Read-Host
Write-Output "Please enter the password of the SFTP user"
$password = Read-Host -AsSecureString
$username | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "$scriptroot\Credentials.dat"
$password | ConvertFrom-SecureString | Out-File -Append "$scriptroot\Credentials.dat"

Basically the two scripts work just fine and do what they are supposed to. However, for whatever reason the decryption will stop working once I log out and then log back into windows again.

I do not understand why this stops working over and over again and I am not sure what to do about it. Does anybody know a way to figure out why the decryption stops working due to me logging out of the system? The script does not even run under my own user, it is executed as a scheduled task which runs under a completely different AD user.

I also read that Microsoft no longer recommends using SecureString for new projects, but then what is the alternative that can be used instead? How else am I supposed to securely store user credentials in a file without having some sort of plain text decryption key stored in the script or in another file somewhere?

like image 829
Chris Avatar asked Mar 03 '20 15:03

Chris


1 Answers

It's really kind of odd the to decrypt just stops working, that sounds environmental. However, why are you doing this, this way...

Write-Output "Please enter the username of the SFTP user."
$username = Read-Host
Write-Output "Please enter the password of the SFTP user"
$password = Read-Host -AsSecureString
$username | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "$scriptroot\Credentials.dat"
$password | ConvertFrom-SecureString | Out-File -Append "$scriptroot\Credentials.dat"

... vs going one fo these routes.

$UserCreds = Get-Credential -Message 'Please enter the username of the SFTP credentials'
$UserCreds.GetNetworkCredential().UserName
$UserCreds.GetNetworkCredential().Password
<#
# Results

postanote
password
#>

Or this way,

Get-Credential -Message 'Please enter the username of the SFTP credentials.' | 
Export-Clixml -Path 'D:\temp\SFTPUserCreds.xml'
Get-Content -Path 'D:\temp\SFTPUserCreds.xml'
<#
# Results

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>System.Management.Automation.PSCredential</T>
      <T>System.Object</T>
    </TN>
    <ToString>System.Management.Automation.PSCredential</ToString>
    <Props>
      <S N="UserName">postanote</S>
      <SS N="Password">01000000d08c9ddf0115d1118c7a00c04fc297eb01000000bd0a9dd27ffa41419fb2b289838ebe6400000000020000000000106600000001000020000000ad2e4c96413a3e93e461f600e98f72aa5
e3493bde41ac40491bfd4bedc462152000000000e8000000002000020000000e0016657a9f6e545b55876fa8095143c08046f1361baec0f693a1e823cc6ee0d200000006949857c09b23099dab66fdc3a7e4f7637970dbd3aa13
be11fda7c8de63df70e40000000f9a266cbb34440f64d9a2bdeaaec3a6cda483138e0be29323ca0a523ac475e169793557e74dd208e3d4292aa4fbe5b90fc7023d41c4dd6d01f819366e0587885</SS>
    </Props>
  </Obj>
</Objs>
#>

no decrypt needed, just pass the variable names

($UserCreds = Import-Clixml -Path 'D:\Temp\SFTPUserCreds.xml')
<#
# Results

UserName                      Password
--------                      --------
postanote System.Security.SecureString
#>

Or this way

Get-Credential -Message 'Please enter the username of the SFTP credentials.' | 
Export-PSCredential -RegistryPath 'HKCU:\software\SFTP' -Name SFTPUserCreds
$UserCred = Import-PSCredential -RegistryPath 'HKCU:\Software\SFTP' -Name SFTPUserCreds

# Or just use Windows Credential Manager
Find-Module -Name '*CredentialManager*' | Format-Table -AutoSize

Version Name                          Repository Description                                                                        
------- ----                          ---------- -----------                                                                        
2.0     CredentialManager             PSGallery  Provides access to credentials in the Windows Credential Manager                   
...

So, even based on what you've read about SecureString, it's still a thing for most folks, though based on what I show above, I am not sure why.

Anyway, give one or more of the above a shot to see if that allows you more consistancy.

like image 119
postanote Avatar answered Nov 08 '22 12:11

postanote