Community Brainstorming: PowerShell Security versus malicious code

A couple weeks ago, some malicious PowerShell code was discovered in the wild, dubbed the "Power Worm" in the Trend Micro article that originally publicised the malware. Matt Graeber has done a great analysis of the code on his blog. In the comments for that blog post, we started discussing some options for locking down PowerShell, preventing it from being used in this type of attack. (Unfortunately, Execution Policy is currently no barrier at all; PowerShell.exe can simply be launched with the -Command or -EncodedCommand parameters, bypassing ExecutionPolicy entirely.) Matt's idea is to have PowerShell run in Constrained Language mode by default, similar to how it works on the Windows RT platform.

This post is to engage some community discussion on the topic; please do so in this thread:

What are your thoughts on this topic? Do you feel that PowerShell.exe needs some additional security features to try to prevent it from being used in this sort of malware? What impact would these ideas have on your normal, legitimate uses of PowerShell (if any)? How would you suggest minimizing that impact while still making it more difficult for PowerShell malware to execute?

About the Author

Dave Wyatt

Dave Wyatt is a Microsoft MVP (PowerShell) and a member of's Board of Directors.


  1. Thanks for posting this, Dave. Ultimately, my stance on the matter is that I believe that a non-admin user should be able to do little to nothing with PowerShell out of the box. I would even go so far as to advocate forcing NoLanguage mode. Of course, just like with the execution policy (which is not a security mitigation), you would easily be able to re-enable functionality for the user using a cmdlet along the lines of Set-LanguageMode. Some have argued against such a mitigation because they claim that it's game over anyway if you can already execute code on the compromised machine even as a non-admin. While there is some truth to that, at least PowerShell wouldn't be used as the primary attack vector. An attacker may have to resort to other techniques that are more likely to be detected - e.g. downloading and executing malicious executables. Forcing an attacker to resort to alternate attack technique are much more likely to be detected.

    Along those lines, it would also be great if there was more verbose event logging for PowerShell out of the box. I've analyzed several malware campaigns where PowerShell was used as the primary attack vector. The existing entries in the event log indicated that PowerShell was used for an attack but it didn't give any insight into what was performed. It's possible to gain additional insight into an attack by tapping into the PowerShell ETW provider with the Enable-PSTrace cmdlet but of course, if you've already been compromised, this detection technique is useless after the fact.

    Of course, my opinion is biased towards the side of security versus usability because I've seen how devastating malware infections are on an enterprise. I'd love to hear the merits of those with opposing opinions though.


    • Hi Matt,

      Just FYI, I've copied your response over to the forum thread. Blog comments are an awkward place for this sort of discussion on, as there's no email notification for replies, code formatting is terrible, etc. 🙂

    • Matt,

      I haven't looked into this in great detail so don't have a full recommendation, but while discussiong this last week with Brian Krebs and Kieran Jacobson on Twitter I came across this article on

      PowerShell Basics - Execution Policy and Code Signing Part 2

      In the article it disccusses how in PowerShell 3 you can increase the information captured

      "In the Group Policy Management Console you can create a policy to manage PowerShell settings and go to Computer Configuration –> Policies –>Administrative Template–> Windows Components and double click on Turn Module Logging"

  2. A cut&paste error with Excel while building a test pointed me to the invocation of an outside script while a hashtable is being loaded.

    Name : ConsoleHost
    Version : 5.0.10586.117
    InstanceId : 1c32d516-81c1-4a16-a287-38b912aaa3f8
    UI : System.Management.Automation.Internal.Host.InternalHostUserInterface
    CurrentCulture : en-US
    CurrentUICulture : en-US
    PrivateData : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
    DebuggerEnabled : True
    IsRunspacePushed : False
    Runspace : System.Management.Automation.Runspaces.LocalRunspace

    # created one liner for demonstration purposes
    write-host 'this is a test script';

    $hshtestx = @{ 1980 = test; 2000 = test; 2020 = test; 2040 = test;
    1981 = 'test'; 2001 = 'test'; 2021 = 'test'; 2041 = 'test';
    1982 = 'test'; 2002 = 'test' }
    #Nota Bene: the lack of quotes in top line from Excel faux pas

    Ran from ISE:
    PS H:\> H:\hshtest00.ps1
    this is a test script
    this is a test script
    this is a test script
    this is a test script

    Don't think that invoking another script on the load of a hash table is a desired behavior. May be wrong, but couldn't find anything via google about it this AM.