Skripte vertrauenswürdig ausführen - mit Codesignatur-Zertifikaten!

Lesedauer 6 Minuten


PowerShell ist einerseits ein ziemlich mächtiges Werkzeug zur Automatisierung. Andererseits setzen Microsoft und auch andere Hersteller mittlerweile gewisse Grundkenntnisse in der Nutzung von PowerShell voraus.
Funktionen werden teilweise gar nicht erst in einer grafischen Oberfläche bereitgestellt, sondern müssen stets mit PowerShell geändert werden. Es ist auch anzunehmen, dass dies zunehmen wird, da es nicht für jede Funktion Sinn macht, eine (ggf. recht aufwändige) Konfigurationsmöglichkeit bereitzustellen.

Daher macht es durchaus Sinn, sich mit PowerShell auseinanderzusetzen. Ein PowerShell-Skript ist schnell gebaut, sobald man einmal die Syntax verstanden hat.

Da man mit solchen Skripten jedoch auch einigen Schaden anrichten kann, hat Microsoft bewusst einige Hürden eingebaut, damit Skripte nicht einfach so ausgeführt werden können. Ein Beispiel sind die sogenannten Ausführungsrichtlinien.

Was sind PowerShell-Ausführungsrichtlinien?

Über PowerShell-Ausführungsrichtlinien kann definiert werden, ob und unter welchen Umständen ein Skript ausgeführt werden darf. Dies lässt sich sogar separat für das Computerkonto und den angemeldeten Benutzer definieren, da Skripte in beiden Kontexten ausgeführt werden können.

Schon gewusst? Wird ein PowerShell-Skript im Kontext des Computerkontos ausgeführt, so stehen dem Skript die Berechtigungen des SYSTEM-Kontos zur Verfügung. Dieses Prinzipal verfügt sogar über mehr Rechte als ein Administratorkonto! Daher sollte die Ausführungsrichtlinie für Computerkonten immer strikter sein als für Benutzerkonten.

Es können die folgenden Richtlinien konfiguriert werden:

RichtlinieAuswirkungen
AllSignedSkripte können ausgeführt werden, müssen jedoch immer mit einem vertrauenswürdigen Zertifikat signiert sein.
BypassKeinerlei Einschränkungen (nur für bestimmte Szenarien gedacht, siehe unten)
DefaultSetzt ggf. abweichende Einstellungen auf die Standardeinstellung zurück (RemoteSigned)
RemoteSignedNicht auf dem lokalen Computer erstellte Skripte müssen signiert werden.
Lokal auf dem Computer erstellte Skripte können ohne Signatur ausgeführt werden.
RestrictedSkripte sowie entsprechende Modulskriptdateien können nicht ausgeführt werden.
UndefinedKeine spezifische Ausführungsrichtlinie festgelegt, daher Rückgriff auf Restricted (Windows-Clients) bzw. RemoteSigned (Windows Server)
UnrestrictedKeinerlei Einschränkungen

Die Richtlinie "Bypass" ist nicht für eine dauerhafte Konfiguration gedacht, sondern wird dazu genutzt, die einmalige Ausführung eines nicht signierten Skripts zu ermöglichen:

# Unsigniertes Skript einmalig ausführen und PowerShell-Ausführungsrichtlinie umgehen
PowerShell.exe -ExecutionPolicy Bypass -File '<Pfad\zum\Skript>.ps1'
PowerShell

Wichtig: eine Ausführungsrichtlinie verhindert nicht, dass ein PowerShell-Fenster geöffnet und der Inhalt eines Skripts hineinkopiert wird!

Es wäre prinzipiell möglich, die Ausführungsrichtlinie sowohl für Computer als auch per Benutzer auf "Unrestricted" zu stellen. Allerdings reduziert dies die Sicherheit erheblich und ist daher nicht empfehlenswert. Besser ist es, die Richtlinie "AllSigned" zu verwenden, da dies den besten Kompromiss aus Flexibilität und Sicherheit bietet - es können Skripte ausgeführt werden, diese müssen allerdings signiert sein.

Die Ausführungsrichtlinie kann per Gruppenrichtlinie (und auch über Intune) festgelegt werden:

Computerkonfiguration > Richtlinien > Administrative Vorlagen > Windows-Komponenten > Windows PowerShell > Skriptausführung aktivieren

Benutzerkonfiguration > Richtlinien > Administrative Vorlagen > Windows-Komponenten > Windows PowerShell > Skriptausführung aktivieren

Aktiviert, Skriptausführungsrichtlinie > Nur signierte Skripts zulassen

Dies stellt sicher, dass ausschließlich signierte Skripte zugelassen werden. Aber wie funktioniert das mit dem Signieren eigentlich?

