PowerShell Security at Enterprise Customers

TL;DR; ("too long; didn't read")

There are some people who don´t have the time to read the whole text - if you are familiar with the topic the text in bold includes the most important points and is just for you.

The most important points to enforce PowerShell Security is to use the newest Versions (OS and PowerShell), use whitelisting and enforcing the usage of the ConstrainedLanguageMode and establish a good rights structure with frequent centralized logging and validate all the new features coming with the new Windows 10 Versions. And now in more detail:



Hi together,

I work as Premier Field Engineer for Microsoft Germany and have been working with many enterprise customers to assist in the preparation of the migration towards Windows 10. Here I got very often asked how to establish a complete PowerShell Security approach. What are the most important steps and what has to be done in which priority order? The problem is that there is no comprehensive overview for this. And the complexity also raises from 0 to 100 within the first topics. There are a lot of dependencies which you should be aware of!

Therefore I created a session for the PowerShell Conference 2017 to show this in depth - unfortunately it is a huge amount of information and you need to know about some of the technical terms to understand the whole picture which I will explain within this (long) blog post.

First we should start why everyone thinks that PowerShell is the evil armyknife for the blackhats out there. The news are full of security breaches where Powershell has been used. If you search a little bit you will find without any doubt dozens of hacking frameworks which can be used out of the box even from unexperienced people and allowing to do disturbing harming things much too easily. This brings most people (who are not familiar with the technical parts in depth) to the conclusion that PowerShell is evil and has to be deactivated. Don´t try this. You won´t do this even correctly. PowerShell can be used even without the PowerShell.exe and there are some frameworks like PSAttack which do this easily as you can see in this Procmon log:



PowerShell is just powerful!


As you can see in the picture (top right quadrant) PowerShell is one of the most used languages on GitHub.

Hackers use PowerShell for the same reasons you do. Because it is more convenient than twenty years of other popular command line tools. And how does PowerShell compare to all the other scripting languages ot there? Lee Holmes did an awesome job comparing the most known ones and created different evaluation categories to compare them all. And this was the outcome:


Lee Holmes, Azure Management Security, April 10, 2017, Comparison


So - Where to start? The PowerShell Version!

First of all you have to understand the basics when it comes to PowerShell Security. Here we start with the most simple point - this is definetely the PowerShell Version itself - and here you should target always the most current one which is out there - PowerShell Version 5 (WMF 5.1)

Many customers do still use Windows 7 and are going to use it at least to a decent number for the next 2-3 years. With WMF 5.1 it is very easy to update the PowerShell Version on your existing machines to it and this is also a must do for all the Windows 7 machines. I got very often tackled with arguments like "ah we are just in the uprading process to Windows 10 - we don´t touch our Windows 7 machines anymore." - I have to be very honest here - this kind of argumentation is just - stupid. How many computers does an attacker need to initialize his attack? Correct! - only one computer.


What changes with Version 5?

PowerShell Version 5 adds additional capabilities with the constrained language, the logging and brings also some improvements regarding JEA. We will speak about this later on.


Just update it - it is a must do!



PowerShell Version 2 - be aware of! (read here)

There are some attacks targeting the usage of the PowerShell Version 2. Why? No logging. In Windows 10 you can disable the integrated Version 2 via optionalfeatures and this a important recommendation after having tested it.



Speaking about versions - what´s about the OS?

Windows 10 comes along with many security features, which we will describe later on in very detail. To give you just an overview this are the keywords you should know about: Credential Guard, Device Guard, AMSI, WDATP and much more. In a nutshell - speaking security-wise the recommendation is so easy as you can image.
You should migrate to Windows 10 and evaluate all the security features which can be used.




There it is - the ExecutionPolicy. I cannot even describe how frustrating this topic sometimes can be. I have been at so many big enterprise customers (n clients > 20000) who used the ExecutionPolicy as a security boundary.

Please remind the following analogy:

ExecutionPolicy is like a baby door. The ExecutionPolicy keeps babies safe but every grown-up surpasses it easily.

There are like over 20 ways to surpass the ExecutionPolicy even as a standard user. Therefore you should set it via GPO as you like it. (RemoteSigned e.g.) It may prevent some people using Powershell scripts from the internet but you should not count on it.



PowerShell Remoting

PowerShell is evil - the only thing which is even more insecure is PowerShell Remoting. True? Not even close. Take a read here.

The facts:

  • always encrypted by default
  • single port 5985 or 5986
  • PowerShell remoting respects all Windows authentication and authorization protocols.
  • It requires local Administrators group membership by default.
  • It can be even hardened with IPFilters and SSL.
  • The improvements in WMF 5.0 (or WMF 4.0 with KB3000850) make PowerShell the worst tool of choice for a hacker when you enable script block logging and system-wide transcription.
  • Hackers will leave fingerprints everywhere, unlike popular CMD utilities.

For this reason, PowerShell should be the only tool you allow for remote administration. 

You have to just set up a correct right structure in your environment and then it´s the most secure technology to do remoting.


Till here we have done our most important and most basic settings as shown in the following graph:

Important: I will use these graphs in the whole article and extend them time by time to reach a complete security approach at the end. They should be read always from the left to the right. The most important points which normally also don´t take too much invest to implement are mostly oriented to the left. The more you get into the right area - the more you increase the security level - but the effort to reach some of the goals is also higher and comes along with an higher investment of time or money by using new technologies, setting up dedicated servers or investing human resources.



Securing Privileged Access

In the last part I wrote the following sentence: "You have to just set up a correct right structure in your environment." And this topic is completely about this. We (Microsoft) have developed a roadmap to achieve a very comprehensive approach which is separated into 3 parts:


Unfortunately this is a very huge topic. The complete approach can be found in the following link and is worth a read for every security-oriented person!


For our PowerShell Security Approach it is worth a mention but this would exceed the main topic too much. To consolidate the information I created the following simplified graph.



Modernizing Environment

This is a topic which most of my customers are in. They are planning to migrate to Windows 10 with new hardware and evaluate all the new security features which came along with. Starting with the most important ones:


One of the biggest attacking vectors is Pass the Hash. There are also PowerShell modules out there like mimikatz which can be used out of to box for such attacks. It can be described easily - the attacker obtains the password hashes from one machine and uses them remotely to connect to other machines and with some other techniques he tries to elevate his rights he is using. The following picture illustrates this.


Windows 10 brings this really cool new feature called Credential Guard. The hashes are stored in a separate container on which the attacker cannot read on. As simple as that. Technically spoken this is the process LSAIso (isolated). The communication is done via RPC-Calls.



In my opinion the following video just nails it:




The next part which I have put into the topic Modernizing Environment is one the most important ones speaking of PowerShell Security:



Whitelisting / Signing / ConstrainedLanguage / Applocker / Device Guard

Signing allows us to set a trust in the scripts. The signing certificates can be created by our PKI environment and give even the developers security to not accidental modify and execute scripts. In combination with DeviceGuard or Applocker this can be used as a prerequirement for executing it. Only our signed scripts would then be executed in the FullLanguageMode.




First of all we need to get to know what the Full / ConstrainedLanguageMode is. PowerShell can be used in different language modes. If you configure your ExecutionPolicy and don´t user PowerShell Version 5 or AppLocker / DeviceGuard any attacker can use the FullLanguageMode. So he can load his COM objects / libraries / classes into his PowerShell session as he likes to. In the example of mimikatz - he is able to load this framework and easily capture the credentials out of a Windows 7 device. ConstrainedLanguage cuts this ability down massively and breaks nearly all attacking frameworks. But how can you enforce PowerShell to use the ConstrainedLanguageMode? And how do you control that some scripts still keep working and use the FullLanguageMode?


