PowerShell is an Object-Oriented Shell for anyone working with or within the Microsoft Windows ecosystem.
You should never run untrusted code without taking a look at it and understanding it. PowerShell execution policies are the first, but certainly not the only line of defense against malicious PowerShell scripts. Execution policies can help avoid mishaps and possibly some novice attackers, but it is not designed to be a defense mechanism on its own.
Therefore, it is important to know how to utilize these policies and to be aware of possible pitfalls.
Execution Policies and Scopes
Execution policies are set per scope. The policies either restrict or allow running of unsigned code. The scope determines at what level the policies are enforced. You can set them locally, via group policy, or at script launch by adding
-ExecutionPolicy <Policy Name> to
powershell.exe -ExecutionPolicy RemoteSigned -File C:\Scripts\Unsigned_Code.ps1
There are five scopes, four of them have a more permanent nature and one is used during the script runtime.
|CurrentUser||This policy, as the name implies, is set by the current user, for the current user.|
|UserPolicy||This policy is set via group policy at user level.|
|LocalMachine||This policy is set locally for the local machine by a computer administrator. It affects all users.|
|MachinePolicy||This policy is set via group policy at computer level. It affects all users.|
|Process||This is used when running
As shown in the table above, you can use different scopes via different means. Therefore, you have to know in what order you should set the policies.
When applying execution policies locally, the CurrentUser has precedence over MachinePolicy. The same is not true when either MachinePolicy or UserPolicy is configured via group policy. If you have more restrictive MachinePolicy configured, it will override local scope policies, which have lower precedence.
Execution policies are less effective without the group policy enforcement, since local user could easily override the policy, by modifing the scope of UserPolicy.
Setting a policy for each scope is not necessary.
NOTE: You can get an error-like notification when your Execution Policy is set in an ineffective way, such that the machine policy that has lower precedence has stricter policy than the higher precedence user policy, which has a looser policy, thus rendering the stricter machine policy useless. This message wants you to acknowledge the problem in your execution policy, but will actually still set the policy.
There are several execution policies for different use cases. Going from offering no protections at all to potentially keeping the user away from generic malicious scripts, or keeping users from running random scripts that are not approved by IT, although they may not be malicious in nature. You will see that execution policies do not offer a bulletproof safety net when it comes to PowerShell scripts, but it is better to have them configured than not. Additional IT Security measures have to be in place to ensure stricter and more effective code execution policies.
Let’s go over different policies, from the least restrictive to the most restrictive one:
Bypass policy does not restrict anything, nor will it prompt you when you are about to run untrusted code you downloaded from the internet. Use this extremely sparingly and only when you have ensured that the code you are about to run is safe and the environment you are in is adequately protected.
This particular execution policy is used mainly when invoking a new PowerShell session, when there is a need to run a script or a cmdlet with no restrictions (including possible prompts) during the runtime.
The following example will run your script in a new session without the PowerShell logo, user profile or interactive elements. PowerShell window will be hidden and execution policies will not block the script from running. The user will also not be prompted due to the origin of this script.
powershell.exe -NoLogo -NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -Command (Get-Content C:\Scripts\Unsigned_Code.ps1)
To circumvent the execution policy, you would use -Command parameter, instead of -File, which you would use normally to run a script. Even with the Bypass execution policy, using the -File parameter would trip the execution policy, resulting in an error if the policy is configured not to allow running of unsigned code. There are also other ways to go around execution policies1.
This execution policy should not be used as a permanent policy.
Unrestricted policy is similar to the Bypass policy in that it does not stop the user from executing untrusted code, but it will warn the user if the code is downloaded from the internet, so the user is provided a prompt.
This execution policy is default for Windows Servers from Windows Server 2012 R2 and up.
With this policy, the scripts originated from outside of the local network are required to be digitally signed, by a trusted Certificate Authority (CA), otherwise they are not allowed to run, unless you unblock the file beforehand.
You can turn off the warning by unblocking the file using the
Unblock-File cmdlet, which does the same as unblocking the file via its properties:
These restrictions do not apply to scripts originated from the same network you are in.
This policy requires all scripts to be digitally signed by a trusted CA and will prompt you when you are trying to run a signed script that is signed by untrusted certificate provider.
Although this sounds like the safest option, while still maintaining usability of PowerShell, there are ways to circumvent this policy. For example, the malicious script could be signed by a trusted CA, the person running the script can use the Bypass execution policy to temporarily get around this restriction, or by setting CurrentUser policy to something less restrictive. The latter works, when the computer does not have restrictive policies set via group policy.
Despite all of this, you should still have your environment as secure as possible. In an ordinary environment, consisting mostly of regular users, where no random, unsigned scripts should be run, you could use this to avoid accidental executions of unknown code or to attempt to keep users from running unapproved scripts.
Important Note: As is the case with environment-wide changes, you should perform thorough testing before going straight to the most restrictive policy because some legitimate unsigned scripts will suddenly cease to function. That includes both the local scripts and some Microsoft scripts. Make sure that the change will not brake your daily operations.
TIP: You could implement your organization’s CA for code signing and require scripts to be signed by that CA.
This execution policy is default for Windows clients.
Restricted policy allows you to run available cmdlets, but no scripts, PowerShell modules, or PowerShell configuration files regardless of code signing availability.
Policies: Undefined & Default
Undefined and Default policies are in reality more like references than actual policies but they are assigned as you would assign the other policies.
In a fresh installation of Windows, you will see that all scopes have Undefined policies. Undefined however means that if nothing else is specified, Restricted policy is actually in effect.
Default is referring to either Restricted, when working with Windows clients, or RemoteSigned, when working with Windows servers from Windows server 2012 R2 and up.
Querying Execution Policies
Get-ExecutionPolicy, you will be shown the most restrictive policy in place. By adding the List Parameter, you will be shown all the scopes with current policies in place.
Execution Policies in Group Policy
PowerShell Execution Policy Group Policy setting can be found under
Computer or User Configuration - Policies - Administrative Tewmplates - Windows Components - Windows PowerShell - Turn on Script Execution.
You are given the choice between AllSigned, RemoteSigned and Unrestricted Policies from top to bottom.
Code Signing Certificate
Important Note: When requesting a code signing certificate from your CA, you should place the certificate under the Trusted Publishers store, instead of your personal store.
NOTE: No CA related activies, such as setting up a code signing certificate template, requesting the certificate or signing the code are in the scope of this module.
An article covering many ways to bypass the execution policies: 15 Ways to Bypass the PowerShell Execution Policy. ↩