Passwords and Secure Strings


In certain situations, you may need to have a script prompt for a string that you need to keep safe and secure such as a password. PowerShell provides a special object called SecureString that is designed to securely work with string data. Three cmdlets are available for working with SecureString objects: Read-Host, ConvertFrom-Securestring, and ConvertTo-Securestring.

Read-Host prompts for input and masks whatever is typed. The typed input then returns as the result of the cmdlet that can be stored in a variable. For example:

 PS C:\> $password = read-host -assecurestring ******** PS C:\> 

The password is stored in the variable $password. However, unlike a regular variable, you can't just display the contents of a SecureString:

 PS C:\> $password System.Security.SecureString PS C:\> 

As you can see, the contents of $password weren't displayed. Instead, the type of $password-"System.Security.SecureString"-was displayed. So how can you get the password? Well, you can't exactly. It's intended to be passed directly to other cmdlets that accept a SecureString as their input.

However, there's another way in which SecureString is useful. You may have already realized that hardcoding passwords into a script is a bad idea because anyone with permission to run the script also has permission to read it, which means they can read the hardcoded password. SecureString provides a slight amount of additional security when you must hardcode a password. You start by creating a new SecureString like the ones we've shown you. Then you use ConvertFrom-SecureString to export your encrypted password in a format that can be hardcoded into a script:

 PS C:\> $password = read-host -assecurestring ******** PS C:\> $password = ConvertFrom-SecureString $password PS C:\> $password 01000000d08c9ddf0115d1118c7a00c04fc297eb010000009c0d9c7fe8c37b439faf e0000000002000000000003660000a80000001000000093aaa18edf6f108b6222559 00000004800000a00000001000000098e4c93b57f59ff35110960a80b248a2180000 10ef82f30674ca4beea5df77c556388e95238b2140000002735d16881363c9c7b385 c7aea529 PS C:\> 

That string of letters and numbers can be hardcoded into your script, assigning them to a variable. When you're ready to actually use the password, such as passing it as a parameter to a cmdlet that accepts a SecureString, then use ConvertTo-SecureString to turn the letters and numbers back into a SecureString:

 PS C:\> $password = read-host -assecurestring ******** PS C:\> $password = ConvertFrom-SecureString $password PS C:\> $password 01000000d08c9ddf0115d1118c7a00c04fc297eb010000009c0d9c7fe8c37b439faf e0000000002000000000003660000a80000001000000093aaa18edf6f108b6222559 00000004800000a00000001000000098e4c93b57f59ff35110960a80b248a2180000 10ef82f30674ca4beea5df77c556388e95238b2140000002735d16881363c9c7b385 c7aea529 PS C:\> $password= ConvertTo-SecureString $password PS C:\> $password System.Security.SecureString PS C:\> 

The last four lines show ConvertTo-SecureString being used. As you can see, once again $password is a SecureString.

Here's the only problem - the encryption algorithm used by SecureString is deterministic, which means any given input always results in the same output. This makes the encrypted password vulnerable to a dictionary attack, which occurs when the encrypted password is compared to a huge list of pre-encrypted passwords. When a match is found, the dictionary knows the clear-text password used to produce that particular encrypted password, which means the password is compromised.

Dictionary attacks are not particularly time-consuming once the dictionary itself is created. Pre-created dictionaries exist that contain every possible character combination for 6-, 7-, and 8-character passwords. Even good dictionaries will fit on a stack of DVD-ROM discs. If you plan to use this technique to hardcode passwords into your script, be sure they're very long passwords-think passphrases-to help avoid the possibility of an easy dictionary attack.

You should also be aware that a clever .NET developer or PowerShell scripter can decrypt the contents of a SecureString and display the clear-text result:

 PS C:\> $Secret = read-host -assecurestring ******** PS>$Secret System.Security.SecureString PS>$BSTR = [System.Runtime.InteropServices.marshal]::SecureStringToBSTR($Secret) PS>$ClearString = [System.Runtime.InteropServices.marshal]::PtrToStringAuto($BSTR) PS>[System.Runtime.InteropServices.marshal]::ZeroFreeBSTR($BSTR) PS>$ClearString The password PS> 

What happened, here? A new SecureString was created and stored in the variable $secret. This might be a password, for example. Then, .NET's COM interoperability services were used to convert the SecureString to a binary string (BSTR). It is then used to output the cleartext version into the variable $ClearString. This isn't exactly the huge security leak it looks like since it can only be done with the original SecureString object created by Read-Host, and only on the computer on which the SecureString was created on. So really, the only person who could use this trick is the person who typed the password in the first place. In essence, your personal login credentials are used to encrypt the SecureString in memory. So without those, it can't be decrypted.



Windows PowerShell. TFM
Internet Forensics
ISBN: 982131445
EAN: 2147483647
Year: 2004
Pages: 289

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net