Sensible Daten mit PowerShell verschlüsseln
Bildsymbol PowerShell-Sicherheit
Sensible Daten mit PowerShell verschlüsseln

Sicherheit im PowerShell Code

Wenn Sie in der PowerShell mit sensiblen Daten umgehen, sollten Sie diese verschlüsseln, um sie vor Unbefugten zu schützen. Sensible Daten sind Geheimnisse, kompromittieren Protokolle, Passwörter, Zugangsdaten (Credentials) und der gleichen. Um die Sicherheit im Unternehmen zu erhöhen, sollten diese mittels Passwort, Zertifikate oder Benutzer-Profile verschlüsselt werden. Mit 5 einfachen Tricks gelingt Ihnen das ohne viel Aufwand.

TIPP - Wie Sie PowerShell produktiv absichern, trotzdem administrative Aufgaben delegieren und verdächtige und unerwünschte Aktivitäten zu protokollieren können. Beschreit der folgende Sicherheits-Guide: "PowerShell produktiv und sinnvoll absichern".

Sicherheit durch Zufalls-Passwörter

Zum Beispiel beim zurücksetzen oder neu Anlegen von Benutzerkonten, sollten eindeutige Initial-Passwörter verwendet werden. Und nicht wie oft gesehen, immer das Standard-Passwort, das im Helpdesk an der Pinwand hängt, was nicht zur Sicherheit beiträgt.

Windows Terminal Screenshot - Zufallspasswörter für neue Benutzer erstellen

# ! Möglichkeit 1:
[System.IO.Path]::GetRandomFileName() -replace '\.', [String]::Empty | Write-Warning

# ! Möglichkeit 2:
(1..100 | Get-Random -Count 3 | ForEach-Object { '{0:00}' -f $_ }) -join [String]::Empty | Write-Warning

# ! Möglichkeit 3:
[Convert]::ToBase64String((0..255 | Get-Random -Count 9)) | Write-Warning

# Zum Beispiel:
'p.mueller', 'i.schmitt', 'k.bauer', 'e.baecker' | ConvertFrom-Csv -Header 'Username' | ForEach-Object -Process {
    $RandomPassword       = [Convert]::ToBase64String((0..255 | Get-Random -Count 9))
    $RandomSecurePassword = $RandomPassword | ConvertTo-SecureString -AsPlainText -Force
    $_ | Add-Member -Name 'PlainTextPassword' -Value $RandomPassword       -MemberType 'NoteProperty'
    $_ | Add-Member -Name 'Password'          -Value $RandomSecurePassword -MemberType 'NoteProperty'
    return $_
}

Passwörter persistent sicher aufbewahren

Des öfteren müssen Passwörter z.B. in Automatisierungskripten zwecks Authentifizierung angegeben werden. Anstatt diese im Klartext im Skript zu speichern, erhöht es die Sicherheit diese Passwörter verschlüsselt auf der Festplatte abzulegen. Das Verschlüsselungs-Passwort wird automatisch über die Windows-Anmeldung sichergestellt. WICHTIG - Der Verschlüsselungsvorgang muss daher für jeden Host und User erneut durchgeführt werden.

# ? 1. Passwort sicher abfragen und verschlüsselt in C:\Temp\ speichern:

Read-Host -Prompt 'Passwort eingeben' -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath 'C:\Temp\SecureString.txt' -Force

Get-ChildItem -Path 'C:\Temp\SecureString.txt' | Get-Content | Write-Warning

# ! 2. Verschlüsselt Passwort von C:\ wieder einlesen:
Get-Content -Path 'C:\Temp\SecureString.txt' | ConvertTo-SecureString | Write-Warning

# TODO Aufräumen:
Remove-Item -Path 'C:\Temp\SecureString.txt' -Force

Mit Zertifikaten in PowerShell umgehen

HINWEIS - Da das Handling mit Zertifikaten auf jedem Betriebssystem anderst gehandhabt wird, müssen wir in PowerShell 7 die Windows PowerShell Module dafür verwenden.

# READ betroffene Cmdlets:
Get-Command -Name '*' -Module 'PKI'

Zertifikat erstellen:

using namespace 'Microsoft.CertificateServices.Commands'
$params = @{
    FriendlyName                = 'Superman'
    Subject                     = 'CN=_Superman (Doctor S. Man), E=s.man@krypton.universe'
    HashAlgorithm               = 'SHA512'
    KeyAlgorithm                = 'RSA'
    KeyLength                   = 4096
    KeyExportPolicy             = [KeyExportPolicy]::ExportableEncrypted
    KeySpec                     = [KeySpec]::KeyExchange
    CertStoreLocation           = 'Cert:\CurrentUser\My'
    Type                        = [CertificateType]::Custom
    TextExtension               = @('2.5.29.37={text}1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.3,1.3.6.1.5.5.7.3.4,1.3.6.1.5.5.7.3.5,1.3.6.1.5.5.7.3.6,1.3.6.1.5.5.7.3.7,1.3.6.1.5.5.7.3.8,1.3.6.1.5.5.7.3.9,1.3.6.1.4.1.311.80.1,1.3.6.1.4.1.311.10.3.4,1.3.6.1.4.1.311.10.3.4.1', `
                                    '2.5.29.17={text}email=s.man@krypton.universe&upn=s.man@krypton.universe')
    NotAfter                    = (Get-Date).AddMinutes(60)
    AlternateSignatureAlgorithm = $true
}
$myPfxCert = New-SelfSignedCertificate @params

Zertifikat exportieren:

$myPfxCert | Export-PfxCertificate -Password (Read-Host -Prompt 'Set PFX-Password for Superman' -AsSecureString) -FilePath 'C:\Temp\Superman.pfx'

$myPfxCert | Export-Certificate -Type 'CERT' -Force -FilePath 'C:\Temp\Superman.cer'

# ! Zertifikat im Zertifikats-Speicher löschen:

Get-ChildItem -Path 'Cert:\CurrentUser' -Recurse | Where-Object -Property 'Thumbprint' -CEQ $myPfxCert.Thumbprint | Remove-Item -Force -Recurse

Zertifikat importieren:

Import-Certificate -FilePath 'C:\Temp\Superman.cer' -CertStoreLocation 'Cert:\LocalMachine\Root'

Import-PfxCertificate -FilePath 'C:\Temp\Superman.pfx' -CertStoreLocation 'Cert:\CurrentUser\My' -Password (Read-Host -Prompt 'PFX-Password for Superman' -AsSecureString)

Zertifikat-Verwendungszweck testen:

# ! Zertifikat aus dem Dateisystem lesen und auf Verwendungszweck testen:

Get-PfxData -Password (Read-Host -Prompt 'PFX-Password for Superman' -AsSecureString) -FilePath 'C:\Temp\Superman.pfx' | Format-List -Property '*'

$test = Get-PfxCertificate -FilePath 'C:\Temp\Superman.pfx'

Test-Certificate -Cert $test -Policy 'SSL' | Write-Warning

Test-Certificate -Cert $test -EKU '1.3.6.1.5.5.7.3.1' | Write-Warning # = Server Authentication

# ! Zertifikat aus dem Cert-Speicher lesen und auf Verwendungszweck testen:

Get-ChildItem -Path 'Cert:\CurrentUser\My' | Where-Object -Property 'Subject' -CLike -Value 'CN=_Superman (Doctor S. Man), E=s.man@krypton.universe' | Test-Certificate -Policy 'SSL' | Write-Warning

Get-ChildItem -Path 'Cert:\LocalMachine\Root' | Where-Object -Property 'Subject' -CLike -Value 'CN=_Superman (Doctor S. Man), E=s.man@krypton.universe' | Test-Certificate -EKU '1.3.6.1.5.5.7.3.1' | Write-Warning

Das Beispiel aufräumen:

Remove-Item -Path 'C:\Temp\Superman.*' -Force
Get-ChildItem -Path 'Cert:\LocalMachine\', 'Cert:\CurrentUser\' -Recurse | Where-Object -Property 'Subject' -CLike -Value 'CN=_Superman (Doctor S. Man), E=s.man@krypton.universe' | Remove-Item -Force

Daten mittels Zertifikats verschlüsseln

Die Cmdlets Protect-CmsMessage und Unprotect-CmsMessage können kleine oder große Text mittels X.509 Zertifikat schifrieren bzw. deschifrieren. Geheimnisse die nicht im Klartext vorliegen, sondern verschlüsselt sind erhöhen die Sicherheit.

Windows Terminal Screenshot - Sensible Daten mittels CmsMessage verschlüsselt

# READ Übersicht der betroffene Cmdlets:
Get-Command -Noun 'CmsMessage' -Module 'Microsoft.PowerShell.Security'

# ! 1. Ein selbst signiertes Zertifikat erzeugen oder über die PKI erhalten:
$params = @{
    FriendlyName      = 'Superman'
    Subject           = 'CN=_Superman (Doctor S. Man), E=s.man@krypton.universe'
    HashAlgorithm     = 'SHA512'
    KeyExportPolicy   = 'ExportableEncrypted'
    KeyLength         = 4096
    KeySpec           = 'KeyExchange'
    CertStoreLocation = 'Cert:\CurrentUser\My'
    Type              = 'DocumentEncryptionCert'
    NotAfter          = (Get-Date).AddMinutes(60)
}
$myPfxCert = New-SelfSignedCertificate @params

# ! 2. Text verschlüsseln:
$CryptedText = 'Das sind die streng geheimen Daten!' | Protect-CmsMessage -To $myPfxCert.Thumbprint

# ! 3. Chiffre checken:
$CryptedText | Get-CmsMessage

# ! 4. Entschlüsseln:
$CryptedText | Unprotect-CmsMessage -To $myPfxCert.Thumbprint | Write-Warning

# TODO Aufräumen:
Get-ChildItem -Path 'Cert:\CurrentUser\My' | Where-Object -Property 'Subject' -CLike -Value 'CN=_Superman (Doctor S. Man), E=s.man@krypton.universe' | Remove-Item -Force

Credentials persistent sicher speichern

Die unterschiedlichsten Cmdlets erwarten über einen Parameter Authentifizierungsinformationen (Benutzname & Passwort) in Form eines [PSCredential]-Objektes. Dieses Objekt kann per Cmdlet Get-Credential oder manuell erzeugt werden. Der Fokus liegt hierbei auf das Password das als [SecureString]-Objekt verschlüsselt im Arbeitsspeicher abgelegt ist.

$Cred = Get-Credential -Message 'Zugangsdaten für Administrator auf 127.0.0.1' -UserName 'Administrator'

Enter-PSSession -ComputerName '127.0.0.1' -Credential $Cred

SICHERHEIT - Credentials können auch verschlüsselt im Dateisystem gespeichert werden, um diese später wieder einzulesen.

# ! 1. Credentials verschlüsselt speichern:

$Username = Read-Host -Prompt 'Benutzername eingaben'
$Password = Read-Host -Prompt 'Passwort für $username eingeben' -AsSecureString
[PSCustomObject]@{
    Username = $Username
    Password = $Password | ConvertFrom-SecureString
} | ConvertTo-Json | Set-Content -Path 'C:\Temp\Credential_Admin.json' -Force

# ! 2. Verschlüsselte Daten laden, und daraus ein [Credential]-Objekt instanziieren:

$Admin = Get-Content -Path 'C:\Temp\Credential_Admin.json' | ConvertFrom-Json | Select-Object Username, @{ Label='Password'; Expression={$_.Password | ConvertTo-SecureString } }
$Cred = [System.Management.Automation.PSCredential]::new($Admin.Username, $Admin.Password)

Enter-PSSession -ComputerName '127.0.0.1' -Credential $Cred

# TODO Aufräumen:
Remove-Item -Path 'C:\Temp\Credential_Admin.json' -Force

Über das Modul Microsoft.PowerShell.SecretManagement aus der PowerShell-Gallery können Sie sämtliche Geheimnisse sicher aufbewahren das zur Sicherheit beiträgt. Hierzu gibt es eine Built-In-Local-Vault. Aber denkbar ist auch eine eigene Vault zentral zu hinterlegen oder auch eine Anbindung jedes beliebige Verschlüsselungs-System, wie z.B. KeePass ist möglich. Einen Wermutstropfen gibt es allerdings, dass Modul ist noch im Alpha-Status 🙁

# ! 1. 'Microsoft.PowerShell.SecretManagement'-Module installieren:

Find-Module -Name 'Microsoft.PowerShell.SecretManagement' -Repository 'PSGallery-Alternative' -AllowPrerelease | Install-Module -Scope 'CurrentUser' -SkipPublisherCheck -AllowPrerelease -Force

# ! 2. Credential persistent speichern:
Set-Secret -Name 'Administrator' -Secret (Get-Credential) -Vault 'BuiltInLocalVault'

# ! 3. Credential abrufen und verwenden:

$Credential = Get-Secret -Name 'Administrator' -Vault 'BuiltInLocalVault'

Start-Process -FilePath 'notepad.exe' -Credential $Credential

Get-Process 'notepad' -IncludeUserName

# TODO Aufräumen:
Get-Process 'notepad' | Stop-Process -Force
Remove-Secret -Name 'Administrator' -Vault 'BuiltInLocalVault'
Remove-Module -Name 'Microsoft.PowerShell.SecretManagement' -Force
Uninstall-Module -Name 'Microsoft.PowerShell.SecretManagement' -AllVersions -AllowPrerelease -Force

Epilog

Von mir gibt es noch weitere PowerShell-Fachartikel und Guideszum Thema Sicherheit. Und jetzt Neu, abonnieren Sie meinen PowerShell-YouTube-Kanal.

Oder Wissen vom Trainer mit vielen praxisbezogenen Übungen, Wissenstests und Frage und Antwort-Runden. Jetzt in meinen PowerShell-Seminaren und -Workshops.

Wenn Sie diesen Artikel als hilfreich empfunden haben würde ich mich über eine Erwähnung und einen Verweis auf diesen Artikel in den sozialen Medien sehr freuen.

Als Dankeschön bekommen Sie ein von mir erstelltes hochwertiges A1-PowerShell-7-Poster mit den wichtigsten Informationen für die tägliche Arbeit per Post zugesendet. Hierzu schreiben Sie mir an info at attilakrick.com einfache eine E-Mail mit dem Link der Erwähnung sowie Ihre Adresse. Aber nur solange der Vorrat reicht. Ihre Daten (E-Mail, Adresse) werden nur zum Zweck des Poster-Versandes benötigt und anschließend gelöscht.


Bitte bewerten Sie diesen Artikel


Dieser Beitrag hat einen Kommentar

Schreibe einen Kommentar