4 Was bringen die Executionpolicies "allsigned, remotesigned" der Security?

Seht euch mal diese kleine "harmlose Zeile" an

GCI "$env:SystemDrive\" -Recurse -EA 0 | Remove-Item -Force -Recurse -EA 0 -whatif 

Solltet ihr dieses Skript (ohne -whatif) auf eurem System ausführen, so geschieht erstmal relativ wenig. Bald aber werdet ihr bemerken, dass alle Daten auf eurem Systemlaufwerk im Nivana verschwinden. Um die unbeabsichtigte Ausführung solcher oder ähnlicher Schadskripte zu verhindern, bietet die Powershell einige Sicherheitsfeatures.

4.1 Umwandeln eines PS - Skriptes in ein lauffähiges Batchfile

Sicherlich ist es besser, die Executionpolicy auf "allsigned" oder "remotesigned" zu setzen, anstatt auf "unsigned". Andererseits kann man Powershellskripte sehr leicht so manipulieren, dass sie auch unsigned überall laufen. Im folgenden den Weg, wie man aus einer unsignierten Powershelldatei eine überall lauffähige *.bat - Datei generiert.

erster Schritt:

Erstellt euch auf einer Maschine ohne Restrictions euer Powershellscript:

#unsigniertes Skript

Get-Process

und speichert es unter einem beliebigen Namen ab. Beispielsweise unter C:\Powershell\test1.ps1

zweiter Schritt:

speichert euch dieses Script am besten direkt neben das erste Skript unter  C:\Powershell\createcmd.ps1

param($Filenames, [bool]$EncodeIt=$false)

if (-not $Filenames)
{
    Write-Host "Usage: createcmd.ps1 [-Filenames] <string[]> [-EncodeIt <bool>]"  
    Write-Host "  Returns a powershell command line with contents of <Filesnames> concatenated and "
    Write-Host "  encoded into a compressed stream which will be uncompressed and invoked on startup."
    Write-Host "  Large code files may exceed 8K cmd limits of DOS and will not load correctly."
    Write-Host "  Do not use EncodeIt on large files. The command line will be too long for DOS to handle."
    Write-Host "    To write to a file that dos can read, use ascii encoding. For example:"
    Write-Host "      PS>.\createcmd.ps1 mycode.ps1 `$false | Out-File mycmd.bat ascii"
    Write-Host "    To concat multiple files together, pass in an array of strings or output from ls like this:"
    Write-Host "      PS>.\createcmd.ps1 `$(ls myfile*.ps1) | Out-File mycmd.bat ascii"
    return;
}
$contents = gc $Filenames;

$ms = New-Object IO.MemoryStream
$cs = New-Object IO.Compression.DeflateStream ($ms, [IO.Compression.CompressionMode]::Compress);
$sw = New-Object IO.StreamWriter ($cs, [Text.Encoding]::ASCII);
$contents | %{
    $sw.WriteLine($_);
    }
$sw.Close();
$code = [Convert]::ToBase64String($ms.ToArray());
$command = "Invoke-Expression `$(New-Object IO.StreamReader (" +
    "`$(New-Object IO.Compression.DeflateStream (" +
    "`$(New-Object IO.MemoryStream (,`$([Convert]::FromBase64String(`"$code`")))), " +
    #"[IO.Compression.CompressionMode]::Decompress)), [Text.Encoding]::ASCII)).ReadToEnd();clear;`"Load complete.`""
    "[IO.Compression.CompressionMode]::Decompress)), [Text.Encoding]::ASCII)).ReadToEnd();`"Load complete.`""
# Command version that builds the code from args passed to the script.
# Don't use. -Command lets you pass args to the command, but -encodedCommand doesn't, which doesn't help with the
# command line length problem.
#$command_using_args = "Invoke-Expression `$(New-Object IO.StreamReader (" +
#    "`$(New-Object IO.Compression.DeflateStream (" +
#    "`$(New-Object IO.MemoryStream (,`$([Convert]::FromBase64String([string]::Join(`"`",`$args)))))," +
#    "[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd();clear;`"Load complete.`""

$doscommand = "powershell.exe -NoExit {0} `"{1}`"";

if ($EncodeIt)
{
    $doscommand -f "-encodedCommand",$([Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($command)));
}
else
{
    $doscommand -f "-Command",$command.Replace("`"", "\`"");
}

 
# aus https://www.trustedsec.com/downloads/tools-download/

Dieses interessante Skript habe ich auf der am Skriptende angegeben Website von TrustedSec gefunden!


3. Schritt

ruft in der Powershell-Shell diesen Befehl auf

PS C:\Powershell> ./createcmd.ps1 test1.ps1 | Out-File Test1.bat ascii

und schon habt ihr eine aufrufbare Batch-Datei, die sich um die Powershell-Executionpolicy herzlich wenig kümmert

powershell.exe -NoExit -Command "Invoke-Expression $(New-Object IO.StreamReader ($(New-Object IO.Compression.DeflateStream ($(New-Object IO.MemoryStream (,$([Convert]::FromBase64String(\"7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGAqsgfP358Hz8iLvJ2e1VX07xpfuPk/wE=\")))), [IO.Compression.CompressionMode]::Decompress)), [Text.Encoding]::ASCII)).ReadToEnd();\"Load complete.\""

Der Code in Schritt 2 konvertiert den Powershellcode des Eingangskript in einen Base64-Ascii Code. In der Batchdatei wird powershell gestartet, welches den Code mit "Invoke-Expression" aufruft.

Aus Securitysicht bringen das Signieren von Powershellskripten und das Setzen von strengen Restrictionpolicies wiegesagt eher wenig.

Anders als im hier erzeugten Beispiel würde ein Skript mit Schadcode sicher versteckt im Hintergrund ablaufen. Wie das zu erreichen ist zeige ich nicht, es ist aber kein Problem.
 

4.2 Normale (=nicht privilegierte) Useraccounts dürfen keine PS-Skripte laufen lassen

Jaaaa(!!), das wäre schön und erwartet man auch. Versucht nämlich ein nicht-priviligierter User auf einem Windows8.1 Client ein Skript zu starten, erhält er erwartungsgemäß diese Meldung



Die Meldung besagt, dass auf diesem System das Ausführen von Skripten deaktiviert ist. Versucht der Anwender die Executionpolicy zu verändern "Set-Executionpoliy unrestricted" wird ihm das ohne Adminrechte selbstverständlich nicht gelingen.

Aaaaber(!!): Was soll die ganze Mimik mit Executionpolicies und so weiter, wenn der vollkommen unprivilegierte Anwender, sich nur ein Shortcut des Skripts erstellen braucht und darüber das Skript ohne jede Einschränkung starten kann:



Das im Shortcut verlinkte Skript läuft ohne einen Fehler durch, obwohl "get-executionpolicy" auf diesem Rechner auf "restricted" steht.
Um die Eingangsfrage nach Sinn- und Zweck der PowershellExecution-Policies wohlwollend zu beantworten: diese Policies können ein versehentliches Ausführen von Skripten verhindern. Viel mehr darf man nicht von ihnen erwarten