Windows PowerShell basiert auf der Runtime (CLR) des .NET-Frameworks und wird mit Windows als Teil des Windows Management Frameworks (WMF) ausgeliefert. Mit Powershell-Skripten lassen sich somit alle essentiellen Teile eines Windows-Betriebssystems lesen und bearbeiten, die jeweiligen Rechte vorausgesetzt.
Da Powershell auch von Schadsoftware eingesetzt wird, verbieten die Betriebssysteme üblicherweise die Ausführung von Skripten, die aus dem Internet heruntergeladen wurden oder allgemein von unsignierten Skripten.
Eine digitale Signatur ist das Ergebnis eines kryptografischen Prozesses, bei dem mit Hilfe eines geheimen Signaturschlüssels aus beliegen Daten ein Wert berechnet wird: die Signatur. Dieser Wert ermöglicht es, mit Hilfe des öffentlich bekannten Schlüssels zwei wichtige Eigenschaften des Informationssicherheitsmanagements zu prüfen:
Hier in diesem Kontext bedeutet es, dass das Betriebssystem vor Ausführung eines Scripts prüft, ob die Signatur übereinstimmt mit dem Inhalt der Scripts und ob die Signatur mit einem Schlüssel angefertigt wurde, der vertrauenswürdig ist.
Sollte die Signatur nicht stimmen, könnte zum Beispiel ein böswilliger Akteur den Inhalt des Scripts manipuliert haben.
Als normaler Benutzer folgenden Code ausführen in Powershell. Ein Zertifikat wird im eigenen Zertifikatspeicher abgelegt.
New-SelfSignedCertificate -Subject 'CN=Powershell Code Signing Cert' -Type CodeSigningCert -CertStoreLocation Cert:\CurrentUser\My -HashAlgorithm 'sha256'
Mittels Powershell ließe sich das Zertifikat nun in den Speicher der vertrauenswürdigen Stammzertifikate verschieben. Einfacher ist, das mittels certmgr.msc
zu tun.
Nun das soeben erstellte Zertifikat verschieben von “Eigene Zertifikate” in den Speicher “Vertrausenwürdige Stammzertifizierungsstellen”.
## sign_file.ps
## Signiert die genannte Datei mit dem ersten Codesigning-Zertifikat aus dem Stammzertifikatspeicher der Nutzerin
param([string] $file=$(throw "Please specify a filename."))
Set-AuthenticodeSignature $file @(Get-ChildItem Cert:\CurrentUser\Root -CodeSigningCert)[0]
Jetzt müssen wir das Signaturskript selber noch signieren, bevor wir es nutzen können:
Set-AuthenticodeSignature .\sign_file.ps @(Get-ChildItem Cert:\CurrentUser\Root -CodeSigningCert)[0]
Nicht vergessen, die Policy anzupassen, so dass alle Skripte eine gültige Signatur haben müssen:
Set-ExecutionPolicy -ExecutionPolicy AllSigned
Voilà. Jetzt können wir unsere Skripte signieren mittels
.\sign_file.ps file.ps
Die Signatur befindet wird im Skript selber an den Code angehängt. Bei jeder Änderung muss neu signiert werden.
Um etwas sicherer zu sein, wäre es besser, statt den ersten Signaturschlüssel zu nehmen, genau den Schlüssel zu nehmen, der erstellt wurde. Das geht über dessen ID.