Nun stellt sich bei mir die Frage: Gibt es noch weitere Verzeichnisse innerhalb der Standardregel-Verzeichnisse von Applocker, in denen ein Standardbenutzer Schreibrechte hat? Mit einem einfachen Script versuche ich über die PowerShell, in jedem Unterverzeichnis als Standardbenutzer eine Datei zu schreiben. Wenn dies gelingt, dann ist das Verzeichnis ein Bypass-Kandidat. Das ist mein Code:
trap {'continue'}
$RootFolders = @()
$RootFolders += Get-ChildItem -Path 'C:\' -Directory |
Where-Object {$_.fullname -notlike 'c:\users*'} |
Select-Object -ExpandProperty fullname
$RootFolders += 'c:\Programdata'
Get-ChildItem $RootFolders -Directory -Recurse -ErrorAction SilentlyContinue |
ForEach-Object {
$Pfad = $_.FullName
try {
'test' | out-file -FilePath ($Pfad + '\test.txt')
Write-Host $Pfad -ForegroundColor Green
Remove-Item -Path ($Pfad + '\test.txt') -ErrorAction stop
}
catch { }
}
Der erste Block definiert die Hauptverzeichnisse, in denen schreibbare Verzeichnisse gesucht werden sollen. Durch das Try-Catch werden nur Verzeichnispfade gelistet, in denen das Schreiben der test.txt erfolgreich war. ACHTUNG: ggf. hat ein Standardbenutzer ein Schreibrecht aber kein Löschrecht – es können also durchaus Testdateien im System verbleiben
Nach einer kurzen Laufzeit kommt folgendes Ergebnis zustande:

Das hat mich überrascht!!! Besonders perfide finde ich den Ordner AntiMalwareTest… Aber da sind auch Verzeichnisse gelistet, die der Applocker abdeckt – z.B. c:\Programdata. Also erweitere ich meinen Test im Script auf das Erstellen und Starten einer Anwendung in einem Verzeichnis:
$CleanUpDirs = @()
trap {'continue'}
$RootFolders = @()
$RootFolders += Get-ChildItem -Path 'C:\' -Directory |
Where-Object {$_.fullname -notlike 'c:\users*'} |
Select-Object -ExpandProperty fullname
$RootFolders += 'c:\Programdata'
write-host "Verzeichnisse mit Recht 'Schreiben und Ausfuehren' ohne Applocker-Schutz:" -ForegroundColor White
Get-ChildItem $RootFolders -Directory -Recurse -ErrorAction SilentlyContinue | ForEach-Object {
$Pfad = $_.FullName
try {
Copy-Item -Path C:\Windows\System32\cmd.exe "$Pfad\ApplockerTest.exe" -ErrorAction Stop
Start-Process -FilePath "$Pfad\ApplockerTest.exe" -WorkingDirectory $Pfad
Stop-Process -Name ApplockerTest -ErrorAction Stop
# Platzhalter für ApplockerPolicyCreator
$error.clear()
Remove-Item -Path "$Pfad\ApplockerTest.exe" -ErrorAction Silentlycontinue
if ($error) {
$CleanUpDirs += $Pfad
} else {
Write-Host " $Pfad" -ForegroundColor Green
}
}
catch {
if (Test-Path -Path "$Pfad\ApplockerTest.exe") {
$error.clear()
Remove-Item -Path "$Pfad\ApplockerTest.exe" -ErrorAction Silentlycontinue
if ($error) { $CleanUpDirs += $Pfad }
}
}
}
write-host "Verzeichnisse mit Recht 'Erstellen ohne Ausfuehren' (manuell bereinigen):" -ForegroundColor White
$CleanUpDirs | ForEach-Object { Write-Host " $_" -ForegroundColor Yellow }
Das Ergebnis ist nicht mehr ganz so dramatisch. Die grünen Einträge sind fehlerhaft vom Applocker geschützt. Die gelben lassen zwar das Erstellen von Dateien zu – nicht aber die Ausführung (keine Execute-Berechtigung):

OK, für alle gefundenen Verzeichnisse kann nun eine Applocker-Deny-Regel erstellt werden. Die Verzeichnisberechtigungen selber würde ich nicht anfassen. Wer weiß, was danach alles nicht mehr funktioniert… Die Policies möchte ich aber nicht von Hand zusammenstellen. Dafür gibt es doch die PowerShell Im Script gibt es einen Platzhalter-Kommentar. Hier kann folgender Code eingefügt werden, um für die gefundenen Verzeichnisse eine Applocker-Regel im XML-Dateiformat zu generieren:
$Filename = $Pfad -replace '\\','-' -replace ':'
$XML = Get-AppLockerFileInformation -Path "$Pfad\ApplockerTest.exe" |
New-AppLockerPolicy -RuleType path -User everyone -Xml
$XML = $XML -replace '"Allow"','"Deny"' -replace "ApplockerTest.exe",'*'
$XML = $XML -replace 'Description=""','Description="verhindert Applocker-Bypass"'
$XML | Out-File -FilePath "$XMLVerzeichnis\$Filename.xml"
Zusätzlich muss vor dem Code das Verzeichnis für die XML-Dateien erstellt werden:
$XMLVerzeichnis = "c:\ApplockerXMLs"
if ((Test-Path -Path $XMLVerzeichnis) -eq $false) {
New-Item -Path $XMLVerzeichnis -ItemType directory | Out-Null
}
Dann erstellt der Code zur Laufzeit diese Dateien. Jede Datei ist eine Applocker-DenyRule für ein gefundenes Verzeichnis:

Auf dem DomainController können diese XML-Dateien dann mit der PowerShell direkt in die bereits vorhandene GPO übernommen werden:
# Variablen
$BackupDir = "C:\admin\GPOBackup"
$XMLVerzeichnis = "c:\ApplockerXMLs"
# suche und sichere die GPO auf dem PDC
if ((Test-Path -Path $BackupDir) -eq $false) {
New-Item -Path $BackupDir -ItemType directory | Out-Null
}
$GPO = Get-GPO -All | Where-Object { $_.Displayname -eq 'GPO-Computer-Security-Applocker' }
Backup-GPO -Guid $GPO.id -Path $BackupDir | Out-Null
$GPO = $GPO.path
$PDC = (Get-ADDomain).PDCEmulator
# erstelle für jedes Bypass-XML eine Deny-Ausnahme in der GPO
Get-ChildItem -Path $XMLVerzeichnis | ForEach-Object {
Set-AppLockerPolicy -XmlPolicy $_.FullName -Ldap "LDAP://$PDC/$GPO" -Merge
}
Die GPO ist dann entsprechend erweitert:

Achtung: In meinem Script habe ich nicht getestet, ob in den gefundenen Verzeichnissen noch andere Anwendungen liegen, die von Microsoft dort für bestimmte Aufgaben abgelegt wurden. Im realen Leben prüft ihr das bitte genauer!