Zugangsdaten in PowerShell sicher handhaben — Klartext-Passwörter aus Ihren Skripten verbannen

· · PowerShell, Windows, Sicherheit, Zugangsdaten, DPAPI, Automatisierung, Betriebsoptimierung, Skript

Wenn wir bei einer Fehlersuche oder einer Skript-Durchsicht die PowerShell-Skripte eines Kunden ansehen, stoßen wir mit bemerkenswerter Regelmäßigkeit auf eines: $password = "P@ssw0rd123". Eine Verbindung zu einem Dateiserver, zur Datenbank hinter dem Kernsystem, der E-Mail-Versand, ein Web-API-Schlüssel. Es funktionierte, das hatte Priorität, und das Passwort blieb am Ende im Klartext im Skript eingebettet – jahrelang, in einem Freigabeordner oder einem Git-Repository.

Das Unangenehme daran: Wer es geschrieben hat, weiß meist schon, dass das nicht gut ist. Aber was ist stattdessen richtig? SecureString, Export-Clixml, SecretManagement, Credential Manager, Azure Key Vault – die Optionen häufen sich, und es ist schwer zu erkennen, was jede davon tatsächlich abdeckt und wo sie an ihre Grenzen stößt. Dazu kommt der Satz „SecureString wird nicht mehr empfohlen“, und es wird unklar, was noch gilt. Diese Verwirrung hat Gründe, und sobald man sie offenlegt, wird der Weg klar.

Dieser Artikel richtet sich an interne IT- und Betriebsmitarbeiter, die interne Betriebsskripte und geplante Batch-Jobs betreuen. Er beginnt damit, was an Klartext-Passwörtern tatsächlich falsch ist, ordnet PowerShells Werkzeuge für Zugangsdaten Mechanismus für Mechanismus ein und fasst die realistischen Antworten auf „was tue ich bei unbeaufsichtigten Läufen?“ in einer Entscheidungstabelle zusammen. Als Grundlage dient PowerShell 7.x, mit Hinweisen für Umgebungen, die noch Windows PowerShell 5.1 einsetzen.

1. Die wichtigsten Punkte vorab

  • Das Problem eines Klartext-Passworts ist, dass das Leck in dem Moment feststeht, in dem die Datei sichtbar wird. Git-Historie, Freigabeordner, Backups, Protokolle – jeder Pfad, über den sich Kopien des Skripts vermehren, ist ein Leckpfad. Code zu schreiben, der Klartext in eine SecureString umwandelt (ConvertTo-SecureString -AsPlainText), löst nichts, wenn der ursprüngliche Klartext weiterhin im Skript oder im Protokoll steht.12
  • Für interaktiv genutzte Skripte ist das Grundmuster, ein PSCredential von Get-Credential zu beziehen. Das Passwort wird nie auf dem Bildschirm angezeigt und lässt sich als Objekt an den -Credential-Parameter jedes Befehls übergeben.3
  • Die offizielle .NET-Dokumentation stellt unmissverständlich fest, dass SecureString für neue Entwicklungen nicht empfohlen wird. Die Verschlüsselung findet nur unter Windows statt; auf Nicht-Windows-Plattformen ist das Innere nicht verschlüsselt. PowerShell hält aus Kompatibilitätsgründen dennoch an SecureString fest, sodass Sie auf absehbare Zeit mit ihm als Standard-Übergabeformat leben werden. Vertrauen Sie ihm nicht zu sehr, und bauen Sie keinen eigenen Schutzmechanismus darauf auf.45
  • Für unbeaufsichtigte Läufe ist das Speichern von Zugangsdaten in einer Datei mit Export-Clixml und DPAPI-Verschlüsselung die minimale praxistaugliche Antwort. Sie lässt sich nur von dem Benutzer entschlüsseln, der sie gespeichert hat, und nur auf dem Rechner, auf dem sie gespeichert wurde, sodass die Datei allein bei einem Leck nutzlos ist. Die Kehrseite: Sie muss vom Ausführungskonto der Aufgabenplanung selbst gespeichert werden. Auf Nicht-Windows-Plattformen wird nichts verschlüsselt.6
  • Sobald Sie mehrere Geheimnisse verwalten, zentralisieren Sie sie mit SecretManagement plus SecretStore. Die einheitliche Set-Secret-/Get-Secret-Schnittstelle erlaubt es, das Speicher-Backend von einem lokalen SecretStore bis hin zu Azure Key Vault auszutauschen. Für unbeaufsichtigte Läufe bleibt der Umgang mit dem Tresor-Passwort jedoch ein offenes Problem.78
  • Das Allererste, was Sie erwägen sollten, ist ein Design, das überhaupt keine Zugangsdaten besitzt. Geben Sie dem Ausführungskonto selbst (einem Domänenkonto oder einem gMSA) Rechte auf dem Ziel, und das Passwort verschwindet aus dem Skript. Mit einem gMSA wird die Passwortverwaltung selbst an das Betriebssystem übergeben.910
  • Bauen Sie das Durchsickern in Protokolle und Transkripte in Ihr Design ein. Die offizielle Dokumentation warnt, dass das Aktivieren der Skriptblock-Protokollierung sensible Daten, einschließlich in Skripten verwendeter Zugangsdaten, ins Ereignisprotokoll schreiben kann. Sobald Sie ein Klartext-Passwort auf einer Befehlszeile eintippen, gehen Sie davon aus, dass es aufgezeichnet wurde.11

