Skip to the main content.

PowerShell-Erfolgsrezepte – die Profi-Tipps für effektives Scripting

Sicherheitsrisiken bei cross-platform Encryption mit .NET SecureString

Denkst du, dass dein SecureString sicher ist? Nicht auf allen Plattformen! Entdecke die Risiken der plattformübergreifenden Datenverschlüsselung mit SecureString in .NET. Lies hier unseren ersten von vier SecureString-Deep Dive Artikeln:

SecureString wurde entwickelt, um den Umgang mit sensiblen Texten (z.B. Passwörtern) zu vereinfachen: Im Hintergrund verwendet .NET's System.Security.SecureString eine starke AES-Verschlüsselung, um sicherzustellen, dass nur der Besitzer eines Strings diesen lesen kann – unabhängig davon, ob in einer Datei gespeichert oder bei einem Angriff in einem "Memo Dump" gefunden.

Leider funktioniert dies unter Windows sehr gut, aber auf anderen Plattformen versagt es unbemerkt. Es ist an der Zeit, in dieser Miniserie einen genaueren Blick darauf zu werfen. Wer sich für plattformübergreifende Lösungen interessiert, findet auf  auf Microsoft | Learn eine gute Übersicht über kompatible plattformübergreifende Verschlüsselungen.

 

Geheimnisse transparent verschlüsseln

Auf Windows-Systemen ist SecureString automatisch geschützt, sodass du es zum Speichern lokaler Passwörter verwenden kannst. Im folgenden Beispiel kannst du Anmeldedaten für drei verschiedene Server eingeben (du kannst auch weitere hinzufügen), die dann in einer XML-Datei serialisiert werden:


$path = "$env:userprofile\mypasswords.xml"

@{
    Server1 = Get-Credential -Message 'Enter password for Server 1' -UserName $env:USERNAME
    Server2 = Get-Credential -Message 'Enter password for Server 2' -UserName $env:USERNAME
    Server3 = Get-Credential -Message 'Enter password for Server 3' -UserName $env:USERNAME
} | Export-Clixml -Path $path 

 

Wenn die XML-Datei in einem Texteditor geöffnet wird, sind die Passwörter verschlüsselt:

<ToString>System.Management.Automation.PSCredential</ToString>
<Props>
  <S N="UserName">tobia</S>
  <SS N="Password">01000000d08c9ddf0115d1118c7a00c04fc297eb01000000fca013869c24324fa191f7d1f5e8d46a00000000020000000000106600000001000020000000de26f1058a814b27a481821459eea01f8ad340a87512a6be0c21f871b46e8ee6000000000e8000000002000020000000cc97abd02f4f296d16338711331f1e9893e36da5ba397a3286891b06d329ff6710000000c7f9f9af2a5d3e7b980cab7acc7b22ee400000006dfc7c22382502e9ec47eb0ea28f990807dc336f1d673a06754c9de5a794b077633217176cfa027ee180073bb42965128442c917f40a25d7150d5536e325f82f</SS>
</Props>

Das liegt daran, dass Anmeldeinformationen sensible Informationen im Datentyp SecureString speichern, der automatisch geschützt ist (während der Benutzername im Klartext erscheint, da es sich um einen regulären String handelt).

 

Transparente Entschlüsselung von Geheimnissen

Das Entschlüsseln der zuvor verschlüsselten Informationen ist genauso transparent.

Wenn die in der obigen XML-Datei gespeicherten Anmeldedaten ausgelesen (und verwendet) werden müssen – z.B. durch ein Skript, das unbeaufsichtigt ausgeführt werden soll und diese Anmeldedaten zum Log-in verwendet – ist der umgekehrte Prozess vollständig transparent:


$path = "$env:userprofile\mypasswords.xml"

$mySecrets = Import-Clixml -Path $path

# Abrufen der gespeicherten Anmeldedaten
$mySecrets.Server1

# Ich bin der Besitzer, also kann ich auch immer den Klartext-String sehen
$mySecrets.Server1.GetNetworkCredential().Password

$mySecrets.Server2
$mySecrets.Server2.GetNetworkCredential().Password

$mySecrets.Server3
$mySecrets.Server3.GetNetworkCredential().Password 

 

Dieser Prozess ist sicher, keine Frage. Schließlich werden nur unter Windows zwei "Geheimnisse" für die AES‑Verschlüsselung verwendet: du und dein PC. Die transparente Entschlüsselung funktioniert ausschließlich für die Identität, die den SecureString verschlüsselt hat, und auch nur auf dem ursprünglichen PC. Andere Personen können die Passwörter aus der XML-Datei nicht entschlüsseln.

 

Datentyp SecureString löst Verschlüsselung aus

Es ist wichtig zu verstehen, dass die zugrunde liegende Verschlüsselung und Entschlüsselung von .NET durchgeführt wird, wenn der Datentyp System.Security.SecureString an einer beliebigen Stelle innerhalb des Codes serialisiert wird:


# Verschlüsselung
$path = Join-Path -Path $env:temp -ChildPath secret.xml
Read-Host -Prompt 'Enter your secret' -AsSecureString | Export-Clixml -Path $path

# Entschlüsselung
$path = Join-Path -Path $env:temp -ChildPath secret.xml
$secureString = Import-Clixml -Path $path 

$secureString 

 

Auch hier wird der eingegebene String transparent mit AES verschlüsselt und in die XML-Datei geschrieben:


