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.