2. Was an Klartext falsch ist ── so viele Leckpfade wie Kopien

Schauen wir uns zunächst das typische Muster an, das umgeschrieben werden muss.

# Anti-Muster: Beide Zeilen sind gleichermaßen problematisch, weil der Klartext im Skript bleibt
$password = "P@ssw0rd123"

# Die Umwandlung in eine SecureString hilft nicht — der ursprüngliche Klartext steht weiterhin in Zeile 1.
# PSScriptAnalyzer meldet diese Verwendung von -AsPlainText als Fehler
$secure = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential('svc-transfer', $secure)

Ein Passwort fest zu verdrahten ist nicht nur deshalb gefährlich, weil „ein böswilliger Eindringling es lesen könnte“. Aufgrund dessen, was ein Skript als Artefakt ist, vermehren sich Kopien allein schon durch den legitimen Tagesbetrieb.

Woher Kopien stammen Was passiert
Git-Repository Ein einmal committetes Passwort bleibt für immer in der Historie erhalten. Die Datei nachträglich zu korrigieren entfernt es nicht aus der Historie
Freigabeordner Breitet sich auf jeden mit Lesezugriff aus, dazu Backups und Generationskopien
E-Mail und Chat Sobald Sie es mit „hier, nutze dieses Skript“ anhängen, ist es außerhalb Ihrer Kontrolle
Ereignisprotokoll Bei aktivierter Skriptblock-Protokollierung wird der Inhalt ausgeführten Codes im Protokoll aufgezeichnet11
Transkripte Start-Transcript oder eine unternehmensweite Transkriptionsrichtlinie zeichnet auf, was über den Bildschirm ging11

Diese Struktur bedeutet: Sie können das Problem des Klartext-Passworts nicht lösen, indem Sie „dafür sorgen, dass niemand die Datei sehen kann“. So streng Sie die Zugriffsrechte auch einschränken – Git-Historie und Backups lassen sich damit nicht verschließen. Die eigentliche Antwort ist, das Passwort aus dem Skript zu entfernen und in verschlüsselten Speicher zu verlagern. Es ist dasselbe Argument, das wir zu Konfigurationsdateien von .NET-Anwendungen in „Geheimnisse in Windows-Apps speichern - Klartext-Konfiguration mit DPAPI vermeiden“ gemacht haben, und das Prinzip ändert sich bei PowerShell nicht.

Beachten Sie: Klartext an Ort und Stelle in eine SecureString umzuwandeln – ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force – ist keine Lösung. PSScriptAnalyzer (das offizielle statische Analysewerkzeug) meldet diesen Stil als Fehler (Severity: Error). Er umgeht die Verschlüsselung und legt Klartext im Speicher offen, und der ursprüngliche Klartext lebt weiterhin im Skript.1

3. Was die Werkzeuge wirklich sind ── PSCredential, SecureString und ihre Grenzen

3.1. Get-Credential und PSCredential

Für ein interaktives Skript ist dies bereits das gesamte Grundmuster.

# Nach Benutzername und Passwort fragen und sie als PSCredential-Objekt entgegennehmen
$cred = Get-Credential -Message 'Konto für die Verbindung zur Kerndatenbank eingeben'

# Lässt sich direkt an jeden Befehl mit einem -Credential-Parameter übergeben
Invoke-Command -ComputerName APPSV01 -Credential $cred -ScriptBlock { hostname }

Get-Credential fragt nach Benutzername und Passwort und gibt ein PSCredential-Objekt zurück. Unter Windows PowerShell 5.1 ist das ein Dialogfeld, ab PowerShell 6 eine Konsoleneingabe.3 Das Passwort wird innerhalb des PSCredential als SecureString gehalten und nie auf dem Bildschirm angezeigt. Wo akzeptabel ist, dass „eine Person es zur Laufzeit eintippt“, brauchen Sie nichts Komplizierteres als dieses Vorgehen.

Schreiben Sie eigene Funktionen, gestalten Sie sie so, dass sie einen [PSCredential]-Parameter -Credential entgegennehmen, statt ein Passwort als [string]. Der offizielle Artikel „Add Credential support to PowerShell functions“ beschreibt, wie das geschrieben wird.2

3.2. Was SecureString wirklich ist ── wie das „nicht empfohlen“-Urteil zu lesen ist

Es gibt drei Dinge, die Sie über SecureString wissen sollten.

  • Die offizielle .NET-Position lautet „nicht in neuen Entwicklungen verwenden“. Das interne Array wird nur unter Windows verschlüsselt; auf Nicht-Windows-Plattformen ist der interne Speicher nicht verschlüsselt. Und da es im Moment der Nutzung ohnehin in eine Klartextdarstellung umgewandelt werden muss, erreicht es im Kern nur eine Verkürzung des Expositionsfensters. Die empfohlene Alternative ist „ein undurchsichtiger Verweis auf ein außerhalb des Prozesses gespeichertes Credential“ – also ein Anmeldeinformationsspeicher des Betriebssystems oder etwas wie Key Vault.4
  • PowerShells Standardausstattung setzt trotzdem SecureString voraus. PowerShell unterstützt SecureString aus Kompatibilitätsgründen weiterhin, und es wird nach wie vor genutzt, um versehentliche Offenlegung in der Konsole oder in Protokollen zu vermeiden. Die Einordnung lautet „sicherer als eine Klartext-Zeichenfolge“.5
  • Es lässt sich trivial zurück in Klartext umwandeln. Unter PowerShell 7 liefert ConvertFrom-SecureString -AsPlainText in einem Schritt Klartext.12 Es ist deutlich zutreffender, SecureString als „einen Umschlag, damit man es nicht versehentlich sieht“ zu betrachten als als „einen unlesbaren Tresor“.

