PowerShell Constrained Language Mode
The PowerShell execution policy restricts the execution of
scripts, but this is a weak protection mechanism
which can be easily bypassed
with the built-in “Bypass” execution policy.
However, the more robust Language Modes avoid
execution of code like our shellcode runner
and operates at three distinct levels.
The first, and default level, FullLanguage, allows all cmdlets
and the entire .NET framework as well as C# code execution.
By contrast, NoLanguage disallows all script text.
RestrictedLanguage offers a compromise, allowing default
cmdlets but heavily restricting much else.
These settings are relatively uncooperative.
For example, it would be difficult to allow
administrative execution, while allowing execution of scripts
we trust and blocking scripts belonging to a user,
malicious or otherwise.
To address this, Microsoft introduced the
ConstrainedLanguage mode (CLM) with PowerShell version 3.0.
When AppLocker, or WDAC, is enforcing whitelisting rules
against PowerShell scripts,
ConstrainedLanguage mode is enabled as well.
Under ConstrainedLanguage mode, scripts that are located in
whitelisted locations or otherwise comply with
a whitelisting rule can execute with full functionality.
However, if a script does not comply with the rules,
or if commands are entered directly on the command line,
ConstrainedLanguage mode imposes numerous restrictions.
The most significant limitation excludes calls to the .NET
framework, execution of C# code and reflection.
To demonstrate this, let’s open a PowerShell prompt
in the context of the “student” user,
and attempt to invoke the .NET framework.
As evidenced by the warning, we cannot access the otherwise
simple cosine function in the Math namespace of .NET.
This warning is indicative of constrained language mode.
The language mode of the current PowerShell session or prompt
is always stored in the
$ExecutionContext.SessionState. LanguageMode variable
which can be displayed as follows:
In contrast, let’s open a second PowerShell prompt with
administrative privileges in the context of the “Offsec” user,
and dump the contents of the same variable:
Obviously this is our preferred language mode,
as it is unrestricted,
allowing us to reuse all our previous tradecraft.
However, in the next section we’ll dig deeper into .NET
and develop code that will bypass constrained language mode