Organisations should use script whitelisting to help mitigate execution of malicious PowerShell scripts.
Script execution policy
PowerShell has the ability to enforce a policy that controls the execution of PowerShell scripts and modules. The PowerShell script execution policy is often heralded as the solution to securing PowerShell; however, it can often be bypassed and should not be relied on to provide a secure PowerShell environment.
It is possible to enforce the script execution policy via Group Policy. The recommended script execution policy is AllSigned (all scripts have to be signed by a Trusted Publisher). Alternatively, for workstations where scripts are developed, the script execution policy should be RemoteSigned (only remotely downloaded scripts have to be signed by a Trusted Publisher). Organisations should use code signing certificates that are trusted across the entire environment to ensure a consistent script execution experience across the environment.
See Appendix B for more details on implementing script execution policies.
Organisations should install PowerShell version 5.0 where possible due to the superior logging capabilities provided over earlier versions.
Role-based application whitelisting
PowerShell hosts should be restricted to privileged accounts performing administrative actions, or users with a defined need. Whitelisting is the preferred approach to restricting access to default PowerShell hosts as it will also be effective against custom PowerShell hosts; however, a blacklist approach on the default hosts (powershell.exe and powershell_ise.exe) is better than no restrictions. Access to PowerShell hosts should be denied through the use of technical controls for users that do not have a business need.
The implementation details for role-based application whitelisting will vary depending on the operating systems and Active Directory (AD) functional levels involved. Appropriate vendor documentation should be consulted to ensure the implementation’s effectiveness.
Logging and analysis
As it is difficult to secure PowerShell completely, centralised logging and log analysis of PowerShell-based activities should be the foundation of a secure PowerShell deployment. With PowerShell version 5.0, it is possible to enforce logging of a wide range of PowerShell activities. An active log analysis capability will greatly enhance an organisation’s ability to identify unusual activity. A number of logging options can be configured via Group Policy making deployment relatively easy.
PowerShell event logging
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  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.
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.
Event log analysis
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.
Prevent modification and enable auditing of configuration settings and transcripts
To make obfuscation of malicious PowerShell behaviour harder, organisation should ensure standard users are not given permission to modify the relevant registry keys or to modify the transcript folder.
Organisations should also consider using Protected Event Logging to prevent leakage of sensitive information such as passwords in script blocks that are logged to the event log.
See Appendix F for more details on applying permissions via Group Policy to registry keys and file folders.
Configuration of PowerShell remoting is well documented by Microsoft in their Installation and Configuration for Windows Remote Management publication at https://docs.microsoft.com/en-au/windows/desktop/WinRM/installation-and-configuration-for-windows-remote-management.
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 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.