Die praktische Schlussfolgerung lautet: Lassen Sie sich von SecureString nicht dazu verleiten, eine eigene komplizierte Verschlüsselung zu bauen. Verwenden Sie es als das Format, das PowerShells Werkzeuge (Get-Credential, SecretManagement) verlangen, und legen Sie den eigentlichen Schutz in prozessexterne Mechanismen wie DPAPI oder einen Tresor.

4. Der Standard für unbeaufsichtigte Läufe ── Export-Clixml, DPAPI und die Mauer „derselbe Benutzer, derselbe Rechner“

Ein unbeaufsichtigtes Skript, das über die Aufgabenplanung läuft, kann schlecht einen Menschen mit Get-Credential fragen. Die minimale praxistaugliche Antwort ist eine mit Export-Clixml erstellte Zugangsdaten-Datei.

# --- Vorbereitung (nur einmal, ausgeführt als Ausführungskonto der Aufgabe) ---
$cred = Get-Credential -Message 'Integrationskonto'
$cred | Export-Clixml -Path 'D:\Jobs\secrets\transfer.credential'

# --- Produktivskript (unbeaufsichtigt) ---
$cred = Import-Clixml -Path 'D:\Jobs\secrets\transfer.credential'
# Beispiel: Verbindung zu einer Freigabe, die andere Zugangsdaten braucht, oder Remote-Ausführung
Invoke-Command -ComputerName FILESV01 -Credential $cred -ScriptBlock { Get-ChildItem D:\Export }

Export-Clixml speichert das Credential-Objekt mit Windows-DPAPI (der Data Protection API) verschlüsselt. Es lässt sich nur entschlüsseln, wenn das Benutzerkonto, das es gespeichert hat, es auf dem Computer öffnet, auf dem es gespeichert wurde. Die exportierte Datei lässt sich weder auf einem anderen Rechner noch von einem anderen Benutzer verwenden.613 Genau die Eigenschaft, dass eine gestohlene Datei sich nicht öffnen lässt, macht sie als Speicher für unbeaufsichtigte Läufe praktisch.

Allerdings ist „nur derselbe Benutzer, derselbe Rechner“ gleichzeitig Schutz und betriebliche Falle.

  • Es muss zum Ausführungskonto der Aufgabenplanung passen. Eine .credential-Datei, die Sie unter Ihrem eigenen Konto erstellt haben, lässt sich in dem Moment nicht mehr entschlüsseln, in dem die Aufgabe als Dienstkonto läuft. Führen Sie den Vorbereitungsschritt immer als das Ausführungskonto der Aufgabe durch (PowerShell unter diesem Konto starten und die Datei dort speichern). Ausführungskonten und Anmeldearten für Aufgaben werden ausführlich in „Wenn Aufgaben der Aufgabenplanung nicht laufen oder mit 0x1 enden ── die Ursache isolieren und für zuverlässigen Betrieb gestalten“ behandelt.
  • Ein Serverwechsel oder eine Kontoänderung bedeutet immer, sie neu zu erstellen. Das ist eine klassische Ursache für „es funktionierte nach der Migration nicht mehr“, also skripten Sie den Vorbereitungsschritt und bewahren Sie ihn im Repository auf (natürlich ohne das Passwort selbst).
  • Jeder Prozess, der unter demselben Konto läuft, kann es entschlüsseln. DPAPI steht jedem Code offen, der unter diesem Benutzer läuft, sodass die Umgebungshygiene weiterhin wichtig bleibt: Platzieren Sie keine unnötige Software unter dem Ausführungskonto, und halten Sie dessen Berechtigungen minimal.
  • Auf Nicht-Windows-Plattformen wird nichts verschlüsselt. Die offizielle Dokumentation hält ausdrücklich fest, dass unter macOS und Linux die Ausgabe praktisch Klartext ist (ein Unicode-Zeichenarray).6

Es gibt auch den Ansatz, -Key an ConvertFrom-SecureString für eine AES-Verschlüsselung zu übergeben, aber das verschiebt tendenziell nur dasselbe Problem einen Schritt weiter: Jetzt müssen Sie die Schlüsseldatei schützen.12 Sobald Sie Rechnergrenzen überschreiten müssen, wechseln Sie zum Tresor im nächsten Abschnitt oder zum „nichts besitzen“-Design in Kapitel 6.

5. Wenn sich Geheimnisse häufen ── SecretManagement und SecretStore

Mit wachsender Zahl an Zielen und der Vermischung mit API-Schlüsseln und Tokens stoßen verstreute .credential-Dateien an ihre Verwaltungsgrenze. Hier kommt das Modul SecretManagement ins Spiel. Es ist eine einheitliche Schnittstelle zu Geheimnisspeichern (Tresoren), wobei die tatsächliche Speicherung von Erweiterungs-Tresoren übernommen wird. Neben dem lokal gespeicherten SecretStore (von Microsoft) lassen sich Erweiterungs-Tresore wie Azure Key Vault und KeePass über dieselben Befehle ansteuern.714

# Nur beim ersten Mal: Module installieren und einen Tresor registrieren
Install-Module Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore
Register-SecretVault -Name SecretStore -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault

