Sunday, January 14, 2018

A Critique of Logging Capabilities in PowerShell v6

PowerShell 6 was released couple of days back. PowerShell v6 is the core version, that is, it is open source, cross platform and it is NOT Windows PowerShell which continues to be the default one on Windows. As per this blog by PowerShell Team, going forward, PowerShell core is the future (Windows PowerShell will still get critical bug-fixes.)
PowerShell Team, over past 2-3 years, has constantly improved the security controls in PowerShell. The defining moment was, of course, PowerShell ♥ the Blue Team where the PowerShell Team detailed many interesting features like System-wide Transcription, Deep Script Block Logging, AntiMalware Scan Interface, Protected Event Logging, Constrained Language Mode (with Applocker "Allow" mode) etc. Comparing PowerShell v2 - which comes installed by default in Windows 7 - with PowerShell 5.1 which is the default for Windows 10, the effort to restrict, track and log PowerShell usage on a box is clearly visible and effective.

Having used PowerShell for 7+ years for red team assessments and penetration tests, I look forward to every major release of PowerShell to change and upgrade my techniques and methodologies. With PowerShell 5.1, as an attacker, I am actually afraid that whatever I do on a foothold or launchpad box may be logged and (hopefully) monitored. During my Offensive PowerShell and Active Directory training, the attendees who are industry practitioners and researchers, always appreciate the logging capabilities of PowerShell and try to implement them in their organization's networks.

But with PowerShell v6, PowerShell logging features have been drastically reduced! This is almost certainly because v6 is based on .NET Core but there has been no authoritative word about it. This post is to compare the most interesting logging capabilities of PowerShell v6 with Windows PowerShell 5.1.

Deployment

All the enhanced logging capabilities PowerShell has, can be deployed using Group Policy. But this doesn't hold true for v6! To enable whatever logging for v6, a script RegisterManifest.ps1 (found in the $PSHOME directory) needs to be executed on each machine to register PowerShellCore event provider (PowerShell remoting can be used to run this script on scale). Thanks Satoshi for pointing this out.

The ability to configure logging from Group Policy is much easier to manage and harder to tamper with whereas the PowerShellCore event provider can be unregistered by using the "-UnRegister" parameter of the script.

System-wide Transcription

When System-wide transcription is enabled, all the activity for every PowerShell host (powershell.exe, powershell_ise.exe, System.Management.Automation.dll or other custom host) is logged to the specified directory or the user's "My Documents" directory if none is specified. With proper implementation, that is, forwarding logs to secure storage and correlation, system-wide transcription could be very effective in detecting PowerShell attacks. 

This is how system-wide transcription looks like for PowerShell 5.1 (The execution is using InstallUtil)
PowerShell v6 does not support system-wide transcription.

Script Block Logging

PowerShell v5.1 has two types of script block logging: Warning level auto logging and Verbose logging that can be configured. Warning level auto logging logs known bad/suspicious commands and script blocks and logs them in Microsoft-Windows-PowerShell/Operational log as Event ID 4104 Warning. When Verbose logging is turned on, which can be done using Group Policy, PowerShell commands are logged as Event ID 4104 Verbose.
Yes, there are public bypasses for script block logging as blogged by Ryan Cobb here and here, still, it increases attacker costs.

PowerShell v6 has no automatic script block logging. But when The PowerShellCore provider is created, the suspicious script blocks are logged with Event ID 4103 in the PowerShellCore logs.
 
Interestingly, while testing the warning level logs, I found out that v6 excels over v5.1 and logs less false positives. For example, one of suspicious strings (see code here) "GetMembers" is logged by 5.1 even if it is just executed senselessly.
But in case of v6, the above is not logged unless, there is a proper use of "GetMembers".
I find this very interesting and will have an in-depth look at it later on. May be, it could help in some interesting findings.

AntiMalware Scan Interface (AMSI)

AMSI provides the content of a script tor script block to the registered antivirus before execution takes place. This enables the antivirus to detect known bad scripts and script blocks regardless of input method (disk, memory, manual) and even encoded and obfuscated scripts. I spoke about AMSI at BlackHat USA 2016 and did a detailed blog post.

Fortunately, AMSI is enabled for PowerShell v6 as well. Although, Matt's bypass still works with just a minor modification.
But, once again, since it still increases cost to an attacker, its great to have AMSI in v6.

Constrained Language Mode

If "Allow mode" is enforced for Applocker or Device Guard, PowerShell is restricted automatically to the Constrained Language Mode which restricts Windows API, interaction with COM etc. See Language Modes

That is not the case with v6!

 

Introducing the PowerShell Upgrade Attack

PowerShell downgrade attack is popular with red teams. If you can run PowerShell v2, ALL security measures we have seen are bypassed as v2 simply doesn't support them. Lee provided an excellent guide on how to detect and prevent such attacks. If v2 is blocked or no required .NET version is installed, what to do? Simply run pwsh from your PowerShell session and you will drop in a new PowerShell session (v6 - if installed) which has minimal security features compared to v5/5.1. I am calling it the PowerShell Upgrade Attack :P. On a serious note, please keep in mind that Windows PowerShell - with enhanced logging - is the default one on Windows OS. Also, v6 is not an update, it needs to be installed separately. Windows PowerShell and PowerShell Core can be installed on a single machine and both will work independently.

So, what next?

I hold the PowerShell Team in high regard (for creating such a useful tool, being open to criticism and acting on the feedback) and quite confident (and hope) that they will address these shortcomings soon. Jeffery already tweeted that the Constrained Language Mode will be fixed in 6.1. But, if your production environment is working fine with Windows PowerShell v5/5.1, I would not advise to install v6 on any system (at least not the production ones).

UPDATE (25-Jan-2018) - The PowerShell Core Roadmap is published and there is no mention of bringing Core logging in parity with Windows PowerShell 5.1. Thankfully, the DeviceGuard/Applocker policy enforcement will get fixed.