This blog has moved to http://ThePowerShellGuy.com
Greetings /\/\o\/\/
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 :
- the BSTR is a pointer to the memoryLocation
- the ZereFreeBSTR is needed to clean the Memory
- Normaly you would NOT store the result in a clearstring LOL
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.aspDPAPI 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 passwordso 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\/\/