# Ein Geheimnis registrieren (beim ersten Zugriff werden Sie gebeten, das Tresor-Passwort festzulegen)
Set-Secret -Name TransferJobCred -Secret (Get-Credential)

# Im Skript: per Namen abrufen. Diese Zeile ändert sich nicht, wenn sich das Backend ändert
$cred = Get-Secret -Name TransferJobCred

Neben PSCredential und SecureString können Geheimniswerte auch Zeichenfolgen, Byte-Arrays oder Hashtabellen sein, und beim ersten Zugriff werden Sie gebeten, ein Passwort festzulegen, das den Tresor selbst schützt.15 Der Vorteil ist, dass das Wissen darüber, „wo es gespeichert ist“, aus dem Skript verschwindet. SecretStore auf einem Entwicklungsrechner und Azure Key Vault im Produktivbetrieb zu nutzen (das Modul Az.KeyVault stellt den Erweiterungs-Tresor bereit) wird dann zu einer reinen Änderung der Register-SecretVault-Konfiguration.167

Es gibt jedoch drei Dinge zu beachten, wenn Sie das in die unbeaufsichtigte Ausführung übernehmen.

  • SecretStore fragt standardmäßig interaktiv nach dem Tresor-Passwort. Setzen Sie es unverändert in die Aufgabenplanung, bleibt es an der Eingabeaufforderung hängen. Für unbeaufsichtigte Läufe beschreibt die offizielle Dokumentation, Interaction auf None zu setzen und das Tresor-Passwort – abgelegt in einer mit DPAPI geschützten, mit Export-Clixml erzeugten Datei – über Unlock-SecretStore zu übergeben.8 Mit anderen Worten: Der Tresorschlüssel wird am Ende doch wieder von DPAPI geschützt und erbt damit dieselbe Einschränkung „derselbe Benutzer, derselbe Rechner“ aus dem vorherigen Abschnitt. Es ist auch möglich, die Passwortanforderung ganz zu deaktivieren (Authentication None), aber dann wird der Schlüssel allein durch Dateisystemberechtigungen geschützt, was dort, wo starker Schutz erforderlich ist, nicht empfohlen wird.17
  • Es funktioniert nicht mit verwalteten Konten wie gMSAs. SecretManagement hängt vom Benutzerprofil ($env:LOCALAPPDATA) und von DPAPI ab und ist dokumentiert als derzeit nicht unterstützt für verwaltete Windows-Konten, die kein Profil besitzen.14 Möchten Sie, dass ein unter einem gMSA laufender Job Geheimnisse besitzt, steht Ihnen diese Kombination nicht zur Verfügung (und ohnehin lässt ein gMSA meist ein Design zu, das ganz ohne Geheimnisse auskommt – siehe den nächsten Abschnitt).
  • SecretManagement und SecretStore gelten als funktional abgeschlossen, die aktive Entwicklung neuer Funktionen ist beendet. Sicherheitskorrekturen und kritische Fehlerbehebungen laufen weiter, sodass ihre Nutzung unproblematisch ist; Microsoft selbst weist jedoch darauf hin, dass sich „das Wesen von Geheimnissen in Richtung passwortloser und föderierter Zugangsdaten verschiebt“, sodass Sie bei einem langfristigen Design auch die Authentifizierungsmethode selbst im Blick behalten sollten (verwaltete Identitäten von Entra ID und Ähnliches).7

Es gibt außerdem Community-Erweiterungen, die den Windows Credential Manager als Tresor nutzen.7 Wie wir bereits in „Stolperfallen bei Netzlaufwerken und UNC-Pfaden ── mit Dateiservern (Freigabeordnern) aus einer Business-Anwendung heraus arbeiten“ angesprochen haben – etwa wie mit cmdkey registrierte Zugangsdaten automatisch genutzt werden –, verhält sich der Credential Manager auch hier gleich: Er ist an das jeweilige Benutzerprofil gebunden.

6. Die höchste Priorität ── überhaupt keine Zugangsdaten besitzen

Wir haben bisher „wie speichere ich es sicher“ aufgebaut, doch die sauberste Antwort für unbeaufsichtigte Ausführung ist eigentlich keine raffinierte Speichertechnik. Es ist die Notwendigkeit zu beseitigen, dass das Skript überhaupt ein Credential besitzen muss.

Windows-Aufgaben und -Dienste laufen im Sicherheitskontext ihres Ausführungskontos. Ist das Ziel durch Windows-Authentifizierung geschützt – eine ACL auf einem Freigabeordner, SQL-Server-Windows-Authentifizierung, integrierte Windows-Authentifizierung auf einer internen API –, dann bedeutet die Vergabe von Rechten am Ziel an das Ausführungskonto selbst, dass im Skript nie ein Passwort oder ein Get-Secret auftaucht. Kerberos übernimmt die Authentifizierung unter der Identität des Ausführungskontos für Sie.

Was das ermöglicht, ist das gMSA (group Managed Service Account). Ein gMSA ist ein verwaltetes Domänenkonto, bei dem die Passwortverwaltung vom Windows-Betriebssystem übernommen wird.9 Das Passwort ist ein 240 Byte langer Zufallswert, den das Betriebssystem automatisch alle 30 Tage rotiert, sodass ihn niemand kennt und nichts wegen Ablaufs kaputtgeht.10 Und gMSAs lassen sich nicht nur für Windows-Dienste, sondern auch für Aufgaben der Aufgabenplanung nutzen.18

