Spaß mit .Net SecureString und Powershell oder sicheres Speichern und Einlesen von Passwörtern


Wer sich per .Net dem Thema SecureString annähert wird sich irgendwann fragen: “Warum bekomm ich den hinterlegten String nicht einfach zurück?”. Tja die Sache liegt in der Natur des SecureString selber. Er soll sicher sein!

Fangen wir mal mit einer einfachen Geschichte an, man möchte ein Passwort sicher eingeben:

PS> $pw=Read-Host –AsSecureString
*****
PS>

Sieht schon mal gut aus. Meine Passworteingabe lautete Hallo und es wurden aber nur Sternchen angezeigt. Wer jetzt denkt, man bekommt bei Abfrage von $pw das Passwort der täuscht sich:

PS> $pw
System.Security.SecureString

OK, dann halt über ein Property?

PS> $pw | Get-Member

   TypeName: System.Security.SecureString

Name         MemberType Definition
—-         ———- ———-
AppendChar   Method     void AppendChar(char c)
Clear        Method     void Clear()
Copy         Method     securestring Copy()
Dispose      Method     void Dispose(), void IDisposable.Dispose()
Equals       Method     bool Equals(System.Object obj)
GetHashCode  Method     int GetHashCode()
GetType      Method     type GetType()
InsertAt     Method     void InsertAt(int index, char c)
IsReadOnly   Method     bool IsReadOnly()
MakeReadOnly Method     void MakeReadOnly()
RemoveAt     Method     void RemoveAt(int index)
SetAt        Method     void SetAt(int index, char c)
ToString     Method     string ToString()
Length       Property   int Length {get;}

Na supi! Nur Length ist als Property vorhanden. Na dann vielleicht ToString()?

PS> $pw.ToString()
System.Security.SecureString

Nene, das Ding soll ja sicher sein!

Übrigens was gibt Length zurück?

PS> $pw.Length
5

Das würde passen, “Hallo” hat genau fünf Buchstaben. Kurz gesagt, es gibt keine direkte Möglichkeit den String zurückzubekommen.

Wofür braucht man nun das Ding? Die aktuelle Beschreibung auf MSDN (V4.5), gibt keinen Tipp. http://msdn.microsoft.com/en-us/library/system.security.securestring.aspx

Also mal etwas recherchiert:

Sicher gibt es noch mehr Stellen, aber die kleine Auswahl sollte erst mal reichen.

OK, der Anwendungszweck gegeben, aber was kann ich damit anfangen? Vor allem im Zusammenhang mit Powershell? Ein erster Hinweis steht in der SecureString Doku auf MSDN:

Note that SecureString has no members that inspect, compare, or convert the value of a SecureString. The absence of such members helps protect the value of the instance from accidental or malicious exposure. Use appropriate members of the System.Runtime.InteropServices.Marshal class, such as the SecureStringToBSTR method, to manipulate the value of a SecureString object.

Aha, man muss also in die Niederungen der InteropServices absteigen. Dann legen wir gleich mal los:

PS> $BSTR=[System.Runtime.InteropServices.marshal]::SecureStringToBSTR($pw)
PS> $BSTR
39018744
PS> $pws = [System.Runtime.InteropServices.marshal]::PtrToStringAuto($BSTR)
PS> $pws
Hallo
PS> [System.Runtime.InteropServices.marshal]::ZeroFreeBSTR($BSTR)

Hier findet nun die ganze Show statt. Zuerst holt man sich mittels SecureStringToBSTR die ursprüngliche Eingabe und einen Pointer auf die Stelle, wo der String nun temporär abgelegt wird. Bei PtrToStringAuto wird der temporäre String ausgelesen, zurückgegeben und in $pws gespeichert. Mit ZeroFreeBSTR wird der temporäre String wieder freigegeben, bzw der temporäre Speicherplatz mit Nullen überschrieben (Secure!). Blöd nur, dass wir das Passwort nun in $pws haben, denn ab nun ist die Sache nicht mehr sicher!!

Hier noch der Link zu SecureStringToBSTR: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.securestringtobstr.aspx

Damit schließt sich der Kreis. Aber Moment, da geht noch mehr.

Passwörter in Dateien speichern
Es gibt nämlich die tollen Funktionen ConvertTo-SecureString und ConvertFrom-SecureString. Wer glaubt, damit ließe sich obige Prozedur abkürzen, der täuscht sich. Denn diese dienen nur dazu den SecureString zu serialisieren bzw. in einen Standard-String zu wandeln, um ihn z. B. in einer Datei speichern zu können.

Machen wir genau dies und speichern unseren String mal in einer Datei, dazu wandeln wir ihn zuerst, lassen ihn ausgeben und prüfen ob es ein String ist:

PS> $pwe = ConvertFrom-SecureString –SecureString $pw
PS> $pwe
01000000d08c9ddf0115d1118c7a00c04fc297eb01000000d13e0b3adb59f6469325c229ee5b0d520000000002000000000003660000c0000000100
00000d57efc5b5ccd1e52e71296ec9b91a3530000000004800000a0000000100000006b946cd8b1c877db8c8ae6f39f4932bd10000000858fb31747
0ef57f405d954a5857409a14000000e2154da0885013dc5dbf21097c61c1d429f1e8ce
PS> $pwe.GetType()

IsPublic IsSerial Name                                     BaseType
——– ——– —-                                     ——–
True     True     String                                   System.Object

PS> Set-Content –Value $pwe –Path pwenc.txt
PS> type .\pwenc.txt
01000000d08c9ddf0115d1118c7a00c04fc297eb01000000d13e0b3adb59f6469325c229ee5b0d520000000002000000000003660000c0000000100
00000d57efc5b5ccd1e52e71296ec9b91a3530000000004800000a0000000100000006b946cd8b1c877db8c8ae6f39f4932bd10000000858fb31747
0ef57f405d954a5857409a14000000e2154da0885013dc5dbf21097c61c1d429f1e8ce

Perfekt. Damit hat man eine saubere Möglichkeit gefunden Passwörter sicher abzuspeichern. Um sicher zu gehen, dass dem so ist, muss man die Sache natürlich auch wieder rückwärts machen können.

SecureString-Passwörter aus Dateien auslesen
Die Geschichte ist einfach erzählt

PS> $pw=Get-Content pwenc.txt | ConvertTo-SecureString

Damit kann man $pw wieder bei SecureStringToBSTR, wie oben gezeigt anwenden und bekommt das gespeicherte Passwort im Klartext zurück.

2 Antworten to “Spaß mit .Net SecureString und Powershell oder sicheres Speichern und Einlesen von Passwörtern”

  1. In den Niederungen von SecureString mittels Powershell « Das nie endende Chaos! Says:

    […] Aber doch der Versuch etwas Ordnung reinzubringen. « Spaß mit .Net SecureString und Powershell oder sicheres Speichern und Einlesen von Passw&… […]

  2. Wifi Netzwerksicherheitsschlüssel unter Windows per Powershell auslesen « Das nie endende Chaos! Says:

    […] Dann ist wichtig, wie man mit SecureStrings in Powershell umgeht: https://newyear2006.wordpress.com/2012/12/30/spa-mit-net-securestring-und-powershell-oder-sicheres-sp… […]

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s


%d Bloggern gefällt das: