PowerShell ExecutionPolicy

Damit ein PowerShell Skript vertrauenswürdig ist, kann der Autor das Skript digital signieren. In Verbindung mit einer entsprechenden Richtlinie auf ihren Computern können Sie damit die Ausführung von fremden, unbekannten oder nicht verifizierte Skripte unterbinden.

Set-ExecutionPolicy

Die meisten Administratoren werden mit der Codesignatur in Berührung gekommen sein, wenn Sie ein Skript aus dem Internet auf einem Client einfach ausführen wollten und dies verhindert wurde. Die Standardeinstellungen eines Windows PCs steht auf "RemoteSigned". Starten Sie einfach eine PowerShell und führen sie folgendes Commandlet aus:

# Standardeinstellung auf einem Windows Client
Get-ExecutionPolicy -List | ft -AutoSize

        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine       Undefined

Für ihre Umgebung gilt natürlich nur eine effektive Richtlinie, d.h. hier ist die Priorität zu beachten. Der Default Scope beim Setzen einer Richtline mit "Set-ExecutionPolicy" ist "Local Machine". Das geht natürlich nur als Administrator und die PowerShell informiert sie.

# PowerShell 2-5
Set-ExecutionPolicy : Access to the path 'C:\Program Files\PowerShell\6\powershell.config.json' is denied.
To change the execution policy for the default (LocalMachine) scope, start PowerShell with the "Run as administrator" 
option. To change the execution policy for the current user, run "Set-ExecutionPolicy -Scope CurrentUser".

#PowerShell 6-x
Set-ExecutionPolicy : Der Zugriff auf den Registrierungsschlüssel
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" wurde verweigert. Starten Sie zum
Ändern der Ausführungsrichtlinie für den Standardbereich (LocalMachine) Windows PowerShell mit der Option "Als
Administrator ausführen". Führen Sie zum Ändern der Ausführungsrichtlinie für den aktuellen Benutzer

Achtung:
Sie sehen schon am Fehler, dass die Speicherorte für die Richtlinien für Powershell 1-5 und 6-x an unterschiedlichen Stellen verwaltet werden. PowerShell Core läuft ja auch auf Linux u.a., wo es keine Registrierung gibt.

Der zweite Aspekt ist die Vererbung von Richtlinien. Sie können gerne eine Richtlinie auf "LocalMachine" setzen, aber eine Richtlinie per GPO gewinnt. Darauf weist Sie die PowerShell aber auch hin.

PS> Set-ExecutionPolicy -ExecutionPolicy Restricted -Scope LocalMachine 

Set-ExecutionPolicy : PowerShell updated your local preference successfully, but the 
setting is overridden by the Group Policy applied to your system. Due to the override, 
your shell will retain its current effective execution policy of "AllSigned". 
Contact your Group Policy administrator for more information.

Damit haben aber Administratoren eine sehr gute Kontrolle, welche Skripte wo ausgeführt werden. Speziell Clients mit "normalen Anwendern", die als Einfallstor für Malware genutzt werden können, sind so gut zu blocken.

Ausführung geblockt

Die Standardpolicy für Skripte eines Windows Clients lautet auf "Restricted" und verhindert den einfachen Start von PowerShell.

PS C:\End2End> .\end2end-http.ps1
.\end2end-http.ps1 : Die Datei "C:\End2End\end2end-http.ps1" kann nicht geladen werden, da die Ausführung von Skripts
auf diesem System deaktiviert ist. Weitere Informationen finden Sie unter "about_Execution_Policies"
(https:/go.microsoft.com/fwlink/?LinkID=135170).

Das ist aber kein 100% Schutz, denn der Anwender kann diese Blockade mit ein paar Handgriffen umgehen. Viele Firmen erlauben aber schon lokale Skripte, wenn diese nicht aus dem Internet heruntergeladen wurden oder von einem UNC-Pfad kommen. Dazu stellen Sie die Richtline dann auf "RemoteSigned" um. Sicherer ist das aber nicht. Interessanter ist da eher die Vorgabe "AllSigned"

Set-ExecutionPolicy -ExecutionPolicy AllSigned -scope LocalMachine

Wenn ein Anwender auf seinem Client dann versucht ein nicht signiertes Skript zu starten, dann kann er folgende Meldung sehen.