And here comes the PowerShell Version into play. First of all you need the PowerShell Version 5 to enforce this. Coming with PowerShell Version 5 you can enforce this either with Applocker in Allow Mode or DeviceGuard using UMCI (User Mode Code Integrity).


Damn! So many technologies and dependencies. Let us first take a look at the separate technologies.


Applocker with PowerShell Version 5:

The aim should be the usage of Applocker in Allow Mode. The downside of Applocker is that every admin can deactivate it by stopping the service AppIDSvc.

Scripts that are allowed by the AppLocker policy (for example: signed by the enterprise’s trusted code signing certificate, or in a trusted directory) are not subject to Constrained Language.


Device Guard (detailed information)

  • Combination of hardware + software security features
  • Enables businesses to strongly control what is allowed to run
  • Brings mobile-like security protections with support for existing line of business apps
  • UMCI places PowerShell into constrained language mode
  • Device Guard UMCI also applies code integrity rules to DLLs.


What is the whole picture for this?

Device Guard can be separated from this overview into KMCI and UMCI and you see how they come into play here. Many customer do just have Applocker in usage today. The recommendation here would be to start with Applocker leveraging towards Allow mode in combination with DeviceGuard in KMCI. Afterwards leveraging Device Guard towards UMCI.


Code Integrity + Applocker:

  • Together, AppLocker and code integrity are the correct technologies for enforcing code and application rules on Windows
  • Code integrity best expresses high level expression of trust
  • AppLocker allows for granular rules
  • Managed through common management tools in Windows 10


Now we have learned a lot of new stuff - let us recap the last topic of Device Guard with PowerShell Version 5:

  • Device Guard UMCI is another security feature that a defender should consider from a cost/benefit analysis.
  • It will always be vulnerable to bypasses, but raises the baseline bar of security.
  • So obviously, you would want to use additional security solutions along with Device Guard - e.g. WEF, an anti-malware solution, and to perform periodic compromise/hunt assessments. (we will dive into this little later)



The last part of the category Modernizing Environment shows our newest defense technologies.

Anti-Malware Scan Interface is an interface which can be used by every Antivirus scanner to evaluate if a script is potentially harmful.


  • AMSI enables all of the scripting engines (PowerShell, VBScript, and JScript) to request analysis of dynamic content, from a script file, typed commands at the command line, and even code downloaded and executed in memory.
  • When code is delivered to the PowerShell “engine” (System.Management.Automation.dll), it is sent to the AMSI for anti-malware checks. Windows Defender supports AMSI on Windows 10 just out of the box. 


And this is how it looks like when its working.



The next topic is the Windows Defender Advanced Threat Protection. But before we start with this extremely great feature we throw a look at the Windows 10 Defense Stack:

As you can see we have two approaches here. Everything what belongs to the Pre-Breach approach and a second one - the Post-Breach approach. Every good security person today knows that it is not only anymore about preventing attacks. The detection of attacks increases in importance day by day. A huge number of all attacks are even processed without any malicious code. So not even the best AV on the world can catch these attacks! Today it is crucial to have the latest updates. (You WannaCry again?)


Advanced Threat Protection

Windows Defender ATP combines sensors built-in to the operating system with a powerful security cloud service enabling Security Operations to detect, investigate, contain, and respond to advanced attacks against their network.

Herefore the Microsoft Intelligent Security Graph is used which stores all information and creates patterns for different attacks by different hacker groups.


Gathering all the necessary information at the customer side:


You can easily view what happened and which events correlate to each other:


In this example you can see a NEROBLAZE attack and can initialize your response to this. ATP is built-in in Windows Defender - therefore you can trigger actions which normally need elevated rights. For example - cutting down network connections, shutting down processes and many more. Also you would get to know where this email with this attachment landed in your environment to proactively prevent all users from opening the attachment.




Coming with PowerShell Version 5 we have the additional logging capabilities of ScriptBlock-Logging. Read Here.