Als Rangfolge dargestellt, ergibt sich Folgendes.

  1. Lässt sich am Ziel Windows-Authentifizierung nutzen, entfernen Sie das Credential, indem Sie dem Ausführungskonto (einem Domänenkonto oder einem gMSA) Rechte gewähren. Bei unbeaufsichtigten Jobs in einer Domänenumgebung ist das der erste Ansatz.9
  2. Speichern Sie nur dort ein Geheimnis, wo das nicht möglich ist (eine per SQL-Authentifizierung geschützte Datenbank, ein API-Schlüssel, ein NAS in einer Arbeitsgruppe und Ähnliches). Bei ein oder zwei Geheimnissen: Export-Clixml mit DPAPI. Bei mehreren: SecretManagement plus SecretStore.68
  3. Für Verbindungen zu Cloud-Ressourcen bevorzugen Sie verwaltete Identitäten oder föderierte Zugangsdaten gegenüber dem Speichern von Schlüsseln. Müssen Sie sie doch speichern, legen Sie sie in einem dedizierten Tresor wie Azure Key Vault ab.167

Wo Sie Zugangsdaten explizit an einen entfernten Server übergeben, um dort Arbeit auszuführen, kommt zusätzlich der Authentifizierungsmechanismus von PowerShell Remoting ins Spiel. Siehe „Eine Einführung in PowerShell Remoting (WinRM) ── mehrere Windows-Rechner auf einmal verwalten“, das parallel zu diesem Artikel veröffentlicht wurde.

7. Geheimnisse aus Protokollen und Transkripten heraushalten

Die Speicherung abzusichern bringt nichts, wenn das Geheimnis stattdessen über den Laufzeitmitschnitt durchsickert. Zwei Punkte sind zu beachten.

Erstens verfügt PowerShell über mehrere Funktionen, die aufzeichnen, was ausgeführt wurde, und diese können durch Unternehmensrichtlinien aktiviert sein. Ist die Skriptblock-Protokollierung aktiviert, wird der Inhalt jedes verarbeiteten Skriptblocks im Ereignisprotokoll aufgezeichnet. Die offizielle Dokumentation warnt ausdrücklich, dass „das Aktivieren der Skriptprotokollierung sensible Daten, einschließlich in Skripten verwendeter Zugangsdaten, ins Ereignisprotokoll schreiben kann“, und empfiehlt, es für alles über reine Diagnose hinaus mit Protected Event Logging zu kombinieren.11 Dasselbe gilt für Transkription: Was über die Konsole ging, bleibt in einer Datei erhalten.

Zweitens, und daraus folgend: Seien Sie konsequent dabei, Code so zu schreiben, dass Klartext niemals über eine Befehlszeile oder den Bildschirm läuft.

  • Gestalten Sie Skripte nicht so, dass sie ein Passwort als Argument entgegennehmen. Sobald Sie .\job.ps1 -Password "P@ssw0rd" eintippen, gehen Sie davon aus, dass es in Protokollen, der Historie und der Prozessliste steht. Müssen Sie es entgegennehmen, nehmen Sie ein PSCredential oder eine SecureString entgegen.2
# Hausstil für den Einstiegspunkt Ihres eigenen Skripts: das Passwort nicht als [string] entgegennehmen
[CmdletBinding()]
param(
    # Zugangsdaten als PSCredential entgegennehmen. Bei Weglassen interaktiv mit
    # Get-Credential beziehen; für unbeaufsichtigte Läufe das Ergebnis von Import-Clixml oder Get-Secret übergeben
    [Parameter(Mandatory)]
    [System.Management.Automation.PSCredential]$Credential
)
# Niemals Variablen mit Geheimnissen an die Debug-Ausgabe weitergeben. Der Benutzername ist die Grenze
Write-Verbose "Verbinde als: $($Credential.UserName)"
  • Geben Sie Variablen mit Geheimnissen nicht mit Write-Host oder Write-Verbose aus. Diese „nur vorübergehende“ Ausgabe, die Sie bei der Fehlersuche hinzugefügt haben, wird in einem Transkript dauerhaft festgehalten.
  • Achten Sie darauf, dass Geheimnisse nicht in Ausnahmemeldungen durchsickern. Bauen Sie eine Verbindungszeichenfolge auf und lösen dann eine Ausnahme aus, wird der abgefangene Fehler tendenziell mit der Verbindungszeichenfolge darin protokolliert. Für das Design dessen, was Ihre Fehlerbehandlung tatsächlich ins Protokoll schreibt, siehe auch „Fehlerbehandlung und Wiederholungsdesign in PowerShell ── von der try/catch-Falle bis zu Exit-Codes und Best Practices für Wiederholungen“.

8. Praktische Faustregeln (Entscheidungstabelle)