PS C:\End2End> .\end2end-http.ps1
.\end2end-http.ps1 : Die Datei "C:\End2End\end2end-http.ps1" kann nicht geladen werden. Die Datei "C:\End2End\end2end-http.ps1"
ist nicht digital signiert. Sie können dieses Skript im aktuellen System nicht ausführen. Weitere Informationen zum Ausführen von
Skripts und Festlegen der Ausführungsrichtlinie erhalten Sie unter "about_Execution_Policies"

Sie können die Ausführung z.B. auf signierte Skripte beschränken, und ihre eigenen Skripte durch eine eigenes CodeSigning-Zertifikat ihrer eigenen PKI signieren. Das ist schon ein guter Schutz aber kein 100% Schutz, da auch Malware-Autoren z.B. CodeSigning-Zertifikate mit gefälschten Identitäten kaufen und ihre Malware signieren können. Aber es ist dennoch eine Überlegung wert.

Allerdings kann ein Anwender je nach Kenntnisstand die Richtlinien auch umgehen. Sie gelten nämlich nur, wenn die PowerShell den Code interpretiert. Es gibt aber zwei sehr einfache Optionen, die Mitarbeiter nutzen können.

  • Powershell ISE
    Sie starten einfach die ISE und öffnen dort die PS1-Datei. In der ISE können Sie das Skript auch ausführen und hier kommt die Default ExecutionPolicy nicht zur Anwendung.
  • Powershell.exe mit "-Eexecutionpolicy remoteSigned" oder "-Executionpolicy bypass" starten
    Für die dann geöffnete PowerShell gilt die ExecutionPolicy, die auf der Kommandozeile mit übergeben wurde
  • Zeilenweises Ausführen
    Nicht verhindern können sie, dass ein Anwender das Skript einfach per Zwischenablage in ein PowerShell Fenster einfügt. Dann wird jede Zeile einzeln ausgeführt. Es ist dann kein "Skript"

Wobei beide Optionen nur eine für den Anwender oder lokal gesetzte Richtline überstimmen. Wenn Sie per Kommandozeile einen von per Gruppenrichtlinien vorgegebenen Policy abweichen, dann greift diese nicht. Aber dann gibt es noch mindestens 13 andere Wege.

Wenn Sie hier "dicht" sein wollen, dann sollten Sie sie sich mal Applocker und SmartScreen anschauen.

ExecutionPolicy per Kommandozeile

Die ExecutionPolicy kann auf dem Computer pro Benutzer oder Computer vorgegeben werden. Über eine Richtlinie kann diese sogar festgeschrieben werden. Weniger bekannt ist aber die Option, beim Start der PowerShell selbst schon eine ExecutionPolicy mitzugeben und damit Richtlinien sogar zu umgehen. Sie starten dazu zuerst eine Shell (CMD oder PowerShell), aus der sie dann PowerShell.EXE mit Parametern aufrufen. Hier ein Beispiel eines Computers, der als Default die ExecutionPolicy "RemoteSigned" hat.

C:\>powershell.exe
Windows PowerShell
Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.

PS C:\> Get-ExecutionPolicy
RemoteSigned

PS C:\> powershell.exe -executionpolicy unrestricted
Windows PowerShell
Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.

PS C:\> Get-ExecutionPolicy
Unrestricted

PS C:\> powershell.exe
Windows PowerShell
Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.

PS C:\> Get-ExecutionPolicy
Unrestricted

Über den Umweg kann ein Anwender die Richtlinienvorgabe temporär überstimmen. Wenn ici aus einer PowerShell wieder eine PowerShell starte, ererbt sie sogar die ExecutionPolicy. Die Online-Hilfe zeigt dazu:

C:\>powershell /?

-ExecutionPolicy
Legt die standardmäßige Ausführungsrichtlinie für die aktuelle Sitzung fest und speichert sie
in der $env:PSExecutionPolicyPreference-Umgebungsvariablen.
Durch diesen Parameter wird die Windows PowerShell-Ausführungsrichtlinie,
die in der Registrierung festgelegt ist, nicht geändert.


C:\>powershell -executionpolicy remotesigned
PS C:\> Get-ExecutionPolicy
RemoteSigned

Achtung: Wenn Sie sich beim Wert vertippen, gibt es keine Fehlermeldung  sondern übernimmt die "Default Richtlinie"

