Manchmal muss man sich in PowerShell authentifizieren. Sei es dass mein eine bestimmte Aktion mit einem anderen Benutzer ausführt oder sich an einem anderen System anmeldet. Viele Anwendungen unterstützen dabei Windows integrierte Authentifizierung, dennoch gibt es häufig einen Grund wieso man gerade einen bestimmten Nutzer im Skript verwenden möchte/muss.
Da Skripte typischerweise hochgradig automatisiert sind, sollte daher der Benutzer und das Passwort hinterlegt sein. Dennoch ist es ein Unding das Passwort im Klartext zu speichern.
In diesem Blog erkläre ich wie man Benutzer und ein verschlüsseltes Passwort verwenden kann.
Voraussetzung
Ich gehe davon aus, dass unser Skript immer unter dem gleichen Benutzer ausgeführt wird. Hintergrund ist, dass wir einmal das Passwort eingeben, das speichert Windows im Crypto Subsystem ab. Erstellt wird zusätzlich ein Key, mit dem aber nur der Benutzer, der ursprünglich das Passwort eingegeben hat, Zugriff erhält. Im Skript speichern wir also nur diesen Key ab, der könnte grundsätzlich auch in einer Datei oder in der Registry abgelegt werden.
Status Quo
Das Skript könnte derzeit so aussehen, Benutzer und Kennwort sind im Klartext hinterlegt:
001 002 | $User = ‘contosoadministrator’ $PlainPassword= ‘password’ |
Passwort abfragen
Passwort neu eingeben
Fragen wir also einmal das Passwort ab:
001 | $SecurePassword = Read-Host -Prompt “Enter your password” -AsSecureString |
Über den Parameter “-AsSecureString” wird es gleich verschlüsselt
Bestehendes Passwort konvertieren (alternativ)
001 002 003 | $User = ‘contosoadministrator’ $PlainPassword = ‘password’ $SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText -Force |
Passwort verschlüsselt speichern
Jetzt kommt der interessante Teil. Um das gerade eben abgefragte Passwort für den aktuellen Benutzer sicher abzuspeichern, führt man folgenden Befehl aus:
001 002 003 004 005 006 | $SecureStringAsPlainText = $SecurePassword | ConvertFrom-SecureStringPS C:> $SecureStringAsPlainText 01000000d08c9ddf0115d1118c7a00c04fc297eb0100000083b2990fabc74f43ab3fcca07023b4690000000002000000000003660000c000000010000000cef8fc0a4db3db731e96841fb425fe3400000 00004800000a000000010000000af8b026b6b653805fdcf0a323e44415e18000000aa95bb9d4e7dd82e18513727b2c4a64924036dfe19a57cfe140000002312b15b12fcb18fd294d1ac711f70cf15d6c0 b3 |
Der Inhalt der Variable $SecureStringAsPlainText enthält den Key (01000000d08c9ddf0115d1118c7a0…), den man anstatt dem Klartext Kennwort verwenden kann. Dabei kann nur der Benutzer, der zuvor das Kennwort eingegeben hat, das eigentliche Passwort wieder abrufen, d.h. habe ich lediglich Kenntnis von dem o.g. Key, kann ich damit nichts weiter anfangen. Wird das Kennwort geändert, muss der Vorgang von Anfang an durchlaufen werden.
Verschlüsseltes Passwort abrufen
In meinem Skript kann ich jetzt den Key anstatt dem Kennwort abspeichern:
001 002 003 | $User = ‘contosoadministrator’ $SecureStringAsPlainText = ‘01000000d08c9ddf0115d1118c7a00c04fc297eb0100000083b2990fabc74f43ab3fcca07023b4690000000002000000000003660000c000000010000000cef8fc0a4db3db731e96841fb425fe340000000004800000a000000010000000af8b026b6b653805fdcf0a323e44415e18000000aa95bb9d4e7dd82e18513727b2c4a64924036dfe19a57cfe140000002312b15b12fcb18fd294d1ac711f70cf15d6c0b3’ $SecureString = $SecureStringAsPlainText | ConvertTo-SecureString |
Die Variable $SecureString enthält anschließend das Kennwort in verschlüsselter Form und wird an den Stellen im Skript verwendet die nach dem Kennwort verlangen.
Beispiel
Einmaliges Speichern
In den nächsten zwei Zeilen Frage ich das Kennwort ab und speichere es in die Variable $SecureStringAsPlainText, diese wird anschließend ausgegeben:
001 002 003 | $SecurePassword = Read-Host -Prompt “Enter your password” -AsSecureString $SecureStringAsPlainText = $SecurePassword | ConvertFrom-SecureString $SecureStringAsPlainText |
Den Inhalt der Variable übernehme ich nun ins nächste Skript. Zu berücksichtigen ist dabei, dass ggf. Zeilenumbrüche die durch die vorherige Ausgabe entstanden sind, zu entfernen sind.
Verwendung im Skript
Das eigentlich Skript könnte wie folgt aussehen.
001 002 003 004 005 006 007 008 009 010 011 | $User = ‘contosoadministrator’ $SecureStringAsPlainText = ‘01000000d08c9ddf0115d1118c7a00c04fc297eb0100000083b2990fabc74f43ab3fcca07023b4690000000002000000000003660000c000000010000000cef8fc0a4db3db731e96841fb425fe340000000004800000a000000010000000af8b026b6b653805fdcf0a323e44415e18000000aa95bb9d4e7dd82e18513727b2c4a64924036dfe19a57cfe140000002312b15b12fcb18fd294d1ac711f70cf15d6c0b3’ $SecureString = $SecureStringAsPlainText | ConvertTo-SecureString#Beispiel 1 (Anmeldung an DocAve PowerShell) Login-DAManager -ControlHost lab-mgr -ControlPort 14000 -Username $User -Password $SecureString #Beispiel 2 (Erstellt ein Web-Client Objekt unter dem Benutzer) |
Referenz
- Working with Passwords, Secure Strings and Credentials in Windows PowerShell: http://social.technet.microsoft.com/wiki/contents/articles/4546.working-with-passwords-secure-strings-and-credentials-in-windows-powershell.aspx
Mit:
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
$pass = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
lässt sich das Kennwort wieder zurück in Klartext konvertieren, damit ist das leider keine sichere Methode.
Siehe auch hier:
https://escde.net/passwoerter-sicher-speichern-die-powershell-dein-freund-und-helfer/
Ich hatte gehofft aus dem Kennwort eine Art Hash zu generieren, welche aber nicht mehr Reverse in Klartext zu konvertieren geht.
Danke für den Hinweis! Ja damit ist es dann leider nicht mehr sicher. Das Umwandeln des Kennwortes zurück in Klartext funktioniert vermutlich aber auch nur für den Benutzer der zuvor den Secure String erzeugt hat. Ich habe für das Skript z.B. einen Service Account eingerichtet und anschließend den Secure String erzeugt. Ein anderer Benutzer konnte auf den Secure String nicht mehr zugreifen. Damit ist es zumindestens etwas besser geschützt als das Kennwort im Klartext zu hinterlegen.