One of the best ways to protect your organization against malicious PowerShell scripts is to leverage the PowerShell execution policies as a tool for restricting the use of scripts. One of the best ways to accomplish this is to configure the execution policy at the Group Policy level. In this article, I will show you how it’s done.
Configuring Group Policy
Microsoft makes it relatively easy to control your PowerShell execution policy enforcement at the Group Policy level. To do so, simply open the Group Policy Editor and load your Group Policy of choice. Next, navigate through the console tree to Computer Configuration\Policies\Administrative Templates\Windows Components\Windows PowerShell. When you do, you should see a Group Policy setting called Turn On Script Execution. You can see what this looks like in the screenshot below. Incidentally, this setting can also be applied at the user level.
You can find the PowerShell-related Group Policy settings at Computer Configuration\Policies\Administrative Templates\Windows Components\Windows PowerShell.
Now, double click on the Turn On Script Execution policy setting, and you will be allowed to configure it. You can see what options exist for this policy setting in the screenshot below.
As you look at the screenshot above, you might notice that Microsoft uses slightly different terminology within the Group Policy setting then they do when you set the execution policy through PowerShell.
Setting the execution policy from within PowerShell involves using the Set-ExecutionPolicy cmdlet, followed by the name of the policy that you want to use. There are presently seven different execution policies recognized by PowerShell. These include:
- AllSigned: All PowerShell scripts must be digitally signed by a trusted publisher.
- Bypass: All scripts are allowed to run, and the user receives no warnings or prompts.
- Default: This setting sets the execution policy to Restricted for Windows client computers, and to RemoteSigned for Windows Server machines.
- RemoteSigned: If a script has been downloaded from the Internet, then it must be signed by a trusted publisher.
- Restricted: No PowerShell scripts are allowed to run.
- Undefined: No execution policy is defined for the given scope. If the execution policy is set to Undefined for all scopes, then the effective policy will be Restricted.
- Unrestricted: All scripts are allowed to run.
By default, the Turn On Script Execution Group Policy setting is not configured, which allows the execution policy to be managed on a per-machine basis. Conversely, if you disable this policy, then it does essentially the same thing as setting the PowerShell execution policy to Restricted.
Enabling the Turn On Script Execution policy allows you to choose between three different execution policy options. The Allow Only Signed Scripts option causes the AllSigned execution policy to be used. Choosing the Allow Local Scripts and Remote Signed Scripts setting sets the execution policy to RemoteSigned. Likewise, choosing the Allow All Scripts option sets the execution policy to Unrestricted.
PowerShell execution policies: What is the benefit?
It’s easy to assume that the primary (and possibly only) benefit to managing PowerShell execution policies at the Group Policy level is that doing so lets you centrally manage PowerShell security. While this is indeed a compelling benefit, there is another major advantage of applying PowerShell execution policies through Group Policy. Take a look at the screenshot below.
As you can see in the screenshot, I set the Turn On Script Execution policy to Disabled. From there, I opened an administrative PowerShell session and then used the GPUpdate /Force command to apply the newly configured Group Policy setting. I then verified that the execution policy had been set to Restricted and then used the Set-ExecutionPolicy command to set the execution policy to Unrestricted. At first, it looks as though PowerShell is going to allow the change. However, PowerShell then informs me that my change is overridden by a policy that is defined at a more specific scope (namely the Group Policy). So even though I am logged in as a domain admin and am using an administrative PowerShell session, PowerShell blocks my attempt to set a new execution policy.
In case you are wondering, PowerShell also blocks any attempt to perform a scope level policy override. In the screenshot below, I listed the execution policies that are in effect for each scope and then attempted to change the policy for a specific scope. Upon doing so, PowerShell produced an error. The same thing happens if I try to set the execution policy to Bypass.
Practice defense in depth
As you can see, setting the execution policy at the Group Policy level can greatly enhance your organization’s security, because even administrators are prohibited from making changes to, or bypassing the PowerShell execution policy. Even so, it is important to understand that execution policies are not the be-all, end-all of PowerShell security.
There are a variety of methods that can be used to circumvent PowerShell’s execution policy. Tools exist, for example, that can turn a PowerShell script into an executable file. PowerShell execution policies do not apply to .EXE files, so the code is allowed to run regardless of any execution policies that may exist.
A simpler method involves a user or administrator simply running a script’s commands one at a time (by pasting them into the command prompt) rather than running the actual script.
My point is that setting a restrictive execution policy is not a guarantee that PowerShell will remain secure. It is therefore important to practice defense in depth. Execution policies are an important security tool, but they need to be used in conjunction with other security mechanisms such as restrictive permissions and PowerShell logging.
Featured image: Freepik / Design vector created by gstudioimagen
More PowerShell Basics articles
- Neat trick: Organizing and formatting messy PowerShell output
- Adding help to your custom PowerShell cmdlets: Step-by-step guide
- Manage Microsoft Teams quickly and easily with PowerShell
- Building custom PowerShell cmdlets the easy way with modules
- Adding custom error messages to your PowerShell scripts