Umgang mit Passwörtern unter Powershell

Dieser Beitrag basiert auf dem Artikel „Ganz vertraulich – Sicherer Umgang mit Passwörtern in der PowerShell“ von Thomas Franke. Der Artikel bzw. sein Blog gibt es leider nicht mehr. 🙁


Mit Hilfe der PowerShell werden heute Vorgänge/wiederkehrende Aufgaben vollständig automatisiert. Dies beschränkt sich nicht nur auf das Betriebssystem, sondern es ist problemlos möglich auch andere Produkte wie Hyper-V, Exchange Server, SQL-Server oder Office 365 von Microsoft zuzugreifen. Inzwischen bieten viele Hersteller wie VMWare, Citrix, etc. entsprechende Module für PowerShell an um auf die jeweilige Anwendung zugreifen zu können. Gerade beim Letzterem erfolgt oft die Authentifizierung durch eine separate Benutzerverwaltung in der Anwendung selbst und nicht durch das Active Directory. Aus Bequemlichkeit und Faulheit werden oft die notwendigen Benutzerdaten (Benutzername + Passwort) unverschlüsselt im PowerShell Skript hinterlegt.

Microsoft hat mit PowerShell ein Objekt „PSCredential“ implementiert. Das Objekt bzw. dessen Inhalt wird im XML-Format abgespeichert. Somit ist jeder Zeit möglich die Daten wieder einzulesen. Somit ist die Verwendung der abgespeicherten Zugangsdaten in einem anderen Benutzerkontexts und ohne erneute Eingabe des Passworts möglich.

PSCredential hat zwei Parameter – userName und password. Die Eigenschaft userName ist vom Typ String. Die Eingabe des Benutzernamens erfolgt somit als Zeichenkette und im Klartext. Die Eigenschaft password ist vom Typ SecureString. Der Vorteil von SecureString gegenüber allen anderen ist, dass dieser auf die Microsoft Data Protection API (DPAPI) zurückgreift. Für die Verschlüsselung des Passworts werden Schlüssel im Kontext des auszuführenden Benutzers erzeugt, welche im dessen Benutzerprofil abgespeichert werden. D.h. das Passwort ist durch das Benutzerkonto geschützt, welches den SecureString erzeugt hat. Erlangt ein anderer Benutzer Zugang zu den Dateien kann er diese ohne die Schlüssel nicht auslesen. Wird hingegen das entsprechende Benutzerkonto kompromittiert, können die Zugangsdaten problemlos entwendet bzw. verwendet werden.

Bei der Verwendung eines Domänen-Benutzers mit einem servergespeicherten Profil, können die abgespeicherten Zugangsdaten an allen Geräten in der Domäne genutzt werden. Grund dafür ist, dass die Schlüssel im Benutzerprofil abgelegt werden und durch die Synchronisation theoretisch überall verfügbar sind. Anders hingegen bei einem lokalen Benutzerkonto. Hier sind die abgespeicherten Zugangsdaten an das System gebunden. Ein Copy & Paste der Dateien auf ein anderes Gerät mit demselben Benutzernamen bringt absolut nichts. Das Skript/Modul legt seine Dateien standardmäßig unter %appdata%\PSCredentials ab. Dies kann natürlich im Skript jederzeit geändert werden.

Seit der Implementierung von PSCredential haben viele Entwickler und Administratoren verschiedene Lösungsansätze für das Handling entwickelt. Funktional erfüllen diese immer das Ziel, das sichere Verwahren der Zugangsdaten. Aber die Implementierung in eigenen Skripten stellt viele vor Probleme. Das Skript/Module von Thomas Franke hat folgenden Ansatz:

Die Funktion Get-PSCredential gibt das PSCredential Objekt des übergebenen Benutzernamens zurück. Gibt es für den Benutzer noch kein solches Objekt bzw. Datei erscheint automatisch der Dialog für die sichere Eingabe von Benutzername und Passwort. Es wird im Hintergrund automatisch das Objekt verschlüsselt und als XML in der Datei abgespeichert. Somit erfolgt das Anlegen, Ändern und Auslesen der Zugangsdaten in einem Vorgang – der Entwickler/Administrator muss sich keine weiteren Gedanken machen.

Die Funktion kann über sogenannte „Dot-sourcing“ in das PowerShell Skript eingebunden werden.

. .\include\Get-PSCredential.ps1

Der Pfad kann sowohl relativ als auch absolut sein. Wichtig den Punkt am Anfang muss unbedingt vorhanden sein.

Alternativ kann die Funktion auch als PowerShell-Modul auf dem System bereitgestellt werden. Dazu einfach das Verzeichnis „Modules\Get-PSCredential“ aus dem Archiv nach „C:\Windows\System32\WindowsPowerShell\v1.0\Modules“ kopieren. Dieser Vorgang muss mit einem Benutzer durchgeführt werden, welcher Mitglied der lokalen Gruppe „Administratoren“ ist. Der große Vorteil ist, dass die Funktion für alle PowerShell Skripte auf dem System zur Verfügung steht, ohne dies explizit einbinden zu müssen (siehe Dot-sourcing).

Der Aufruf/Abruf von Zugangsdaten für einen Benutzer in der PowerShell ist folgendermaßen möglich:

Get-PSCredential
Get-PSCredential benutzer01
Get-PSCredential server01\benutzer01
Get-PSCredential domaene01\benutzer02

Wird die Funktion ohne Angabe eines Benutzernamens aufgerufen, erscheint der Dialog für Benutzername und ggf. Passwort.

Falls der Abruf der Zugangsdaten im Zuge eines Befehls erfolgen soll, muss der Funktionsaufruf in Klammern gesetzt werden.

Test-Path -Path "C:\Temp" -Credential $(Get-PSCredential domaene01\benutzer02)

Selbstverständlich kann der Rückgabewert der Funktion auch in einer Variablen abgespeichert werden.

$zugangsdaten = Get-PSCredential domaene01\benutzer02

Wie bereits weiter oben beschrieben, werden die Dateien unter %appdata\PSCredentials abgelegt. Nicht mehr benötigte Dateien können einfach manuell gelöscht werden. Alternativ kurz und schmerzlos mit Hilfe der PowerShell.

# Löscht das vollständige Verzeichnis
Remove-Item "$env:AppData\PSCredentials" –Recurse

# Löscht die angegebene Datei
Remove-Item "$env:AppData\PSCredentials\computer01\benutzer01.PSCredential"

Damit können nun alle Powershell-Skripte nach und nach umgestellt werden und Zugangsdaten im Klartext gehören endlich der Vergangenheit an! 🙂

Entwickelt und getestet wurde die aktuelle Fassung unter PowerShell 2.0 und 3.0. Ich konnte bei meinen Tests für diesen Artikel unter PowerShell 4.0 und 5.1 keine Fehler feststellen. Das soll aber keine Garantie sein, dass es zu keinen Problemen kommen kann.

Das Skript/Module inkl. der Beispiele habe ich als Download bereitgestellt.