Varonis announces strategic partnership with Microsoft to accelerate the secure adoption of Copilot.

Learn more

PowerShell for Pentesters: Scripts, Examples and Tips

This PowerShell for Pentesters' guide covers running commands, coding, tutorials and examples as well as the benefits of pentesting with PowerShell.
Michael Buckbee
5 min read
Published June 17, 2020
Last updated February 24, 2022

In case you haven’t noticed, we’ve been championing PowerShell as a pentesting tool in more than a few blog posts. One big reason to learn PowerShell and use it to find security holes in your own IT systems is …  that’s exactly what hackers are doing themselves!  They’re leveraging PowerShell to run “file-less” malware, which are non-binary files that can’t easily be detected by anti-virus (AV) solutions.

PowerShell, of course, has a separate life from penetration testing. Those who want to understand the backstory should check out the famous Monad Manifesto. Written by one of the original developers, the Manifesto explained why Microsoft needed a new scripting language, which would ultimately morph into PowerShell.

Get the Free Pentesting Active
Directory Environments E-Book

To save you from having to peruse the Manifesto, I’ll reveal the motivating factor driving the authors of PowerShell: it was to give system administrators command-line access to .Net objects, allowing for automation of system-level workflow that would have otherwise been written in C++ or C#.  If you want real proof of PowerShell’s effectiveness, ask your sys admins how they bulk add users into Active Directory or do some quick security configuration. You’ll likely find a PowerShell solution.

In short: it’s an amazing productivity booster for admins.

Why Use PowerShell for Pentesting?

Unfortunately, the same ingredients that make for a great automation tool for administrators are useful to hackers and then ultimately pentesters.

For example, perhaps an IT admin has been asked to find out who’s actually using a supposedly under-utilized server. With PowerShell and a library of extra functions known as PowerView, a system admin can quickly see the users currently logged onto a server without having to be directly on the server herself:

PowerShell coding screenshot pentesters

However, attackers who’ve already gained entry through a phishing attack can also do the same — they can leverage the same AD capabilities. And their activities would not necessarily be detected: a security analyst monitoring application usage might come to the conclusion that since “it’s just PowerShell, it must be harmless”.

To take this example one step further, hackers can find even more detailed information about individual users with the Get-NetUser command, which dumps all of the user’s AD attributes:

PowerShell coding screenshot

Unfortunately, companies are often careless about the AD attributes they make accessible — say, home or cell phone, address — to employees. Prior to PowerShell, it would have been far more difficult to gather this AD data, but that’s no longer the case!

What can the attackers do with the AD information? They can easily work out a social engineered attack: perhaps sending an email with just enough personal context gained from the AD attributes to make it appear to come from the help desk asking to “reset a password”.

By the way, you can enforce ACLs on AD attributes, so there’s a way to reduce the risk of this type of attack. And that’s precisely the kind of positive result that can come out of actual penetration testing exercises!

PowerShell coding screenshot of permissions

Brief PowerShell Introduction for Pentesters

With PowerShell, attackers can stealthily gather internal user data and exploit it. But there’s no reason why IT security staff can’t master enough PowerShell to start their own pen testing and begin to understand the hacker mindset.

The first key point about PowerShell is that all the old scripts, .bat files, or procedures that you ran from the cmd.exe command prompt still work in the PowerShell console. That’s great news.

The next important point is that unlike Linux-like shells, PowerShell treats everything as an object. Even the output of a command is, wait for it, an object.

For example, enter Get-ChildItem command (or cmdlet in the PS world) into the console, and you’ll see a listing of files in the current directory:

PowerShell coding screenshot of get childitem

Coding with PowerShell

Suppose you wanted to write a PS script that only lists files over 1M in size— just as a quick way to see if there are any storage hogs. This task is a lot harder in a string-oriented output from, say a bash shell. With PowerShell, though, command output is itself an object with attributes.

To see this, just pipe the output of GetChildItem into Get-Member, which tells you the attributes of any PS cmdlet:

PowerShell coding screenshot of get member

So now we have the identifiers for the two attributes we’re interested in: “length” and “name”, which we can reference programmatically. So far, so good.

To deal with the very common situation where objects are often in arrays or collections, we use PS’s ForEach operator to iterate through the array. To make things even easier, the alias“%” stands in for “ForEach”, and  “$_” represents the current object.

Running Commands with PowerShell

Let’s recreate just two columns of output from the GetChildItem command based on our new knowledge. The script below is a pipeline with Get-ChildItem feeding the ForEach operator, outputting just the values of the “length” and “name” attributes:

get-childitem| % {write-host $_.length $_.name -separator "`t`t"}

And here’s the output when we run it:

PowerShell coding screenshot pipe childitem

To finish this micro-project, let’s tweak the PS script above to display only large files above, say, 10M. To accomplish this, I use a filter, known as a Where-Object cmdlet, which has the convenient alias of “?”.  It has all the usual comparison operators (-gt, -eq, -lt, etc.). And I can insert this into the middle of the pipeline so that the script now looks like this:

get-ChildItem| ? {$_.length –gt 10000000 | % {write-host $_.length $_.name -separator "`t`t"}

As an exercise, try running the above scriptware in your own environment.

Tutorial: PowerShell Penetration Testing Example

With that small background in PowerShell, we’re ready to take on a more practical pentesting example. One of the quickest ways to get into pen testing is to use PowerShell to hide a payload — I wrote about how to do this here.

The idea is to sneak the PowerShell into what looks like a standard text file with a .doc suffix. In fact, the file really has a .js suffix, which when clicked will activate the Windows Script Host to run the JavaScript and then launch the embedded PowerShell code.

Confusing, right? But real hackers leverage multiple levels of indirection and obfuscation to hide their attack.

Set up the Launcher and Payload

Here’s what the script looks like:

You insert the above code into a text file and rename it to something like invoice.doc.js.  The above JavaScript acts as the launcher, which is implemented with embedded PowerShell commands NetWebClient and Invoke-Expression, which is itself aliased with “%”.

NetWebClient’s DownloadString method remotely pulls in the actual payload that will ultimately do the malware dirty work. You can supply this method with a URL pointing to your own test malware. The Invoke-Expression cmdlet takes the text of the fake malware file and executes it.

Test it!

In my case, the URL points to a Github project containing a simple PS write-host that will display a  harmless but important message to humankind. In a real-world attack, the script file would be attached to a phish mail that would lure an unsuspecting employee into clicking. And the payload would be far more disruptive.

PowerShell coding screenshot it shows a message saying, "you have a lot of security mitigation work ahead of you

You can try this out on your own installation. And if does run successfully, then you have some homework to do.

Benefits of Penetration Testing

reasons to pentest - a text image that's title says "Reasons to Pentest" and the bulleted copy below says: "Gain an understanding of how hackers operate. See where any of your hidden weaknesses lie. Learn where resources should be allocated. Mitigate damages if/when a breach occurs. Save money and resources on remediation."

This nicely leads to the reasons you’re doing penetration testing in the first place. Here are three real-world benefits that I’ve come up with:

  1. By learning PowerShell commands as a pentester, you’ll understand how hackers subvert this amazing next-gen scripting language. Just ponder the combination of DownloadString method and Invoke-Expression, allowing attackers to pull remote malware into the victim’s site without having to store it.
  2. This exercise also highlights the stealthiness of the modern hacker. I’ve shown with the above example the outline of an attack that doesn’t leave any files around. So you can’t use standard signature-based methods to reliably detect a PowerShell-based attack. There’s no obvious malware signature to trigger on.
  3. You might begin to examine ways to limit PowerShell and other script-based methods. After all, the attack is started with a script, so if companies make it more difficult to run scripts, they can greatly reduce their risk profile.

Let me expand on that last point. You don’t want to completely ban PowerShell (or JavaScript) since it’s a fundamental part of Windows system software. Thankfully Microsoft has a way to selectively disable scripting (and other executables) through its AppLocker, an improved version of the older Software Restriction Policies in Group Policies.

This may sound incredible to tech people, but most ordinary users don’t need PowerShell or other scripts to do their jobs. Shocking, I know! AppLocker can be used to disable PowerShell access for the masses while allowing sys admins to still do their work.

Scripting attacks involving an attachment to a phish mail count on the fact that admins have typically given very broad scripting permissions to employees. That doesn’t have to be the case!  To learn more about AppLocker and white-listing techniques in general, check out our amazing Disabling PowerShell and Other Malware Nuisances series.

 

What you should do now

Below are three ways we can help you begin your journey to reducing data risk at your company:

  1. Schedule a demo session with us, where we can show you around, answer your questions, and help you see if Varonis is right for you.
  2. Download our free report and learn the risks associated with SaaS data exposure.
  3. Share this blog post with someone you know who'd enjoy reading it. Share it with them via email, LinkedIn, Reddit, or Facebook.

Try Varonis free.

Get a detailed data risk report based on your company’s data.
Deploys in minutes.

Keep reading

Varonis tackles hundreds of use cases, making it the ultimate platform to stop data breaches and ensure compliance.

powershell-variable-scope-guide:-using-scope-in-scripts-and-modules
PowerShell Variable Scope Guide: Using Scope in Scripts and Modules
PowerShell variable scopes can cause confusion in writing scripts and functions. This post will cover PowerShell scopes in relation to scripts and modules.
getting-started-with-powershell-option-inputs
Getting Started with PowerShell Option Inputs
PowerShell is the dominant method of automating tasks and scripting changes for Windows sysadmins. This article covers getting started with some basic PowerShell usage and how to pass optional customization...
windows-powershell-scripting-tutorial-for-beginners
Windows PowerShell Scripting Tutorial For Beginners
New to PowerShell scripting? Explore these scripting tutorials to learn to write and execute basic scripts, PowerShell cmdlets, aliases, pipes and more.
detecting-malware-payloads-in-office-document-metadata
Detecting Malware Payloads in Office Document Metadata
Ever consider document properties like “Company,” “Title,” and “Comments” a vehicle for a malicious payload? Checkout this nifty PowerShell payload in the company metadata: #powershell payload stored in office metadataDocument...