$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString)
$plainText = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)

# Allokierten Speicher freigeben
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
$plainText 

 

Umwandlung von SecureString in Klartext-String

Beim Importieren der XML-Datei wird der SecureString abgerufen. Da du Eigentümer des Strings bist, kannst du diesen jederzeit wieder in Klartext umwandeln:


$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString)
$plainText = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)

# Allokierten Speicher freigeben
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
$plainText 

 

Maskiertes Eingabefeld

Der Hauptzweck von SecureString (auf der Windows-Plattform) ist der Schutz sensibler Informationen; es lassen sich jedoch eine Reihe von Anwendungen ableiten: Da PowerShell ein maskiertes Eingabefeld anzeigt, wenn Sie zur Eingabe eines SecureString aufgefordert werden, können Sie nun problemlos maskierte Eingabefelder implementieren.


function Get-SomeSecret
{
    param
    (
        [SecureString]
        [Parameter(Obligatorisch)]
        $Secret
      )
    
    $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($Secret)
    $plainText = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
   
    # Zugewiesenen Speicher freigeben
    [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)

    "The user entered: $plainText"


 

Du bist das Geheimnis

Wie du siehst, machen SecureStrings den Umgang mit Secrets (Geheimnissen) überflüssig: Der Verschlüsselungsschlüssel muss nicht bekannt sein (oder übertragen werden). Stattdessen sind dein Computer und du die Schlüssel.

 

Einschränkungen bei Nicht-Windows

Um zu testen, ob SecureStrings auf deiner Plattform tatsächlich sicher sind, speichere einfach einen SecureString auf eine der abgebildeten Arten in einer XML-Datei. Versuche dann, die Datei als anderer Nutzer oder auf einem anderen Computer zu entschlüsseln. Wenn dieser Vorgang mit einer Ausnahme fehlschlägt, ist dein Geheimnis sicher verschlüsselt. Unter Windows ist dies der Fall.

Bei Nicht-Windows-Plattformen wie Linux und macOS wird die automatische AES-Verschlüsselung von SecureStrings still und leise entfernt. Der gesamte obige Code funktioniert auch dort einwandfrei. SecureString ist nicht AES-verschlüsselt, sondern lediglich codiert. Jeder, der Zugriff auf die XML-Datei erhält, kann das Geheimnis entschlüsseln.
.NET (von PowerShell 7 verwendet) implementiert die Verschlüsselungs-API schlichtweg nicht auf Nicht-Windows-Systemen. Das bedeutet, dass du unter Umständen eine sichere Skriptlösung auf Basis von SecureStrings unter Windows verwendet hast, aber sobald du sie auf eine andere Plattform überträgst, sind deine sensiblen Daten nicht mehr geschützt, auch wenn sie scheinbar weiterhin einwandfrei funktionieren.

 

Allerdings wurde die automatische AES-Verschlüsselung von SecureStrings auf Nicht-Windows-Plattformen wie Linux und macOS still und leise entfernt. Der gesamte obige Code funktioniert auch dort einwandfrei. Allerdings ist der SecureString nicht AES-verschlüsselt, sondern lediglich kodiert: Jeder, der Zugriff auf die XML-Datei hat, kann das Geheimnis entschlüsseln.

Dies liegt daran, dass .NET (von PowerShell 7 verwendet) die Verschlüsselungs-API nicht auf Nicht-Windows-Systemen implementiert. Der gefährliche Nebeneffekt besteht darin, dass du möglicherweise eine sichere Skriptlösung auf Basis von SecureStrings unter Windows verwendet hast, aber sobald du sie auf eine andere Plattform überträgst, sind deine sensiblen Daten nicht mehr geschützt, auch wenn sie scheinbar weiterhin einwandfrei funktionieren.

Unser erster "Deep Dive" (SecureString in .NET) hat die Frage beantwortet, wie sicher deine sensiblen Daten plattformübergreifend sind. In den nächsten drei Deep Dives zeigen wir dir weitere Möglichkeiten, die Sicherheit zu verbessern, im nächsten Artikel behandeln wir Alternativen und bewährte Verfahren auf verschiedenen Plattformen.

 

Good2know

Dein ultimativer PowerShell-Spickzettel

Entfessele das volle Potenzial von PowerShell mit unserem praktischen Poster. Egal, ob frischer Einsteiger oder erfahrener Profi, dieser Spickzettel ist so konzipiert, dass du schnell die wichtigsten und am häufigsten verwendeten Cmdlets findest.

Das Poster ist zum Download und in Papierform erhältlich.

PowerShell Poster 2023

Hol dir hier dein Poster!

 

 

Weiterführende Links 



 

Zusammenhängende Posts

6 min read

Sicherheitsrisiken bei cross-platform Encryption mit .NET SecureString

Denkst du, dass dein SecureString sicher ist? Nicht auf allen Plattformen! Entdecke die Risiken der...

6 min read

Kodierung vs. Verschlüsselung: Was schützt wirklich?

Was ist der Unterschied zwischen Kodierung und Verschlüsselung? Dieser Artikel erklärt, welchen Zweck sie erfüllen und...

6 min read

SecureString – mehr Sicherheit auf verschiedenen Plattformen

Wie gewährleistet Windows die Sicherheit von SecureString? Tauche mit uns im zweiten Artikel noch tiefer in die...

Über den Autor: