- FileZilla: Migrate settings and connections, read stored passwords - Fri, Jan 21 2022
- Microsoft Edge: Open new tab without MSN news, configure start pages with GPO - Tue, Jan 4 2022
- Turn off web search in Windows 11 using Group Policy - Tue, Dec 28 2021
By default, PowerShell operates in Full Language mode, in which all functions are available. This includes access to all language elements, cmdlets, and modules, as well as the file system and the network.
Blocked functions ^
The ability to instantiate COM and .NET objects or to generate new data types (with Add-Type) that have been defined in other languages is a particularly dangerous PowerShell capability. Constrained Language mode blocks these features (except access to permitted .NET classes). It also prevents the declaration of classes, usage of configuration management with DSC, and XAML-based workflows (see Microsoft Docs for a complete list).
Enabling Constrained Language mode ^
A simple way to switch to Constrained Language mode is to set the relevant variable to the required value:
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
It is obvious that setting this variable does not provide any real protection. You may not be able to change it back to FullLanguage in the same session; however, a new PowerShell session will offer the full range of languages features.
Switching to Constrained mode with an environment variable ^
Less easy to overcome is the (undocumented) system environment variable __PSLockDownPolicy, if you set it to the value 4. As a result, PowerShell will start in the secure language mode, regardless of whether it's just a command line or the ISE.
In centrally managed environments, you will probably use Group Policies to set the system variable.
A disadvantage of this procedure is that it always affects all users of a computer, including administrators. However, administrators may temporarily remove the environment variable until the GPO becomes effective again. But this is quite cumbersome and definitely not a good solution.
Furthermore, used in this way, it is not a security feature supported by Microsoft and is relatively easy to circumvent, as shown by Matt Graeber in this tweet. Nevertheless, it might thwart most opportunist attacks.
Strict enforcement of Constrained Language mode on a local computer thus requires the use of a software execution restriction, such as AppLocker or Windows Defender Application Control. In a remote session, however, it can be enforced through session configuration.
Automatically detecting an execution constraint ^
Since version 5, PowerShell recognizes automatically whether it should switch to Constrained Language mode based on script rules. To do so, it creates a module and a script (with a name following the pattern __PSSCRIPTPOLICYTEST_LQU1DAME.3DD.PS1) under $env:temp and tries to execute them. If AppLocker or another tool blocks this attempt, PowerShell starts in Constrained Language mode.
The effect of this mechanism can easily be seen in AppLocker's event log. AppLocker logs the creation and execution of these test files with the ID 8005 (success) or 8007 (execution blocked) under Applications and Services Log > Microsoft > Windows > AppLocker > MSI and Script.
Configuring AppLocker ^
If you use AppLocker for this task, you have to create a new GPO and then edit it in the GPO editor. Navigate to Computer Configuration > Policies > Windows Settings > Security Settings > Application Control Policies > AppLocker and follow the Configure rule enforcement link. In the dialog that appears, select the Script rules option.
In order for AppLocker to block applications on the target systems, the Application Identity service must be running. It is not active by default and does not start up when the system is booting. You can change it to start type Automatic either interactively using the MMC snapin services or from the command line:
sc config AppIDSvc start=auto
For central management of this Windows service, the use of Group Policy is recommended.
Defining rules ^
Finally, rules must be defined that block the start of scripts in the Temp directory. To do this, simply switch to Script Rules below AppLocker and select Create Default Rules from the context menu.
They allow standard users to execute scripts only from the Windows or Program Files directories, i.e., in locations where users cannot store any files themselves. Administrators are explicitly exempted from this restriction by a separate rule.
Activating Constrained Language mode via SRP ^
AppLocker is a feature found exclusively in the Enterprise and Education editions. The Pro edition can use the Software Restriction Policies (SRP) instead. Again, you just have to ensure that the two test scripts cannot be executed in the %temp% directory. To do this, create a GPO, open it in the editor, and navigate to Computer Configuration > Policies > Windows Settings > Security Settings > Software Restriction Policies.
Here, you create a new policy. In the first step, you add the extensions ps1 and psm1 to the list of the designated file types.
Then select Additional Rules > New Path Rule to create a new rule. Here, you enter %temp% as the Path and leave the Security level setting set to Disallowed.
Preventing PowerShell 2.0 circumvention ^
Regardless of whether you choose the environment variable, AppLocker, or Software Restriction Policies, you will need to remove PowerShell 2.0 from the machines on which you want to enforce Constrained Language mode.
Constrained Language mode was introduced with PowerShell 3.0 and can easily be bypassed by a hacker switching to an older version. All he would need to do is enter the command:
powershell.exe -version 2.0
You can check whether this old version is still activated on a PC by entering:
Subscribe to 4sysops newsletter!
Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2
However, you can only uninstall it on Windows 8 and Server 2012 or later, where PowerShell 2.0 is an optional feature.