PowerShell Remoting Project Home

Wednesday, February 08, 2006

Tired of Typing Administrator’s Password Repeatedly?

An example of how to use new- SecureString, export-SecureString and import-SecureString.

If you read my previous blog entry and were convinced to logon as non-privilege user, you must have discovered the beauty and power of runas.exe or our su.msh.

But being the only user of that laptop, isn't it annoying to type Administrator's password again and again just for some routing jobs?  Why can't we just incorporate the Administrator's Password in our msh script?
Yes, we can. We are not dumb enough to put plain text password in our script. We have to store our password in an encrypted form. Monad beta3 contain three cmdlets to operate SecureString:

Name       : export-SecureString
Definition : export-SecureString [-SecureString] SecureString [[-SecureKey] Sec
             ureString] [-Verbose] [-Debug] [-ErrorAction ActionPreference] [-E
             rrorVariable String] [-OutVariable String] [-OutBuffer Int32]
             export-SecureString [-SecureString] SecureString [-Key Byte[]] [-V
             erbose] [-Debug] [-ErrorAction ActionPreference] [-ErrorVariable S
             tring] [-OutVariable String] [-OutBuffer Int32]

Name       : import-SecureString
Definition : import-SecureString [-String] String [[-SecureKey] SecureString] [
             -Verbose] [-Debug] [-ErrorAction ActionPreference] [-ErrorVariable
              String] [-OutVariable String] [-OutBuffer Int32]
             import-SecureString [-String] String [-Key Byte[]] [-Verbose] [-De
             bug] [-ErrorAction ActionPreference] [-ErrorVariable String] [-Out
             Variable String] [-OutBuffer Int32]

Name       : new-SecureString
Definition : new-SecureString [-Verbose] [-Debug] [-ErrorAction ActionPreferenc
             e] [-ErrorVariable String] [-OutVariable String] [-OutBuffer Int32]

Using export-SecureString, we can export a securestring (Administrator's Password) to a safe, persistable format (encrypted Administrator's Password). When needed, we can use import-SecureString to decrypt the output of export-securestring and restore it to a securestring.
> export-SecureString (new-SecureString)|out-file Admin.pass
Enter secret: ******

> get-content Admin.pass
01000000d08c9ddf0115d1118c7a00c04fc297eb0100000091700afb9271384c8d9d0f5fc5bbcad
d0000000002000000000003660000a8000000100000003ab5cb17d04880206425514877334d5600

(Clipped)
Now we can write a script like following:
##########################################
# Defrag.msh
# Start Disk Defragmenter as Administrator
# From http://mshforfun.blogspot.com/
# This script is provided AS IS
# Use it at your own risk
##########################################
$Password=import-SecureString (get-content D:\msh\Admin.pass)
$Windir=(get-childitem Env:windir).Value
$StartInfo = new-object System.Diagnostics.ProcessStartInfo
$StartInfo.UserName = "Admin"
$StartInfo.Password = $Password
$StartInfo.FileName = $Windir + "\system32\mmc.exe"
$StartInfo.Arguments = $Windir + "\system32\dfrg.msc"
$StartInfo.WorkingDirectory = $Windir + "\system32"
$StartInfo.LoadUserProfile = $true
$StartInfo.UseShellExecute = $false
[System.Diagnostics.Process]::Start($StartInfo)
Tada! No more prompts for password!

Something needed to mention:
1. Although I don't know the default key which export-SecureString used to encrypt password, I am pretty sure this key is account-specific and domain-specific. That is to say, another user on the same computer can not use import-SecureString to decrypt export-SecureString output.  Even a user with same account name can't decrypt it if he/she is on another computer (domain). If an unauthorized user tried to import-SecureString, he/she will get an error:
import-SecureString : Key not valid for use in specified state.
But that does not rule out bruce attack. So make sure to apply restricted access rule to you password file. It should be only readable by yourself and Administrators group.

