Language mode is an essential feature in PowerShell which defines what all elements can be used in a PowerShell session. Thus, Language mode is a property of the session configuration that is used to create the session. Remote sessions are established using the session configuration of the remote computer. Following are the various types of PowerShell language mode:
Full Language: In this Mode, users can use all the elements of the PowerShell session, and it is the default mode except on Windows RT. Below is how we can see the Default Language Mode
Constrained Language: As the name suggests, there are some constraints in this language mode. This mode is useful to perform routine Admin tasks and yet restricts language elements that can be used to invoke Arbitrary APIs. We will talk about this language mode in the below sections. Below is the way through which default language mode can be changed, and we can see Methods cannot be invoked in Constrained Language mode. Only those methods can be called in this method which have been exclusively exported from the module. This will be discussed in more detail in the later section.
Restricted Language: In this mode, users can execute cmdlets, workflows, functions but are not allowed to execute script blocks. Below we can see that the language mode is changed from Full to Restricted. Upon change, it is not possible to execute the same command again since it cannot refer properties when in Restricted Language Modes
In this mode, only following variables and operators are allowed.
$PSCulture $PSUICulture $True $False $Null -eq (equal) -gt (greater-than) -lt (less-than)
Below we can see that
No Language: In this mode, the user may run command but will not be to use ANY language elements. The commands which are included in System.Management. Automation.Runspaces are only allowed. Below we can see that language mode is changed from Full to NoLanguage and upon change, it does not even support the same command since even the syntax is not supported.
Environment Variable__PSLockdownPolicy also governs all these Language modes in HKLMSYSTEMCurrentControlSetControlSession ManagerEnvironment and often used by group policies to enforce across domains. MS officially documents this variable thus its values are properly defined. Below we can see the how the setting of __PSLockdownPolicy affects the Language Mode. Value of 0 indicates FullLanguage Mode
Value of 4 Indicates ConstrainedLanguage Mode
As these language modes if used properly can be effective in preventing any malicious code to run (if we believe the settings cannot be bypassed) but setting up of these settings without proper evaluation of the existing scripts which are executed remotely and depends on elements as such scripts block can results in breakage in those scripts execution. Now as we are clear about the basics of language modes, let’s deep dive into one of the important language modes, i.e., ConstrainedLanguage Mode. This mode was designed to work with the system User Mode Code Integrity(UMCI) policies. What are UMCI policies? Code Integrity policies are part of a whitelisting solution which was introduced in Windows 10/2016 to block the WSScript-VBS, js, wsf, PowerShell scripts, drivers, user mode binaries which are not allowed explicitly by the policy. This solution is known as Device Guard. Thus, code integrity is a component of Device Guard which enforces both Kernel Mode Code Integrity(KMCI) and User Mode Code Integrity(UMCI). Thus, the scripts which are not listed as a part of UMCI will be enforced to run with the ConstrainedLanguage mode. This can prevent arbitrary unsigned code execution, for example, when put in Constrained Language Mode, the capability to call the Add-Type is restricted which can prevent the creation of arbitrary types. Other important restricted enforced by Constrained Language mode are as below:
As we have seen above in the screenshot, functions need to be explicitly exposed by the module otherwise they cannot be used. Also, the functions need to be explicitly declared while exposing and wildcards are not supported. Only specific whitelisted .NET types are allowed which helps to restrict invoking of arbitrary Win32 APIs. Start-Job is unavailable if the system is not protected by policy since it will start a new process in the Full Language Mode. If the policy is enforced, then it will always run in Constrained Language Mode. XAML based workflows are blocked in ContrainedLangugae mode. Why will we see this in Part 2? Command and even supported commands are not allowed in the DATA section.
So above are some of the restrictions imposed by Constrained Mode. In the next part of this article, we will look at various techniques that have been discovered in the past to bypass the enforced Language Mode.