Ausführen von Skripten

Als Administrator können Sie die Policy mit "Set-ExecutionPolicy" setzen. Dabei gibt es nicht nur ein "Aus, Signiert, Ein", sondern Windows kann sich pro Datei auch merken, aus welcher Quelle Sie kommt. Eine Datei kann auf einer lokalen Festplatte oder einem UNC-Pfad liegen oder aus der Internet heruntergeladen worden sein. Je nach Policy werden Skripte also ausgeführt oder nicht:

Policy lokal unsigniert Lokal signiert Remote unsigniert Remote signiert Internet unsigniert Remote signiert Beschreibung

Unrestricted

Diese Einstellung gilt für "nicht Windows-Systeme" seit PowerShell 6 und kann wohl nicht geändert werden. Es werden alle Skripte ausgeführt aber unsignierte Skripte aus dem Internet erzeugen eine Rückfrage

RemoteSigned

Lokale Skripte werden unabhängig von einer Signatur ausgeführt. Skripte über UNC-Pfade oder mit der "Internet-Zone" müssen signiert sein. Dies ist die Standardeinstellung für Windows Server

AllSigned

Alle Skripte müssen signiert werden. Unsignierte Skripte werden nicht ausgeführt. Dies ist eine sehr gute Policy für Desktops und Server, auf denen Administratoren Skript aus vielleicht unbekannten Quellen einsetzen. Es kann aber bei Produktinstallationen wie Exchange störend sein, da hier auch PowerShell zum Einsatz kommt

Restricted

Es werden keine Skripte ausgeführt. Dies ist der Default für Windows Clients

Default

Setzt die Standardeinstellung des Betriebssystems. (Server = RemoteSigned, Client=Restricted

Bypass

Keine Warnungen oder Prompts

Undefined

Entfernt eine eventuell manuell gesetzte Richtlinie. Es kommt die Richtline gemäß der Vererbung zum Tragen. Wenn alle Richtlinien "undefined" sind, dann ist der Default wieder "Restricted

Eine Datei, die aus dem Internet herunter geladen wurde, können Sie einfach über die Eigenschaften der Datei mit dem Windows Explorer wieder "freigeben".

Alternativ geht es auch per "Unblock-File" in der PowerShell.

  • Unblock-File
    https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/unblock-file?view=powershell-6

Constrained Language Mode

Neben der Execution Policy, die komplett die Ausführung eines Skripts ggfls. unterbindet, gibt es mit dem "Constrained Language Mode" eine weitere Funktion zur Beschränkung von Funktionen in PowerShell-Skripten. Sobald der Mode aktiv ist, funktionieren einige Dinge nicht mehr, z.B.:

  • ScheduledJobmodule-Mist deaktiviert
  • COM Objekte können nicht mehr aufgerufen werden
  • Module müssen Funktionen explizit exportieren, damit sie genutzt werden können
  • Invoke-Expression startet Code immer im Constrained Language Mode
  • Keine implizite Typkonvertierung. Ich muss explizit Konvertierungen anstoßen.

Das ist nur eine Teilmenge. Eine umfangreiche Liste gibt es auf:

Sie sehen schon, dass gerade die Dinge blockiert werden, die auch von Malware gerne genutzt wird. Es zwingt aber auch einen Administrator, möglichst sauber zu programmieren.

# Mode per PowerShell setzen

# Anzeigen der aktuellen Mode
$ExecutionContext.SessionState.LanguageMode

# Constrained Mode setzen
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"

Es ist natürlich kein Schutz, wenn ich in der PowerShell selbst die Beschränkung wieder aufheben kann. Es gibt aber einen nicht dokumentierten Weg über eine systemweise Umgebungsvariable, die in der Regel nur ein lokaler Administrator setzen und ändern kann.

Mode per CMD.EXE setzen
REM Enable Constrained Language Mode:

setx __PSLockdownPolicy "4" /M

REM Disable Constrained Language Mode: (revert to Full Language Mode)  

setx __PSLockdownPolicy "0" /M

So können Sie den Mode auch per Gruppenrichtline o.ä. zumindest für "normale Anwender" erzwingen. 

Just Enough Admin

Und dann gibt es noch ein weiteres Konzept um das Schadpotential von PowerShel-Skripten zu reduzieren.

Weitere Links