The problem for some customers is to store and evaluate all the logging data. But this is a topic you should be aware of as for the following recommendations:

You should actually activate all three log sources because you want to detect ongoing attacks and cannot prevent every attack. We are here again in the previously described Post-Breach Approach where we want to detect intrusions as fast as possible. Also it leverages us to do afterwards a good forensic analysis - how the hackers entered into our system and what the main targets have been. (must read)



Script block logging provides the ability to log de-obfuscated PowerShell code to the event log. Most attack tools are obfuscated, often using Base64 encoding, before execution to make it more difficult to detect or identify what code actually ran. Script block logging logs the actual code delivered to the PowerShell engine before execution which is possible since the script code needs to be de-obfuscated before execution.

Since many PowerShell attacks obfuscate the attack code, it is difficult to identify what the script code does. Script block logging de-obfucates the code and logs the code that is executed. Since this code is logged, it can be alerted on when seen by a central logging system.

One key challenge with identifying offensive PowerShell code is that most of the time it is obfuscated (Base64, Base64+XOR, etc). This makes real-time analysis nearly impossible since there is no keyword to trigger alerts on.

Deep Script Block Logging records the content of the script blocks it processes as well as the generated script code at execution time.

Microsoft-provided example of obfuscated command code:


## Malware
function SuperDecrypt
    $bytes = [Convert]::FromBase64String($script)
    ## XOR “encryption”
    $xorKey = 0x42
    for($counter = 0; $counter -lt $bytes.Length; $counter++)
    $bytes[$counter] = $bytes[$counter] -bxor $xorKey
$decrypted = SuperDecrypt “FUIwQitCNkInQm9CCkItQjFCNkJiQmVCEkI1QixCJkJlQg==”
Invoke-Expression $decrypted


Extended Logging / WEF and JEA

But with enabling the logs you didn´t win anything. You surely have to examine the content of the logs. Therefore you should evaluate between WEF and SIEM solutions. The main aim is to centralize all the log data and examine the logging data. (automatically with keywords)
I will dive into these topics in later blog articles.



Just Enough Administration (read here)

JEA allows specific users to perform designated administrative tasks on designated servers without giving them full administrator rights. JEA is based on Windows PowerShell-constrained run spaces, a technology used at Microsoft to help secure administrative tasks in environments like Exchange Online / Active Directory.

The whole Picture graphs:

Till here we have read a lot (!) of information. The next complete graphs will show the whole work which has to be done:
To fulfill the complete PowerShell Security Approach all of the three graphs should be addressed in parallel - starting from left to the right. (a clear priority order will follow in next blog articles)



Everything regarding PowerShell itself:


Privileged Access Management simplified:

Modernizing Environment - all the new and updated stuff:


What is important in a nutshell?

  • PowerShell Version 5
  • Disabling PowerShell Version 2 if possible
  • Constrained Language enforced via Applocker and/or Device Guard
  • Logging, Centralization and Evaluation
  • Windows 10 with enabled new Security Features
  • A good Privileged Access Management


Additional Material:

Great Blog from Matt

Introducing Project Sauron – Centralised Storage of Windows Events – Domain Controller Edition

NSA Methodology for Adversary Obstruction

Spotting the Adversary with Windows Event Log Monitoring

PowerShell ScriptBlockLogging rocks!

Enabling deep script block logging

Maslow’s Hierarchy of Security Controls

A Comparison of Shell and Scripting Language Security

Greater Visibility Through PowerShell Logging

AMSI: How Windows 10 Plans to Stop Script-Based Attacks and How Well It Does It

Shutting down scripts with Applocker 

Detecting Offensive PowerShell Attack Tools

PowerShell Security: PowerShell Attack Tools, Mitigation, & Detection

PowerShell Version 5 Security Enhancements

WMImplant - bad news

All the best,

David das Neves

Premier Field Engineer, EMEA, Germany
Windows Client, PowerShell, Security

