Constrained Language Mode: PowerShell-Risiken entschärfen

    PowerShell Constrained Language ModePowerShell ist ein mächtiges Werk­zeug, das fast alle Kompo­nenten von Windows und Anwen­dungen wie Exchange steuern kann. In den Händen von An­greifern kann sie daher große Schäden an­richten. Der Constrained Language Mode sperrt gefähr­liche Features und ver­hindert so deren Missbrauch.

    Standard­mäßig operiert PowerShell im FullLanguage Mode, in dem alle Funktionen verfügbar sind. Dazu zählt der Zugriff auf alle Sprach­elemente, Cmdlets und Module, aber auch auf das Datei­system und das Netzwerk.

    Geblockte Funktionen

    Besonders gefährlich für die miss­bräuchliche Verwendung von PowerShell ist die Fähigkeit, COM- und .NET-Objekte zu instanziieren oder das Erzeugen von beliebigen Datentypen (mit Add-Type), die in anderen Sprachen definiert wurden.

    Der Constrained Language Mode blockiert diese Möglichkeiten (mit Ausnahme des Zugriffs auf zulässige .NET-Klassen). Darüber hinaus verhindert er die Verwendung von Klassen, das Configuration Management mit DSC und XAML-basierte Workflows (für eine komplette Liste siehe Microsoft Docs).

    Constrained Language Mode aktivieren

    Eine einfache Variante, um in den Constrained Language Mode zu schalten, besteht darin, die zuständige Variable auf den gewünschten Wert zu setzen:

    $ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"

    Anzeigen und ändern des Language Mode über die Variable $ExecutionContext.SessionState.LanguageMode

    Es liegt auf der Hand, dass das Setzen dieser Variable noch keinen wirklichen Schutz bringt. Man kann sie zwar in der gleichen Sitzung nicht wieder auf FullLanguage ändern, aber eine neue PowerShell-Session bietet dann wieder den vollen Sprach­umfang.

    In eingeschränkten Modus schalten mit Umgebungsvariable

    Weniger leicht zu überwinden ist die (undoku­mentierte) System-Umgebungs­variable __PSLockDownPolicy, wenn man diese auf den Wert 4 setzt. In der Folge startet PowerShell, egal ob bloße Kommandozeile oder die ISE, im eingeschränkten Modus.

    Umgebungsvariable __PSLockDownPolicy interaktiv setzen

    In zentral verwalteten Umgebungen wird man die System­variable per Gruppen­richtlinien setzen (siehe dazu Gruppenrichtlinien: Umgebungsvariablen setzen und abfragen).

    Umgebungsvariable __PSLockDownPolicy über GPO setzen

    Ein Nachteil dieses Verfahrens besteht darin, dass es sich immer auf alle Benutzer eines Computers auswirkt, auch auf Admini­stratoren. Letztere können die Umgebungs­variable aber temporär entfernen, bis das GPO wieder wirksam wird.

    Darüber hinaus ist es in dieser Form kein von Microsoft unterstütztes Sicherheits-Feature und es lässt sich relativ leicht umgehen, wie Matt Graeber in diesem Tweet zeigt. Trotzdem könnte es auch so einige oppor­tunistische Angriffe vereiteln.

    Eine verbindliche Durch­setzung des beschränkten Sprachmodus auf einem lokalen Rechner erfordert somit die Mithilfe einer Aus­führungs­be­schränkung wie AppLocker oder Windows Defender Application Control (vormals ein Feature von Device Guard). Dagegen kann man ihn in einer Remote-Sitzung über eine Session Configuration erzwingen.

    Automatische Erkennung einer Ausführungsbeschränkung

    Seit der Version 5 erkennt PowerShell selbständig, ob es anhand von Skriptregeln in den Constrained Language Mode wechseln soll. Dazu legt es ein Modul und ein Script (mit einem Namen nach dem Muster __PSSCRIPTPOLICYTEST_LQU1DAME.3DD.PS1) unter $env:temp an und versucht, diese auszuführen. Wenn AppLocker oder ein anderes Tool das verhindert, startet PowerShell im eingeschränkten Sprach­modus.

    Im Eventlog zeigt sich, ob die Ausführung der Test-Scripts erfolgreich war oder gescheitert ist.

    Das Wirken dieses Mechanismus kann man bei AppLocker recht leicht in der Ereignis­anzeige nachvollziehen. Das Anlegen und Ausführen dieser Testdateien protokolliert AppLocker mit der ID 8005 (Erfolg) bzw. 8007 (Ausführung blockiert) unter Anwendungs- und Diensteprotokoll => Microsoft => Windows => AppLocker => MSI und Script.

    AppLocker konfigurieren

    Setzt man für diese Aufgabe AppLocker ein, dann legt man ein neues GPO an und bearbeitet es anschließend im GPO-Editor. Dort wechselt man zu Computer­konfiguration => Richtlinien => Windows-Einstellungen => Sicherheits­einstellungen => Anwendungs­steuerungs­richtlinien => AppLocker und folgt dem Link Regel­erzwingung konfi­gurieren. Im darauf angezeigten Dialog aktiviert man die Option Skriptregeln.

    Regelerzwingung für Scripts in AppLocker aktivieren

    Damit AppLocker Anwendungen auf den Zielsystemen blockieren kann, muss dort der Service Anwendungsidentität laufen. Er ist standardmäßig nicht aktiv und startet nicht zusammen mit dem System. Man kann ihn entweder interaktiv über das MMC-Snapin Dienste oder über die Kommandozeile auf den Starttyp automatisch ändern:

    sc config AppIDSvc start=auto

    Starttyp für den Dienst Anwendungsidentität auf automatisch setzen

    Für ein zentrales Management dieses Windows-Dienstes empfiehlt sich der Einsatz von Gruppenrichtlinien.

    Regeln definieren

    Nun ist es noch notwendig, Regeln zu definieren, die den Start von Scripts im Temp-Verzeichnis blockieren. Dazu reicht es aus, wenn man unterhalb von AppLocker zu Skriptregeln zu wechseln und dort aus dem Kontextmenü den Befehl Standardregeln erstellen auszu­führen.

    Standardregeln für Scripts in AppLocker erzeugen

    Sie bewirken, dass normale User Scripts nur starten dürfen, wenn sie in den Verzeich­nissen Windows oder Programme gespeichert sind, also an Orten, wo sie selbst keine Dateien ablegen können. Administratoren sind über eine eigene Regel explizit von dieser Einschränkung ausge­nommen.

    Constrained Language Mode über SRP aktivieren

    AppLocker ist bekanntlich ein Feature, das den Editionen Enterprise und Education vorbehalten ist (wenngleich es auch über den Configuration Service Provider für MDM auch in der Pro nutzbar sein soll). Daher kann man in der Pro Edition stattdessen auf die Richtlinien für Software­einschränkung (Software Restriction Policies, SRP) zurückgreifen.

    Auch damit muss man nur sicherstellen, dass sich die beiden Test-Scripts im %temp%-Verzeichnis nicht ausführen lassen. Dazu erstellt man ein GPO und bearbeitet es im Editor unter Computer- bzw. Benutzer­konfiguration => Richtlinien => Windows-Einstellungen => Sicherheits­einstellungen => Richtlinien für Software­einschränkungen.

    Dateiendungen für PowerShell in den Software Restriction Policies eintragen.

    Hier legt man eine neue Richtlinie an und ergänzt im ersten Schritt die Liste der designierten Dateitypen um die Endungen ps1 und psm1.

    Neue Pfadregel für die Softwareeinschränkung erstellen

    Anschließend erstellt man unter Zusätzliche Regeln eine neue Pfadregel. Dort gibt man als Pfad %temp% ein und belässt die Einstellung für Sicherheits­stufe auf Nicht erlaubt.

    Pfadregel für das Temp-Verzeichnis definieren

    Umgehung durch PowerShell 2.0 verhindern

    Unabhängig davon, ob man sich für die Umgebungs­variable, AppLocker oder Application Control entschiedet, muss man in jedem Fall dafür sorgen, dass PowerShell 2.0 auf den Rechnern entfernt, auf denen man den Constrained Language Mode erzwingen will.

    PowerShell 2.0 ist ab Windows 8 und Server 2012 ein optionales Feature und standardmäßig aktiviert.

    Dieser Sprachmodus wurde nämlich erst mit PowerShell 3.0 eingeführt und lässt sich von einem Angreifer leicht unterlaufen, indem er auf eine ältere Version wechselt. Dazu gibt man bloß

    powershell.exe -version 2.0

    ein. Ob diese alte Version auf einem PC noch aktiviert ist, kann man mit

    Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2

    feststellen. Die Deinstallation funktioniert aber erst ab Windows 8 und Server 2012, wo PowerShell 2.0 als optionales Feature vorhanden ist.

    Keine Kommentare