/\/\o\/\/ PowerShelled

This blog has moved to http://ThePowerShellGuy.com Greetings /\/\o\/\/
$AtomFeed = ("Atom.xml")
$PreviousItems = (" Atari Laptop (no MSH content) "," Sending Mail from MSH "," MSH More replacement script update (HotFix) "," Enhanced More Function for MSH "," Get driveletters for All drives (Providers) in MSH... "," Math "," Exploring .NET types, classes and Enums from MSH "," Wipe the screen in MSH "," Blog series about Errorhandling in MSH "," This Month's line-break and Pipelines are Back "," ")

Thursday, November 17, 2005

 


Get-credential and Decrypting a SecureString in MSH



In MSH there are a couple of places where you will find a SecureString.

the Most Common will be Get-Credentials.

this will give you a secure way to enter and pass credentials to a CMDlet or function.

one place in MSH where this is very handy is in get-WMIobject.
if you want to connect with alternate credentials you can pass a Credential object.
this will give you a safe way to let the user enter a password for this.





MSH>get-wmiobject -credential $(get-credential) -computer ComputerName win32_process

Cmdlet get-credential at command pipeline position 1
Supply values for the following parameters:
Credential
User: mow
Password for user mow: ***


if you look at the passwordProperty of a credentialObject, you will see that it is a secureString object.

Also some .NET classes take a SecureString as Input, as we used in the run-as function in a former post :




Function Run-as {
$cred = get-credential ; [System.Diagnostics.Process]::start($args[0],$null,$cred.UserName,$cred.password,$null)
}
there is also a bug if you do not enter credentials see :do the MSH - CMD- MSH loop. & RunAs in MSH
and if you want to load a profile with the runas look here : Runas with loading Profile script in MSH

but what if we want to use a secureString to keep are own secred string ?
making it is Simple just use new-securestring,

but if we look at the methods of the SecureString there is no decryption option.
some nice methods to play with the contents but nothing to get them out.
but keeping a Secret is not as usefull if we can not get it out again.



MSH>$secret  gm


TypeName: System.Security.SecureString

Name MemberType Definition
---- ---------- ----------
AppendChar Method System.Void AppendChar(Char c)
Clear Method System.Void Clear()
Copy Method System.Security.SecureString Copy()
Dispose Method System.Void Dispose()
Equals Method System.Boolean Equals(Object obj)
get_Length Method System.Int32 get_Length()
GetHashCode Method System.Int32 GetHashCode()
GetType Method System.Type GetType()
InsertAt Method System.Void InsertAt(Int32 index, Char c)
IsReadOnly Method System.Boolean IsReadOnly()
MakeReadOnly Method System.Void MakeReadOnly()
RemoveAt Method System.Void RemoveAt(Int32 index)
SetAt Method System.Void SetAt(Int32 index, Char c)
ToString Method System.String ToString()
Length Property System.Int32 Length {get;}


I posted this question on the NG a time ago, but did not get an answer, and concluded that then it was only usefull for the get-WMIobject Command (did not find it in some .NET classes yet at that time)

but I found the solution here :

http://msdn2.microsoft.com/library/7kt014s1(en-us,vs.80).aspx

I needed to use the System.Runtime.InteropServices.marshal class for this.

so I worked this out :



MSH>$Secret = new-SecureString
Enter secret: ************

MSH>$Secret
System.Security.SecureString
MSH>$BSTR = [System.Runtime.InteropServices.marshal]::SecureStringToBSTR($Secret)
MSH>$ClearString = [System.Runtime.InteropServices.marshal]::PtrToStringAuto($BSTR)
MSH>[System.Runtime.InteropServices.marshal]::ZeroFreeBSTR($BSTR)
MSH>$ClearString
mow's Secret
MSH>
Remarks :

And we are there so now we can use the SecureString for our Own secrets ;-)

But wait a Minute ???? ..... This is a Security Leak ... you just converted it back again ... without to enter a password or anything !!!.. what use is the SecureString then ??

The trick is that you are the only one that can do this, so if another user tries this it will not work (you can use Export-SecureString and Import-SecureString to test this)


the secureString is using Windows Data Protection.(by Default)
the API use for this is Called DPAPI. the workings are a bit complex, but the important part for the subject is that it uses the current users credentials to en/decrypt the SecureString.

For more info :

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsecure/html/windataprotection-dpapi.asp
DPAPI is focused on providing data protection for users. Since it requires a password to provide protection, the logical step is for DPAPI to use a user's logon password, which it does, in a way. DPAPI actually uses the user's logon credential. In a typical system, in which the user logs on with a password, the logon credential is simply a hash of the user's password

so this is how we where able to Decrypt it and another user will not (b.t.w. it should not be possible on another Computer also !!).

combined with the import-securestring and Export-secure string this is a nice way to save personal data in MSH.
Also you can add your own key, or use Rijndael encryption if you need to be able to use only a key (I'm still a bit testing with this)

I have to look in to it still a bit more but ...
This makes the SecureString a whole lot more interesting and usefull as I did think before..

Enjoy Safely,

gr /\/\o\/\/


Comments:
Anonymous Marcel
If you use get-credential to get the credentials then you can use the GetNetworkCredential() method ot get the cleartext password. Underneath its just doing the same marshaling stuff you mentioned.

MSH>$cred = get-credential foo
MSH>$cred.GetNetworkCredential().Password
bar

If you used new-securestring then you could use new-object to create an MshCredential and then call GetNetworkCredential()

MSH>$secret = new-securestring
Enter secret: ***************

MSH>$cred = new-object System.Management.Automation.MshCredential user, $secret
MSH>$cred.GetNetworkCredential().Password
Setec Astronomy
MSH>

This way you avoid having to call the marshaling APIs.
 
Post a Comment

Links to this post:

Create a Link



<< Home

Archives

October 2005   November 2005   December 2005   January 2006   February 2006   March 2006   April 2006   May 2006   June 2006   July 2006   August 2006   September 2006   October 2006   November 2006   December 2006  

$Links = ("PowerShell RC1 Docs"," PowerShell RC1 X86"," PowerShell RC1 X64"," Monad GettingStarted guide"," Monad Progamming Guide"," Monad SDK"," Monad videos on Channel 9"," MSH Community Workspace"," scripts.readify.net "," MonadSource"," www.reskit.net"," PowerShell Blog"," Under The Stairs"," computerperformance powershell Home"," proudlyserving"," MSH on wikipedia"," MSHWiki Channel 9"," Keith Hill's Blog"," Precision Computing"," PowerShell for fun"," MSH Memo (Japanese)"," monadblog")

find-blog -about "PowerShell","Monad" | out-Technorati.
find-blog -contains "","" | out-Technorati.
Google
 
Web mow001.blogspot.com

This page is powered by Blogger. Isn't yours?