Sunday, August 7, 2011

PowerShell ExecutionPolicy Bypass

PowerShell is exciting and has really taken off as the replacement for Vbscript.  I hope to blog more about the awesome features of PowerShell in the future, but I will start off with a simple bypass of Execution Policies so that you can use your scripts.  Execution policies are seen as a "security" feature by many administrators.  This policy will not allow scripts to be run unless they meet the requirements of the policy.  To find out more about "ExecutionPolicy" use the get-help cmdlet from within PowerShell:

PS C:\Users\Chris> get-help Set-ExecutionPolicy -examples

NAME Set-ExecutionPolicy
SYNOPSIS Changes the user preference for the Windows PowerShell execution policy.
    -------------------------- EXAMPLE 1 --------------------------
    C:\PS>set-executionpolicy remotesigned
    This command sets the user preference for the shell execution policy to RemoteSigned.
    -------------------------- EXAMPLE 2 --------------------------
    C:\PS>Set-ExecutionPolicy Restricted
    Set-ExecutionPolicy : Windows PowerShell updated your local preference successfully, but the setting is overridden by the group policy applied to your system. Due to the override, your shell will retain its current effective execution policy of "AllSigned". Contact your group policy administrator for more information.
    At line:1 char:20   + set-executionpolicy  <<<< restricted
    This command attempts to set the execution policy for the shell to "Restricted." The "Restricted" setting is written to the registry, but because it conflicts with a Group Policy, it is not effective, even though it is more restrictive than the policy.
    -------------------------- EXAMPLE 3 --------------------------
    C:\PS>invoke-command -computername Server01 -scriptblock {get-executionpolicy} | set-executionpolicy -force
    This command gets the execution policy from a remote computer and applies that execution policy to the local computer.
    The command uses the Invoke-Command cmdlet to send the command to the remote computer. Because you can pipe an ExecutionPolicy (Microsoft.PowerShell.ExecutionPolicy) object to Set-ExecutionPolicy, the Set-ExecutionPolicy command does not need an ExecutionPolicy parameter.
    The command does have a Force parameter, which suppresses the user prompt.
    -------------------------- EXAMPLE 4 --------------------------
    C:\PS>set-executionpolicy -scope CurrentUser -executionPolicy AllSigned -force
    C:\PS> get-executionpolicy -list
           Scope            ExecutionPolicy
            -----                 ---------------
    MachinePolicy         Undefined
       UserPolicy            Undefined
          Process              Undefined
      CurrentUser           AllSigned
     LocalMachine      RemoteSigned
    C:\PS> get-executionpolicy
    This example shows how to set an execution policy for a particular scope.
    The first command uses the Set-ExecutionPolicy cmdlet to set an execution policy of AllSigned for the current user. It uses the Force parameter to suppress the user prompts.
    The second command uses the List parameter of Get-ExecutionPolicy to get the execution policies set in each scope. The results show that the execution policy that is set for the current user differs from the execution policy set for all users of the computer.
    The third command uses the Get-ExecutionPolicy cmdlet without parameters to get the effective execution policy for the current user on the local computer. The result confirms that the execution policy that is set for the current user takes precedence over the one set for all users.
    -------------------------- EXAMPLE 5 --------------------------
    C:\PS>set-executionpolicy -scope CurrentUser -executionPolicy Undefined
    This command uses an execution policy value of Undefined to effectively remove the execution policy that is set for the current user scope. As a result, the execution policy that is set in Group Policy or in the LocalMachine (all users) scope is effective.
    If you set the execution policy in all scopes to Undefined and the Group Policy is not set, the default execution policy, Restricted, is effective for all users of the computer.

Although the descriptions read like they are security features, that's not the case as evidenced in David Kennedy and Josh Kelley's "PowerShell OMFG" talk at Defcon last year.  One of the things that they pointed out is that you can encode a script and pass it directly to PowerShell.

For example, lets try to launch a simple PowerShell script that executes calc.exe with the ExecutionPolicy set to restricted.

Although this example uses PowerShell 1.0, it also works with 2.0.  Notice that the error points out that execution of scripts are disabled.  You can use the bat script below to bypass this restriction.

<script begin>
@echo off
REM: Bypass.bat
REM: cmd /C bypass.bat yourps1.ps1

powershell.exe -noprofile -Command "powershell.exe -noprofile -encodedCommand ([Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((gc %1 |%%{$_}|out-string))))"
<script end>

C:\bypass.bat popCalc.ps1

We have successfully bypassed the execution policy with a limited user.  This method does not change the permissions of the logged-in user, but it does allow you run ps1 scripts regardless of the enforced settings.  Administrators that aren't using PowerShell should use software restriction policies with Active Directory to prevent its use for nefarious purposes such as the execution of shellcode.  




  1. Your reference link is dead.

  2. The best bypass that I use is:

    c:\powershell.exe Get-Content 'c:\somescript.ps1' | powershell.exe -noprofile -

    Your method looks cool too but is more work.

  3. powershell.exe -executionpolicy unrestricted foo.ps1

  4. There are definitely a lot of ways to accomplish this task, but that is my favorite!

  5. I like anonymous' post from the 25th, its better than my method as well...

    $exp = "";get-content script.ps1 | foreach {$_.trim()} | where-object {!$_.startswith("#")} | foreach { if ($_.startswith('{')) { $exp=$exp+$_ } else { $exp = $exp + ";" + $_}};invoke-expression $exp

  6. Just start your script like this:
    powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File C:\myscript.ps1

  7. Well thats cool but just add this to your ps1.

    Set-ExecutionPolicy bypass -scope currentuser -force

  8. The purpose of Execution Policies isn't "security", it's to stop stupid users clicking a file that gets emailed to them and having it cause them problems. None of the proposed suggestions make a blind bit of difference in that scenario.

    1. Thank you for commenting. This post is over 2 years old and I have gone through several different methods for bypass, but they are covered pretty well in the comments.

      I agree that it wasn't designed for security and yet I constantly hear that from conference attendees and clients.

      As far as stopping "stupid users clicking a file that get emailed to them and having it cause them problems," I would agree only if the file is a ps1. I email problems to people all the time:


  9. "I agree that it wasn't designed for security..."
    So, it was designed purely for inconvenience then? (No, really, what other purpose does it server?)

    1. I think it was designed to keep users from clicking on a ps1 file and having it execute.