Situation Empfehlung Wie zu entscheiden ist
Eine Person führt es direkt vor Ort aus Get-Credential Es gar nicht zu speichern ist die sicherste Option. Ein PSCredential entgegennehmen und an -Credential übergeben3
Unbeaufsichtigter Job innerhalb einer Domäne (Ziel nutzt Windows-Authentifizierung) Rechte an das Ausführungskonto / einen gMSA vergeben Ein Design ohne Zugangsdaten kommt zuerst. gMSAs funktionieren auch mit der Aufgabenplanung918
Unbeaufsichtigter Job mit ein oder zwei Geheimnissen Export-Clixml mit DPAPI Als das eigene Ausführungskonto der Aufgabe speichern. Bei Rechner- oder Kontowechsel neu erstellen6
Unbeaufsichtigter Job mit vielen Geheimnissen oder einem Backend, das später eventuell gewechselt werden soll SecretManagement + SecretStore Das Tresor-Passwort aus DPAPI-geschütztem Speicher über Unlock-SecretStore bereitstellen. Nicht mit gMSAs nutzbar814
Geheimnisse, die über Cloud-Ressourcen oder mehrere Server hinweg geteilt werden Azure Key Vault (+ SecretManagement) Rechnerlokales DPAPI lässt sich nicht teilen. Einsetzen, sobald zentrale Verwaltung und Auditierung nötig werden16
Klartext im Skript plus ConvertTo-SecureString Umschreiben Eine schlechte Form, die PSScriptAnalyzer als Fehler meldet. Zu einer der obigen Optionen wechseln1

Im Zweifel arbeiten Sie die Reihenfolge „nicht besitzen > rechnergebunden besitzen (DPAPI) > in einem Tresor besitzen“ von oben nach unten ab.

9. Zusammenfassung

  • Das grundlegende Problem von Klartext-Passwörtern ist, dass jeder Pfad, über den sich Kopien vermehren – Git-Historie, Freigabeordner, Protokolle –, ein Leckpfad ist. Zugriffsrechteverwaltung allein kann Sie nicht schützen.
  • Für interaktive Ausführung genügen Get-Credential und PSCredential. Schreiben Sie keine eigenen Funktionen, die ein Passwort als [string] entgegennehmen.
  • SecureString wird laut offizieller .NET-Anleitung für neue Entwicklungen nicht empfohlen, überlebt aber als PowerShells Standard-Übergabeformat. Akzeptieren Sie es als „einen Umschlag, der versehentliche Offenlegung verhindert“, und legen Sie den eigentlichen Schutz in externe Mechanismen.
  • Export-Clixml mit DPAPI gilt „nur für denselben Benutzer, denselben Rechner“. Der entscheidende Punkt: Die gespeicherte Datei muss vom Ausführungskonto der Aufgabenplanung selbst erzeugt werden, und auf Nicht-Windows-Plattformen wird nichts verschlüsselt.
  • SecretManagement plus SecretStore ist wirksam, um mehrere Geheimnisse zu zentralisieren, doch unbeaufsichtigte Läufe brauchen ein Design zur Bereitstellung des Tresor-Passworts, und es lässt sich nicht mit gMSAs nutzen. Berücksichtigen Sie bei der Einführung, dass es als funktional abgeschlossen gilt.
  • Höchste Priorität hat ein Design ohne Zugangsdaten. Prüfen Sie zuerst, ob Windows-Authentifizierung plus an das Ausführungskonto vergebene Rechte (ein gMSA) Passwörter vollständig aus dem Skript entfernen kann.
  • Skriptblock-Protokolle und Transkripte können sensible Daten festhalten. Seien Sie konsequent dabei, Code so zu schreiben, dass Klartext niemals über eine Befehlszeile, den Bildschirm oder eine Ausnahmemeldung läuft.

Verwandte Artikel

Verwandte Beratungsbereiche