Bereitstellung eines Codesignatur-Zertifikats

Für das Signieren von PowerShell-Skripten benötigt man ein sogenanntes Codesignatur-Zertifikat. Ein solches Zertifikat kann nicht nur zum Signieren von Skripten, sondern für jegliche Form von Code verwendet werden, bspw. auch Applikationscode und digitale Makros in Office-Anwendungen.

Bezugsquellen

Das Zertifikat kann auf die folgenden Arten bezogen werden:

BezugsquelleRahmenbedingungen
Öffentlicher Anbieter- Kostenpflichtig, ab 299€
- Maximale Laufzeit: 15 Monate
Unternehmensinterne Zertifizierungsstelle- Kostenfrei
- Maximale Laufzeit je nach Unternehmensrichtlinien
Selbstsigniert- Kostenfrei
- Maximale Laufzeit frei wählbar
- Benötigt lokale Administratorrechte

Die Erstellung und Verwendung eines selbstsignierten Zertifikats ist im Regelfall nicht empfehlenswert, da so ein Zertifikat nicht als vertrauenswürdig erachtet werden kann. In isolierten oder Testumgebungen mag es jedoch eine einfache Alternative darstellen.

Abruf/Erstellung eines Zertifikats

Die folgenden Kapitel gehen auf die notwendigen Schritte zum Abruf bzw. zur Erstellung eines Codesignatur-Zertifikats je nach Auswahl der Bezugsquelle ein.

Wichtig: je nach Unternehmensrichtlinien mag es erforderlich sein, zusätzlich ein 4-Augen-Prinzip für die Nutzung eines solchen Zertifikats zu etablieren. Ein Codesignatur-Zertifikat ermöglicht die Signierung jeglichen Codes - es ist also nicht möglich, es auf die Nutzung mit PowerShell-Skripten oder Makros einzuschränken. Bei einer Weitergabe von signiertem Code an andere Unternehmen gehen diese außerdem davon aus, dass der Code vertrauenswürdig ist. Dementsprechend darf ein solches Zertifikat nicht in Umlauf geraten, sondern muss vor unbefugtem Zugriff geschützt werden!

Tipp: Ein für allgemein genutzte Applikationen und Skripte verwendetes Zertifikat sollte nie auf eine echte Person ausgestellt werden, da diese das Unternehmen verlassen kann.
In solchen Fällen sollte ein spezifisches Dienstkonto hierfür eingerichtet werden, mit dem solche Applikationen und Skripte zentral signiert werden bzw. die regelmäßige Erneuerung durchgeführt wird.

Öffentlicher Anbieter

Für den Bezug eines Codesignatur-Zertifikats von einer öffentlichen Zertifizierungsstelle kann beispielsweise die Webseite https://www.psw-group.de/ genutzt werden. Diese bietet eine zentrale Übersicht der gängigen Anbieter und ermöglicht so einen direkten Vergleich.

Für den Kauf muss ein Konto beim Anbieter eröffnet werden. Ggf. müssen auch zusätzliche Schritte für die Validierung des Unternehmens durchgeführt werden, bspw. durch Hinzufügen von DNS-Einträgen in der öffentlichen DNS-Zone des Unternehmens. Das Codesignatur-Zertifikat selbst muss hierbei typischerweise auf den Namen eines echten Mitarbeitenden ausgestellt werden.

Der Vorteil bei Verwendung eines öffentlichen Anbieters liegt darin, dass die Zertifikatkette zur Validierung der Gültigkeit von überall abrufbar ist. Damit lassen sich so signierte Makros, Applikationen und Skripte auch extern bzw. in anderen Unternehmen nutzen.

Unternehmensinterne Zertifizierungsstelle

Falls das Unternehmen über eine interne Zertifizierungsstelle verfügt, so kann mit wenig Aufwand ein Codesignatur-Zertifikat über diese Zertifizierungsstelle verfügbar gemacht werden (sofern die Unternehmensrichtlinien die Ausstellung zulassen). Hierzu ist in der Zertifizierungsstelle zunächst eine passende Zertifikatvorlage zu erstellen. Der Zugriff darauf sollte über eine bzw. Active Directory-Sicherheitsgruppen pro Berechtigung im Sinne einer granularen Rechtevergabe gesteuert werden (z.B. "Lesen", "Registrieren", "Automatisch registrieren").

  • Auf einem System, auf dem die Verwaltungstools für die Zertifizierungsstelle installiert sind, die Zertifikatvorlagen-Konsole öffnen (certtmpl.msc)
  • Rechtsklick auf die Vorlage "Codesignatur" ausführen und "Duplizieren" auswählen
  • Eigenschaften der Vorlage gemäß den Vorgaben des Unternehmens konfigurieren und einen Namen vergeben, die folgenden Register sind typischerweise relevant:
    • Kompatibilität (aktuelle Versionen auswählen)
    • Kryptographie (möglichst aktuellen Algorithmus und Anforderungshash verwenden, z.B. ECDSA_P256 und SHA256)
    • Sicherheit (zuvor erstellte Active Directory-Gruppen hinzufügen und die vorgesehene Berechtigung zuweisen)