2. Export-SecureString can take a key (a SecureString or byte[]) to encrypt SecureString. Import-SecureString will require the same key to decrypt. (Then we would have to type another password - the encrypt key) This method will output an encrypted password which can be used by another user. But this feature is yet not available in version beta 3. You will get an error:
> $key=new-securestring
Enter secret: *****
> export-securestring (new-securestring) -SecureKey $key
Enter secret: ******
export-SecureString : Cannot process argument because the value of argument "key" is invalid.
Added on 14th, Feb 2006
This is not a bug:
From Lee Holmes--When you use an encryption key on export-secureString, it must be of a length supported by the encryption algorithm. That is 128,192, or 256 bytes -- which is 8, 12, or 16 unicode characters if you type them. I'll file a doc bug to make this more clear.
Added on 14th, Feb 2006
3. Sign your script, and apply the AllSigned execution policy to prevent the script was tampered by malicious user.

4. DO NOT try to grant access to another user using this method. As you can see, if a non-privilege user got the content of Admin.pass (if Admin.pass properly encrypted for this specific user), he can do anything as an Administrator! 

There are more in depth discuss about Cryptograpy in MSH on MoW's Blog: here and here

Have Fun!

[Edit: Monad has now been renamed to Windows PowerShell. This script or discussion may require slight adjustments before it applies directly to newer builds.]

Tags:       


Comments:
I have also some info about this on my blog :

about remark 1

More about the DPAPI encryption API used :

http://mow001.blogspot.com/2005/11/get-credential-and-decrypting.html

and about remark 2 using a Key to encrypt.

http://mow001.blogspot.com/2005/11/more-on-cryptograpy-and-msh.html

gr /\/\o\/\/
 
To MoW:
Do you get the same error when you tried to use a Key to encrypt?
 
Yep, also with my example
hmm b3 ?
 
Hi Tony;

This has been a great series of posts. Keep it up! I started to write some
points in a comment, but it got pretty long -- so I wrote it up here:
http://www.leeholmes.com/blog/CachingCredentialsForAdministrativeTasks.aspx

But some more minor points about this article:
- Brute force attacks against your encrypted password file should not
be a concern. Determining when you've successfully brute-forced a
password is very difficult. It would be much easier to brute-force
the Administrator's password directly, as it is almost definitely
less random, and is easy to determine when you've got it right.
- When you use an encryption key on export-secureString, it must be
of a length supported by the encryption algorithm. That is 128,
192, or 256 bytes -- which is 8, 12, or 16 unicode characters if
you type them. I'll file a doc bug to make this more clear.
 
Thanks for your comment!
 
Typo -- I mean bits, not bytes!
 
Hello! Newbie here loving this blog!

I have noticed here or there that certain cmdlets are not available to me. Just like the encryption cmdlets which are not recognized in my version of either EMS or powershell. I have a scheduled task that calls an EMS script which simply tries to grab files from a remote server (\\some\server). Normally this script fails unless a previous connection was authenticated to that path using some other credentials. Your post got me heading in the right direction but none of the "-SecureString" functions are recognized. Do i need to load some added modules here?
 
Gian, that because the original script was written for older version of Powershell. I've rewritten and test it (I am not a pro though):

#To read your pass from console and save it encrypted in a file:
$secureString = Read-Host -AsSecureString
ConvertFrom-SecureString $AccPass | out-file c:\account.txt

#Script to start defrag (I've added domain setting also):

$accPass = gc C:\account.txt | ConvertTo-SecureString
$Windir=(get-childitem Env:windir).Value
$StartInfo = new-object System.Diagnostics.ProcessStartInfo
$StartInfo.UserName = "user"
$StartInfo.Domain = "domain"
$StartInfo.Password = $accPass
$StartInfo.FileName = $Windir + "\system32\mmc.exe"
$StartInfo.Arguments = $Windir + "\system32\dfrg.msc"
$StartInfo.WorkingDirectory = $Windir + "\system32"
$StartInfo.LoadUserProfile = $true
$StartInfo.UseShellExecute = $false
[System.Diagnostics.Process]::Start($StartInfo)
 
Previous post by PanTzeR. Cheers.
 
tony has been working on a great series of posts to explore some of monad's security features. he provides a method to start programs using the administrator account, without having to always type in the administrator's password.
what are the first signs of pregnancy | first signs of pregnancy | early detection pregnancy tests
 

Post a Comment





<< Home