Die KomuraSoft LLC übernimmt die Prüfung von in Betriebsskripten und geplanten Batch-Jobs eingebetteten Zugangsdaten samt Migration in sicheren Speicher, das Design von Ausführungskonten einschließlich gMSAs sowie Sicherheits-Reviews unbeaufsichtigter Jobs. Klartext-Passwörter aufzuräumen, die nach dem Motto „es funktioniert, also nicht anfassen“ liegen geblieben sind, ist ein guter Ausgangspunkt.

  1. Microsoft Learn, AvoidUsingConvertToSecureStringWithPlainText. Dazu, dass PSScriptAnalyzer die Verwendung von ConvertTo-SecureString -AsPlainText als Fehler meldet (Severity: Error), dazu, dass dies die Verschlüsselung umgeht und sensible Informationen im Speicher als Klartext offenlegt, sowie dazu, dass Read-Host -AsSecureString und das SecretStore-Modul als Alternativen genannt werden.  2 3

  2. Microsoft Learn, Add Credential support to PowerShell functions. Dazu, wie man eigenen Funktionen einen PSCredential-Parameter hinzufügt, und dazu, warum die Verwendung von ConvertTo-SecureString -AsPlainText eine Warnung auslöst, weil Klartext-Passwörter am Ende in diversen Protokollen aufgezeichnet werden.  2 3

  3. Microsoft Learn, Get-Credential. Dazu, wie Get-Credential nach Benutzername und Passwort fragt und ein PSCredential-Objekt zurückgibt, dazu, dass Windows PowerShell 5.1 ein Dialogfeld nutzt, während PowerShell 6 und höher in der Konsole abfragen, sowie dazu, wie das Ergebnis an Befehle mit einem -Credential-Parameter übergeben wird.  2 3

  4. Microsoft Learn, SecureString Class. Zur Empfehlung, SecureString nicht in neuen .NET-(Core-)Entwicklungen zu verwenden, dazu, dass die Verschlüsselung nur unter Windows stattfindet und der interne Speicher auf Nicht-Windows-Plattformen nicht verschlüsselt ist, dazu, dass im Moment der Nutzung eine Umwandlung in eine Klartextdarstellung nötig ist, sowie dazu, dass die empfohlene Alternative ein undurchsichtiger Verweis auf ein außerhalb des Prozesses gespeichertes Credential ist.  2

  5. Microsoft Learn, Advisory Development Guidelines. Dazu, dass .NET von einer neuen Nutzung von SecureString abrät, während PowerShell es aus Gründen der Abwärtskompatibilität weiter unterstützt, dazu, dass es sicherer als eine Klartext-Zeichenfolge ist und genutzt wird, um versehentliche Offenlegung in der Konsole oder in Protokollen zu vermeiden, sowie dazu, dass es sorgfältig eingesetzt werden sollte, da es sich leicht zurück in Klartext umwandeln lässt.  2

  6. Microsoft Learn, Export-Clixml. Dazu, wie Export-Clixml Credential-Objekte mit Windows-DPAPI verschlüsselt speichert, dazu, dass die Entschlüsselung nur für das Benutzerkonto möglich ist, das sie gespeichert hat, und nur auf dem Computer, auf dem sie gespeichert wurde, sodass die exportierte Datei weder auf einem anderen Rechner noch von einem anderen Benutzer verwendet werden kann, sowie dazu, dass auf Nicht-Windows-Plattformen (macOS/Linux) nichts verschlüsselt wird und die Ausgabe praktisch Klartext ist.  2 3 4 5

  7. Microsoft Learn, Overview of the SecretManagement and SecretStore modules. Dazu, dass SecretManagement eine einheitliche Schnittstelle zu Erweiterungs-Tresoren ist, dazu, dass SecretStore ein plattformübergreifender Erweiterungs-Tresor ist, der Geheimnisse verschlüsselt in einer lokalen Datei speichert, dazu, dass Erweiterungs-Tresore für Azure Key Vault, KeePass, Credential Manager (CredMan) und andere existieren, sowie dazu, dass die Secret-Module als funktional abgeschlossen gelten, wobei die aktive Entwicklung beendet ist und nur Sicherheitskorrekturen fortgeführt werden.  2 3 4 5 6

  8. Microsoft Learn, Use the SecretStore in automation. Zur Konfiguration von SecretStores Interaction auf None für unbeaufsichtigte Läufe, zum Muster, das Tresor-Passwort in einer mit Export-Clixml erzeugten, DPAPI-verschlüsselten Datei zu speichern und mit Unlock-SecretStore zu entsperren, sowie dazu, dass dies eine reine Windows-Lösung ist.  2 3 4

  9. Microsoft Learn, Group Managed Service Accounts overview. Dazu, dass ein gMSA ein verwaltetes Domänenkonto ist, das automatische Passwortverwaltung und vereinfachte SPN-Verwaltung bietet, wobei die Passwortverwaltung vom Windows-Betriebssystem statt von einem Administrator übernommen wird.  2 3 4

  10. Microsoft Learn, Secure group managed service accounts. Dazu, dass ein gMSA-Passwort ein 240 Byte langer Zufallswert ist, dazu, dass das Betriebssystem es automatisch alle 30 Tage ändert, sodass weder Planung für Passwortänderungen noch ein Dienstausfall nötig sind, sowie dazu, dass gMSAs als Kontotyp für lokale Dienste empfohlen werden.  2

  11. Microsoft Learn, about_Logging_Windows. Dazu, wie das Aktivieren der Skriptblock-Protokollierung den Inhalt jedes von PowerShell verarbeiteten Skriptblocks im Ereignisprotokoll aufzeichnet, dazu, dass ein höheres Protokollierungsniveau sensible Daten wie in Skripten verwendete Zugangsdaten einschließen kann, sowie zu Protected Event Logging als Schutz dagegen.  2 3 4

  12. Microsoft Learn, ConvertFrom-SecureString. Zur Umwandlung einer SecureString in eine verschlüsselte Standard-Zeichenfolge, dazu, dass ohne Angabe eines Schlüssels Windows-DPAPI verwendet wird und bei Angabe von Key oder SecureKey AES, sowie dazu, dass -AsPlainText direkt in eine Klartext-Zeichenfolge umwandelt.  2

  13. Microsoft Learn, Import-Clixml. Dazu, wie Import-Clixml von Export-Clixml gespeicherte Zugangsdaten und sichere Zeichenfolgen wiederherstellt, und dazu, wie dies das Risiko vermeidet, Klartext-Passwörter in ein Skript zu schreiben. 

  14. Microsoft Learn, Understanding the SecretManagement module. Dazu, wie SecretManagement Geheimnisse über registrierte Erweiterungs-Tresore speichert und abruft, dazu, dass die Tresorregistrierung pro Benutzerkontext erfolgt, sowie dazu, dass die Abhängigkeit von $env:LOCALAPPDATA und DPAPI bedeutet, dass es derzeit nicht mit verwalteten Windows-Konten funktioniert.  2 3

  15. Microsoft Learn, Get started with the SecretStore module. Zur Registrierung von SecretStore mit Register-SecretVault, zu den grundlegenden Vorgängen Set-Secret / Get-Secret / Get-SecretInfo sowie dazu, dass beim ersten Zugriff das Festlegen des Tresor-Passworts verlangt wird. 

  16. Microsoft Learn, Use Azure Key Vault in automation. Dazu, dass Az.KeyVault ab Version 3.3.0 eine SecretManagement-Erweiterung enthält, die es erlaubt, Azure Key Vault mit Register-SecretVault als SecretManagement-Tresor zu registrieren und über Get-Secret und Ähnliches anzusteuern.  2 3

  17. Microsoft Learn, Understanding the security features of SecretManagement and SecretStore. Dazu, dass bei vollständig deaktivierter Passwort-Authentifizierung der Entschlüsselungsschlüssel allein durch Dateisystemberechtigungen geschützt wird, was für Systeme mit hohem Sicherheitsanspruch nicht empfohlen wird. 

  18. Microsoft Learn, Manage group Managed Service Accounts. Dazu, dass sich gMSAs für im Dienststeuerungs-Manager konfigurierte Dienste, IIS-Anwendungspools und Aufgaben der Aufgabenplanung nutzen lassen.  2

Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.

Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.

Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.

