Imagine it: You install Windows PowerShell and are happily using it to automate administrative tasks. Then one day you open the shell and it autonomously starts deleting objects from Active Directory. Is the shell intelligent? Is it simply malicious? Or have you just discovered that Windows PowerShell, as configured by most administrators, is the perfect entry point for malware?
Show me your profile
The problem comes from four scripts that Windows PowerShell is hardcoded to look for and execute. They're called profiles, and they're designed for a good purpose: to pre-configure your shell environment each time you open it -- loading snap-ins, creating functions and so forth. But these profiles are simple text files, and two of them reside in your Documents folder, meaning you and any process you run has full control over them.
So along comes a piece of malware. It executes undetected because it's doing nothing more than writing to a couple of simple text files -- your PowerShell profile scripts. The next time you open the shell, every instruction in your profile executes, including the bad stuff. How could Microsoft possibly have shipped a product that does this?
The Quick Start Guide that comes with Windows PowerShell details the four scripts that the shell is hardcoded to look for and execute. You won't find most of these on your system unless you've created them; they are not created by default. That's a potential danger, because all a piece of malware has to do is create the scripts!
The primary ones are located in your Documents folder, in a subfolder called WindowsPowerShell. The first is named profile.ps1 and the second is Microsoft.PowerShell_profile.ps1. Each has a slightly different purpose as discussed in the guide, but they'll both load and execute automatically each time the shell opens. Even better, most PowerShell script editors – PowerGUI, PowerShell Plus and PowerShell Analyzer, AdminScriptEditor and PrimalScript also look for your PowerShell profile, load it and execute it each time the editor opens. There are plenty of opportunities for malware to execute. And get this: It's not Microsoft's fault. It's yours.
Where you went wrong
Out of the box, Windows PowerShell won't execute scripts -- even those profiles. That's because its Execution Policy is set by default to not permit script execution.
Try opening the shell and running Get-ExecutionPolicy. You should see "Restricted" if you're using the out-of-the-box settings. Then try running a script, and marvel at the error message that basically says, "no way, boss."
As shipped, Windows PowerShell is immune from malicious code being inserted into your profile, because it won't execute your profiles. In fact, if a profile script exists, the shell will still try to execute it, but will display the "no way" error. The only way to get the shell to run any script is to modify that Execution Policy, either by running Set-ExecutionPolicy or by deploying a Group Policy Object (you can get the shell's Group Policy extension from Microsoft's Download Center – search for "PowerShell ADM").
Most administrators seem to opt for the RemoteSigned policy or, even worse, the Unrestricted policy. Both will allow any local script to execute without being digitally signed. That means malware can create your profile script or modify it (if it already exists) and not get caught. Most antivirus software won't even detect that activity, because most don't classify it as malicious, unlike modifications to other sensitive files, such as Boot.ini. So what's an honest Windows admin to do?
The answer is to use the AllSigned policy, which requires all scripts to be digitally signed and forces the shell to check the integrity of the signature each time the script is executed. Sign your profile scripts -- create empty ones first if you need to -- and you're protected. Any malware modifications will break the signature; if the malware has some kind of embedded certificate and re-signs the script, then you can use the signature itself to track down the malware's author and apply the appropriate beatings.
Signing a script isn't tough: Just use the Set-AuthenticodeSignature command inside PowerShell itself, or use an editor capable of applying a signature (some will even do so automatically each time you save a script). You'll need to acquire a Class III AuthentiCode code-signing certificate, either from an internal certification authority (CA) or from a commercial one like VeriSign (they run about $400 to $900 for the first year, depending on where you buy it). Be sure to install the certificate on your system to have a password. That way malware can't access it without your knowing. All these steps may seem like a bit of a hassle, but it's the only way to safely enable script execution and keep malware from turning your profile into an attack vector.
About the author:
Don Jones is a co-founder of Concentrated Technology LLC, the author of more than 30 IT books and a speaker at technical conferences worldwide. Contact him through his website at www.ConcentratedTech.com.
Network Access Protection
Screencast: Getting started with PowerShell
Scripting School archive