Aus Sicherheitsgründen sollte die Option "Exportieren von privatem Schlüssel zulassen" nicht aktiviert werden, damit das Zertifikat nur auf dem System genutzt werden kann, auf dem es angefragt wurde.

Die Zertifikatvorlage muss anschließend in der Zertifizierungsstelle wie folgt bereitgestellt werden:

  • Konsole für Zertifizierungsstelle öffnen
  • Rechtsklick auf "Zertifikatvorlagen" ausführen und "Neu > auszustellende Zertifikatvorlage" auswählen
  • Aus der Liste die neu erstellte Vorlage auswählen

Sofern die berechtigten Benutzer die Berechtigung "Automatisch registrieren" erhalten haben, sollten sie nach einer Neuanmeldung ein Zertifikat erhalten. Sollen Benutzer ein Zertifikat manuell abrufen, ist wie folgt vorzugehen:

  • Zertifikatkonsole für Benutzer öffnen (certmgr.msc)
  • Rechtsklick auf "Eigene Zertifikate", "Alle Aufgaben > Neues Zertifikat anfordern..." auswählen
  • Weiterklicken, bis die verfügbaren Zertifikatvorlagen angezeigt werden und die neue Zertifikatvorlage auswählen
  • "Registrieren"


Wurde alles richtig konfiguriert, verfügt der Benutzer nun über ein Zertifikat, mit dem sich Code jeglicher Art digital signieren lässt.

Selbstsigniert

Falls kein Budget für den Kauf eines Zertifikats von einem öffentlichen Anbieter und auch keine interne Zertifizierungsstelle zur Verfügung steht, kann auch ein selbstsigniertes Zertifikat erstellt und verwendet werden. Hierfür kannst Du ein Skript verwenden, das Du in meinem Skriptnest findest.

Das Skript fragt die benötigten Parameter ab, beispielsweise die zu verwendenden Algorithmen, die Gültigkeitsdauer und den Verwendungszweck. Das Skript kann nicht für für die Erstellung von Codesignatur-Zertifikaten, sondern auch für andere Zwecke genutzt werden.

Verteilung des öffentlichen Schlüssels

Unabhängig von der Bezugsquelle muss der öffentliche Schlüssel des Zertifikats auf alle Systeme verteilt werden, auf den damit signierter Code ausgeführt werden soll. Bei der Ausführung wird nämlich nicht nur die Gültigkeit des Zertifikats, sondern auch die Vertrauenswürdigkeit des Herausgebers geprüft. Und dieser Test erzeugt eine Warnung, wenn das Zertifikat nicht im lokalen Zertifikatsspeicher verfügbar ist.

Daher muss der öffentliche Schlüssel wie folgt exportiert und verteilt werden:

  • Zertifikatkonsole für Benutzer öffnen (certmgr.msc)
  • "Eigene Zertifikate > Zertifikate" erweitern, auf das Zertifikat rechtsklicken und "Alle Aufgaben > Exportieren..." auswählen
  • "Nein, privaten Schlüssel nicht exportieren" belassen und Assistenten fertigstellen

Nun muss das Zertifikat auf alle Systeme verteilt werden, auf denen damit signierter Code ausgeführt wird. Dies kann entweder manuell passieren oder per Gruppenrichtlinie/Intune automatisiert werden.

Signierung von PowerShell-Skripten

Sind alle Voraussetzungen erfüllt, können nun Skripte unter Verwendung des Zertifikats signiert werden. Dies wird mittels PowerShell durchgeführt:

# Zertifikat aus dem lokalen Speicher mit dem Zweck "Codesignatur" ermitteln
$Cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert

# Einzelnes PowerShell-Skript signieren
Set-AuthenticodeSignature -FilePath '<Pfad\zum\Skript>.ps1' -Certificate $Cert

# Alle Skripte in einem Ordner signieren
$ScriptPath = '<Pfad\zu\Skripten>'
$Scripts = (Get-ChildItem -Path $ScriptPath).Name
ForEach ($Script in $ScriptPath){Set-AuthenticodeSignature -FilePath $ScriptPath\$Script -Certificate $Cert}
PowerShell


Gefällt Dir der Beitrag? Lass es andere wissen!