Häufige Fragen

Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.

Warum sollte ich kein Passwort im Klartext in ein PowerShell-Skript schreiben?
Weil ein Skript von seiner Natur her ein Artefakt ist, das kopiert, geteilt und in Historien aufgezeichnet wird. Ist ein Passwort einmal in Git committet, ist es schwierig, es wieder aus der Historie zu entfernen; liegt das Skript in einem Freigabeordner, kann es jeder mit Lesezugriff sehen; und Skriptblock-Protokollierung sowie Transkripte zeichnen den Inhalt von Befehlen wortwörtlich auf. Mit anderen Worten: Ein Klartext-Passwort schafft eine Struktur, bei der das Leck in dem Moment feststeht, in dem die Datei sichtbar wird. Die eigentliche Lösung besteht nicht darin, die Leckpfade einzeln zu schließen, sondern das Passwort aus dem Skript zu entfernen und in geschützten Speicher zu verlagern.
Wie sicher ist ein mit Export-Clixml gespeichertes Credential-Objekt?
Unter Windows wird es mit DPAPI (der Data Protection API) verschlüsselt und kann nur von dem Benutzerkonto, das es gespeichert hat, auf demselben Computer entschlüsselt werden. Selbst wenn die Datei gestohlen wird, lässt sie sich auf einem anderen Rechner oder von einem anderen Benutzer nicht öffnen – das macht sie zu einem praktikablen Speicherort für Zugangsdaten bei unbeaufsichtigten Läufen. Ein Allheilmittel ist es dennoch nicht: Jeder Prozess, der unter demselben Konto läuft, kann sie entschlüsseln, und unter macOS und Linux wird nichts verschlüsselt, sodass die Ausgabe praktisch Klartext ist. Wollen Sie es aus der Aufgabenplanung heraus nutzen, muss die gespeicherte Datei vom Ausführungskonto der Aufgabe selbst erzeugt werden.
Sollte ich SecureString überhaupt noch verwenden?
Die offizielle .NET-Dokumentation stellt unmissverständlich fest, dass SecureString für neue Entwicklungen nicht empfohlen wird. Die Verschlüsselung findet nur unter Windows statt; auf Nicht-Windows-Plattformen ist der interne Speicher nicht verschlüsselt. Und im Moment der tatsächlichen Nutzung muss es ohnehin wieder in Klartext umgewandelt werden. Andererseits ist die Standardausstattung der PowerShell-Welt – Get-Credential, SecretManagement und Ähnliches – um SecureString herum gebaut, und es verringert die Exposition gegenüber dem Herumtragen einer Klartext-Zeichenfolge tatsächlich, sodass es vorerst realistisch ist, es als „PowerShells Standard-Übergabeformat“ zu behandeln. Bauen Sie darauf nur keinen eigenen Schutzmechanismus auf.
Bleibt SecretStore bei einem unbeaufsichtigten Lauf über die Aufgabenplanung nicht bei einer Passwortabfrage hängen?
Mit der Standardkonfiguration ja. SecretStore verlangt standardmäßig ein Tresor-Passwort und löst eine interaktive Eingabeaufforderung aus. Für unbeaufsichtigte Läufe beschreibt die offizielle Dokumentation, Interaction auf None zu setzen und mit Unlock-SecretStore zu entsperren, wobei das Tresor-Passwort aus einer mit DPAPI geschützten Datei gelesen wird (erzeugt mit Export-Clixml). Beachten Sie, dass dies eine Konfiguration ist, die den Tresorschlüssel mit DPAPI schützt, und daher dieselben Einschränkungen wie DPAPI erbt (derselbe Benutzer, derselbe Rechner). Prüfen Sie, bevor Sie diesen Weg gehen, ob ein gMSA oder die Vergabe von Rechten an das Ausführungskonto die Notwendigkeit für Zugangsdaten von vornherein beseitigen könnte.
Gibt es einen Weg, ganz auf die Speicherung von Zugangsdaten zu verzichten?
Den gibt es – und er sollte Ihre erste Wahl sein. Windows-Aufgaben und -Dienste laufen im Sicherheitskontext ihres Ausführungskontos. Gewähren Sie diesem Konto also die nötigen Rechte auf dem Ziel (ein Freigabeordner, SQL-Server-Windows-Authentifizierung und Ähnliches), muss das Skript nie ein Passwort besitzen. Machen Sie das Ausführungskonto zu einem gMSA (group Managed Service Account), wird das Passwort zu einem 240 Byte langen Zufallswert, den das Betriebssystem automatisch alle 30 Tage rotiert, sodass ihn niemand überhaupt kennt. gMSAs lassen sich auch für Aufgaben der Aufgabenplanung nutzen.

Autorenprofil

Profilseite des Artikelautors.

Go Komura

Geschäftsführer von KomuraSoft LLC

Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.

Zurück zum Blog