alphaspirit - Fotolia

PowerShell logging boosts security in the enterprise

Want to track any suspicious PowerShell activity across your network? Use these PowerShell logging techniques to curb potential threats that originate from scripts.

PowerShell gets a lot of bad publicity for being a very common tool for malware authors. Because of its deep integration with Windows and wide-ranging access to the operating system, PowerShell gives an attacker a number of ways to infiltrate and manipulate local and remote machines.

Some security experts have called to remove PowerShell from Windows or to reduce its capabilities, but that's not realistic. PowerShell is an indispensable tool for many system administrators and disabling its functionality would make management work much more difficult. By turning on PowerShell logging, enterprises can catch any suspicious scripting activity across the organization and learn from any security incidents that originated in PowerShell.

Types of PowerShell logging

There are three types of PowerShell logging: module, script block and transcription. You can configure the first two types as events in the Windows PowerShell event log. Transcription logs go to a text file.

Module logging keeps a record of pipeline execution events in PowerShell for specific modules. By default, modules in PowerShell do not log this, as you can see here:

Get-Module -ListAvailable | Select-Object Name,LogPipelineExecutionDetails

Name         LogPipelineExecutionDetails

----         ---------------------------

Microsoft.PowerShell.     False
Operation.Validation       

PackageManagement         False

Pester                    False

PowerShellGet             False

PSReadline                False

AppBackgroundTask         False

There are three types of PowerShell logging: module, script block and transcription.

To log the module SmbShare, run these PowerShell commands:

Import-Module SmbShare

(Get-Module SmbShare).LogPipelineExecutionDetails = $true

To illustrate what is inside these logs, run Get-SmbConnection from the PowerShell console and then check the event logs on the local machine.

PowerShell module logging
Figure 1. Event 4103 breaks down the specifics when running a PowerShell module.

Figure 1 shows the properties of event ID 4013 from this command. Event details include the parameters used with the command -- such as ThrottleLimit and AsJob -- and the hostname, PowerShell version, runspace ID and user who executed the command.

Setting up script block logging

Microsoft documentation calls a script block "a collection of statements or expressions that can be used as a single unit. A script block can accept arguments and return values." A simple way to show how a script block works is to use the Invoke-Command with the -ScriptBlock parameter:

Invoke-Command -ScriptBlock {Get-Process explorer}

The -ScriptBlock parameter
Figure 2. The Invoke-Command cmdlet can use the -ScriptBlock parameter for more advanced PowerShell scripting.

Script block logging is one of the most useful aspects of PowerShell logging because it records obfuscated code to the event log. This is especially useful because the majority of PowerShell malware uses scrambled code to hide from IT teams.

Script block logging shows up in the event log as event ID 4104. Even without script block logging enabled, Windows still generates events that PowerShell flags as potentially malicious.

Figure 3 shows the result of a script block log generated using the following PowerShell command:

Invoke-Command -ScriptBlock {$a = "Variable";"This is a test $a"}

Script block logging
Figure 3. The Windows event log tracks script block logging with event ID 4104.

How to use transcription logging

PowerShell transcription logging writes any PowerShell commands and console output to a text file for analysis. Users start transcription logging manually with the Start-Transcript and Stop-Transcript commands in PowerShell or through a Group Policy/registry configuration.

A typical transcript file looks like this:

**********************

Windows PowerShell transcript start

Start time: 20180704143442

Username: VAGRANT-10\vagrant

RunAs User: VAGRANT-10\vagrant

Configuration Name:

Machine: VAGRANT-10 (Microsoft Windows NT 10.0.16299.0)

Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

Process ID: 6028

PSVersion: 5.1.16299.492

PSEdition: Desktop

PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.16299.492

BuildVersion: 10.0.16299.492

CLRVersion: 4.0.30319.42000

WSManStackVersion: 3.0

PSRemotingProtocolVersion: 2.3

SerializationVersion: 1.1.0.1

**********************

**********************

Command start time: 20180704143459

**********************

PS C:\Windows\system32> Get-SmbConnection

**********************

PS C:\> exit

**********************


How to defend against PowerShell-based attacks

Windows PowerShell transcript end

End time: 20180704151126

**********************

The transcript shows the user running the PowerShell session and other helpful information, such as the process ID, PowerShell version, commands executed and timestamps.

Centralize PowerShell logging with Group Policy

Group Policy makes it easy to configure PowerShell logging for multiple machines. You can find these policies in the Group Policy editor at the following location: Computer Configuration > Administrative Templates > Windows Components > Windows PowerShell

Here, you will see five settings: turn on module logging, turn on PowerShell script block logging, turn on script execution, turn on PowerShell transcription and set the default source path for Update-Help.

Group Policy PowerShell settings
Administrators can use the Group Policy editor to start PowerShell logging on multiple machines.

You can enable all the PowerShell logging types and two others: script execution and default source for Update-Help.

The "Turn on PowerShell transcription" setting should interest administrators who want to configure a central location for transcription logs. This setting writes all logs locally, so you can copy them to a folder with PowerShell.

For instance, once you set up this PowerShell script to run on each local machine, it creates a folder named C:\Windows\PSLogging and gives the local Users group permission to write to the share. It also adds a domain security group called Security Admins with full control to manage the logs.

$registryPath = "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\Transcription"

$Name = "EnableTranscripting"

$value = "1"

New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force

$Name = "EnableInvocationHeader"

$value = "1"

New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force

#Create directory and set permissions to write only for users

$Name = "OutputDirectory"

$value = "C:\Windows\PSLogging"

New-Item $value -type directory

$acl = Get-Acl $value

$acl.SetAccessRuleProtection($True, $False)

$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Users","Write,ReadAndExecute,AppendData", "ContainerInherit, ObjectInherit", "None", "Allow")

$rule2 = New-Object System.Security.AccessControl.FileSystemAccessRule("DOMAIN\Security Admins","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")

$acl.AddAccessRule($rule)

$acl.AddAccessRule($rule2)

Set-Acl $value $acl

New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType String -Force

Use PowerShell to copy the contents of the previous day's transcript log folder from each machine listed in Active Directory into a central folder. You can set this up as a scheduled task to run at the start of each day using the following script:

$YesterdaysLog = Get-Date -Date (Get-Date).AddDays(-1) -UFormat %Y%m%d

New-Item C:\AllLogs\$YesterdaysLog -ItemType Directory

$Computers = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name

foreach ($Computer in $Computers) {

Copy-Item "\\$Computer\C$\Windows\PSLogging\$YesterdaysLog\*" -Destination "C:\AllLogs\$YesterdaysLog\"

}

Last words about the benefits of PowerShell logging

PowerShell logging is easy to set up and a good security practice to protect the enterprise. It just takes a few Group Policy changes to start logging PowerShell activity on all your machines.

If the time comes when a malware infection hits your organization via PowerShell, these logs can help determine the origin and assist with the effort to minimize further attacks. For added protection, admins should investigate the use of security tools such as ELK Stack that can help identify malicious activity. 

Dig Deeper on Windows Server OS and management