Comments (16)

  1. Jaap Brasser says:

    Nice summary David! Good to have a link like this to share with colleagues to get them up to speed with PowerShell security.

    1. Thank you Jaap! Unfortunately this is not even the whole story and some topics require more information into depth like Device Guard.
      Let´s see if I can find some time and create some more articles. 🙂

  2. Kumkax says:

    David, it is a great and extensive article. Every company should follow the steps to secure computer systems environment you presented here. I will definitely follow and start planning how and what should be done to enhance security of my workplace.

  3. D.Ecke says:

    hey David,
    what Jaap said 🙂 very useful information, even with most important info in bold for the tl;dr guys out there 😉
    appreciate that, forwarded already…

    1. Thank you very much! 🙂

  4. pldmgg says:

    Hi David,
    I’ll be referencing this a lot in the future. How does Credential Guard fit in (if at all) with PowerShell Remoting and Remote Desktop Protocol with and without Restricted Admin Mode? Does it do anything for PowerShell Remoting CredSSP concerns?

    Thanks for this post!

    1. Hi,

      Credential Guard would be usable for RDP Connections with the Remote Credential Guard – take a read here:

      Powershell Remoting could be additionally “hardened” with IPFilters and with SSL but won´t benefit from Credential Guard itself.

      Keep the following in mind:
      When you enable Credential Guard, you can no longer use Kerberos unconstrained delegation or DES encryption. Unconstrained delegation could allow attackers to extract Kerberos keys from the isolated LSA process. You must use constrained or resource-based Kerberos delegation instead.

      Take also a read on this articles:

      As you have read WinRM tries to use Kerberos and NTLM authentication afterwards. In the WinRM you have the desired group specified which is allowed for Remoting – which is out-of-the-box the Administrators group.

      CredSSP still keeps the no way of choice.

      “When Credential Guard is enabled, NTLMv1, MS-CHAPv2, Digest, and CredSSP cannot use the signed-in credentials. Thus, single sign-on does not work with these protocols. However, applications can prompt for credentials or use credentials stored in the Windows Vault which are not protected by Credential Guard with any of these protocols. It is strongly recommended that valuable credentials, such as the sign-in credentials, not be used with any of these protocols. If these protocols must be used by domain or Azure AD users, secondary credentials should be provisioned for these use cases.”

      Take also a look at the double hop-problems which in the past had been often solved by the usage of CredSSP.

      Depending on what scenario you are thinking of – my recommendation here would also be to validate the usage of JEA.

      I hope this helped – but good point though. Looks like a “Best Practice”-article for Powershell Remoting could be useful, too. 🙂


      1. pldmgg says:

        This is awesome info! Thanks for the reply, I really appreciate it!


  5. Thank you for this article, it was extensive, and imho not at all too long.
    As a powershell user it’s really nice to have some fears dismissed (but others confirmed) on do’s and dont’s.
    I believe a very interesting additional topic for me will be the IPfiltering parts.

  6. Very useful and usable information. Like the format and external links. We deal with powershell malware daily…so its good

  7. Yoshihiro Kawabata says:

    I hope to translating this article in Japanese, for sharing it with my friends/customers/partners.
    and to presentation it in Japanese.

    1. Hi Yoshihiro,

      I added the “Translate”-Button. It´s not perfect, but hopefully it helps to some extend.
      Just mail me directly if you need further assistance / materials.

      All the best,

  8. Panzerbjrn says:

    Very interesting and informative. This definitely cleared a few things up for me, and I’ll provide it as reading the next time an IT manager says we don’t have to worry about PowerShell security… -_-

  9. Andy Lawrence W says:

    This is up there being legendary badarse epic advice. Appreciate the time and efforts you put in to share this. #respect

    1. Thank you – more to come 😉

  10. Great article! I’m loving being aware of new PS versions . Thanks most humbly respect your efforts in blogging and sharing this. Theres always new stuff to learn. Cheers

Skip to main content