Die Powershell ist ein mächtiges, administratives Werkzeug. Viele Tätigkeiten lassen sich automatisieren. Fast alle Bereiche der Microsoft-Produkte lassen sich so steuern. Und die Powershell ist nativ mit an Bord. Jedes moderne Betriebssystem hat sie dabei.
Da ist es nur natürlich, dass auch unsere Hacker-Kollegen seit Langem einen Gefallen an dieser Plattform gefunden haben. Es existieren etliche Schadcodes für eine Vielzahl von Angriffen…
Doch auch Microsoft hat nicht (mehr) geschlafen! In der aktuellen PowerShell-Version gibt es einige interessante Schutzmechanismen. Diese möchte ich in einer Serie einmal vorstellen.
Für einige der neuen Schutzmöglichkeiten wird die PowerShell-Version 5 benötigt. Diese gehört zu Windows 10 und Windows Server 2016 standardmäßig zur Grundausstattung. Auf älteren Systemen kann die PowerShell natürlich aktualisiert werden. Davon halte ich persönlich nicht viel, denn zu oft habe ich danach Probleme auf Clients und Servern beobachten dürfen. Aber auch für diese Systeme gibt es ein paar Einstellungsmöglichkeiten.
Generell halte ich es nicht für sinnvoll, die PowerShell einfach zu deaktivieren bzw. zu blockieren. Sie ist so tief im System verankert, dass ein geübter Angreifer es dennoch schaffen wird, auf einen PS-Prozess zuzugreifen. Und zudem ist sie für das Daily-Business einfach zu wertvoll!
Für die Angriffe habe ich eines meiner PSHacking-Scripte ausgewählt.
Und um einen Enterprise-Charakter darzustellen werde ich die Konfiguration natürlich über Gruppenrichtlinien vornehmen. Dazu steht in meiner LAB-Umgebung ein kleiner DomainController bereit.
Die Szenarien sind extrem vielfältig. Da die PowerShell auch auf das gesamte .net-Framework und alle WMI-Repositories zugreifen kann ist hier der Fantasie kaum eine Grenze gesetzt. Einige interessante Beispiele kommen gleich in meinen Szenarien vor.
In meinem Beispiel verwende ich einen Code, mit dem die Internet-Explorer-Passworte aus dem Credential-Manager ausgelesen werden. Das funktioniert für Benutzer mit und ohne administrative Berechtigungen und der Code ist nicht besonders lang:
$ClassLoader = [Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime] $PasswordVault = new-object Windows.Security.Credentials.PasswordVault $PasswordVault.RetrieveAll() | ForEach-Object { $_.RetrievePassword() ; $_ } | Select-Object -Property Resource, UserName, Password | Sort-Object Resource | Format-Table -AutoSize
Es ist also ideal für eine Demonstration. Die erforderliche Klasse existiert aber erst seit Windows 8.x. Daher wird das auf Windows 7 nicht funktionieren. Egal, denn ich verwende ein aktuelles Windows 10.
Szenario – PowerShell Script Execution
Die PowerShell verwendet seit langer Zeit eine ExecutionPolicy. Mit dieser kann gesteuert werden, ob Scripte für die Ausführung digital signiert sein müssen. Dabei werden verschiedene Ebenen unterschieden:
Zusätzlich kann dabei ein Speicherort ausschlaggebend sein: RemoteSigned setzt für die Scriptausführung die digitale Signatur nur voraus, wenn das Script nicht auf dem lokalen Rechner gespeichert ist.
Die digitale Signatur soll sicherstellen, dass der Code unverändert von einem vertrauenswürdigen Programmierer stammt. Sollte der Code (Text) manipuliert worden sein, so ist die digitale Signatur nicht länger gültig.
Ein Angreifer könnte also ohne eine Signatur sein Script auf einem System ausführen:
Mit einer erforderlichen Scriptsignierung sollte das nach der Idee von Microsoft verhindert werden. Die Signierung kann lokal festgelegt werden:
Dennoch kann ein Angreifer mit den erforderlichen Rechten die lokal definierte Signierungsanforderung wieder genauso rückgängig machen:
Besser und vor allem effizienter wäre die zentrale Konfiguration mit einer Gruppenrichtlinie:
Nach dem Anwenden der GPO werden neue PowerShell-Prozesse entsprechend konfiguriert sein:
Wenn nun der Admin die Regel lokal außer Kraft setzen will, gewinnt die GPO:
Wie wirkt nun die Einstellung? Benutzer, die nun ein Script ohne Signratur starten wollen werden abgewiesen:
Nur leider existieren einige Optionen, die Richtlinie zu umgehen. Z.B. OHNE die GPO (also wenn die Executionpolicy von einem Admin lokal definiert wurde) kann sogar ein Benutzer die Einstellung aushebeln ☹. Denn die PowerShell lässt sich auch mit dem Parameter -ExecutionPolicy starten. Und dieser überschreibt die lokalen settings für den neuen Prozess:
Wird die Regel dagegen über eine GPO definiert, dann ist dies sogar für den Administrator unmöglich:
Aber der Angreifer könnte den Code auch einfach „tippen“. Dann ist es eben kein Script mehr :
Oder der Code wird zu BASE64 konvertiert und z.B. als Batch-Script gestartet:
Die Erzwingung einer Scriptsignatur wird Schadcode nicht effektiv aufhalten! Ich persönlich nutze die Scriptsignatur eigentlich nur noch, um Manipulationen an meinen Scripten durch andere Admins zu erkennen.
Gleiches gilt natürlich auch, wenn die Scriptsignatur-Überwachung durch Applocker realisiert wird. Selbst diese lässt sich mit EncodedCommands oder durch „Tippen“ umgehen… 🙁
Fazit
Aus meiner Sicht hat Microsoft noch einiges an Arbeit vor sich, um das nützliche Werkzeug PowerShell vernünftig
abzusichern. Erste Ansätze sind erkennbar. Ich bleibe auf jeden Fall dran. Ihr auch?
Stay tuned!
PS: wer mag, kann meine ersten 5 Szenarien zur PS-Absicherung auch hier als PDF herunterladen. Die GPOs sind als Backup und html-Report natürlich auch mit dabei: WSHowto – PowerShell-Security