PowerShell is becoming ubiquitous in the Microsoft ecosystem, and, while it simplifies administration, it opens up a nearly unprecedented suite of capabilities for attackers. Nearly every malicious activity imaginable is possible with PowerShell: privilege escalation, credential theft, lateral movement, data destruction, persistence, data exfiltration, and much more. Malicious PowerShell is being used in the wild, and CrowdStrike has seen an uptick in the number of advanced adversaries employing it during breaches. Dmitri Alperovitch wrote about one of these actors, Deep Panda, in his article “Deep in Thought: Chinese Targeting of National Security Think Tanks.” Attackers are leaning more on PowerShell because it is readily available and gets the job done with an added bonus of leaving behind almost no useful forensic artifacts. Jaron Bradley and I previously tackled the subject of command-line auditing in the CrowdCast, “What Malware? Hunting Command Line Activity”. I am pleased to report that there have been some significant upgrades to command line logging since that webcast.
Process Creation Events
Starting with Server 2012R2, Microsoft released a new group policy setting to enable the recording of full command lines in Process Tracking audit events. When released, logging was restricted to Windows 8.1 and Server 2012R2 systems, but it has since been back-ported due to popular acclaim. With the proper patches, any modern Windows system (Windows 7 and newer) can now enable this feature. One caveat to this significant upgrade is that Process Tracking creation must be enabled in your audit policy. In fact, Event ID 4688 (Process Creation) is used to record the command lines (see Figure 1). Historically, this has been a tough sell due to the number of events generated, but, even without command line information, these events can be very useful when hunting or performing incident response. We have seen this implemented successfully in multiple large environments through the use of centralized logging. If you do not have this enabled on your sensitive networks, you should absolutely consider it — before you need it. You can reference the Microsoft Technet article here.
I am still astonished that something as omnipotent as PowerShell was baked into the world’s most common operating system without security ramifications being considered or adequate security controls provided. Restricting access to PowerShell is notoriously difficult. As an example, the PowerShell Empire project has a capability to inject the required .NET assemblies into memory, allowing PowerShell functionality even if PowerShell.exe has been removed or blocked on the system. Perhaps the only way to truly prevent malicious PowerShell activity is to stop an attacker from achieving administrative privileges. Since that has proven extremely difficult in most networks, detection is currently your best bet. Unfortunately, until recently, PowerShell auditing was dismal and ineffective. A module logging capability has been present since PowerShell v3, but it is difficult to instrument and very unlikely to be used in most organizations. It was not until the recent PowerShell v5 release that truly effective logging was possible.
All Hail Script Block Logging!
A script block can be thought of as a collection of code that accomplishes a task. Script blocks can be as simple as a function or as full-featured as a script calling multiple cmdlets. Script block auditing captures the full command or contents of the script, who executed it, and when it occurred. Audits are recorded as event log entries in the Microsoft-Windows-PowerShell/Operational log regardless of how PowerShell was executed – from a command shell, the integrated scripting environment (ISE), or via custom hosting of PowerShell components. Event ID 4104 records the script block contents, but only the first time it is executed in an attempt to reduce log volume (see Figure 2).
Needless to say, script block auditing can be incredibly helpful when trying to piece together evil PowerShell activity. While logging is not enabled by default, the PowerShell team did sneak in the facility to identify potentially malicious script blocks and automatically log them in the PowerShell/Operational log, even with script block logging disabled. Hence, in environments running PowerShell v5, you should start seeing actionable information populating the Microsoft-Windows-PowerShell/Operational log by default. That, of course, is the only rub – you need to upgrade to PowerShell version 5 to partake. But there is great hope on the horizon for those who get there.