signing-powershell-scripts
Unauthorised PowerShell scripts can and should be a cause of concern on a network, at the higher end of the risk level many Windows malware or Ransomware campaigns can utilise PowerShell scripts as part of their attack. Blocking PowerShell scripts entirely is not an ideal solution so setting a secure policy Domain wide is a good middle ground.
Key steps for the process are:
- Set domain wide policy.
- Create a code signing certificate and distribute.
- Sign our PowerShell script.
Set domain policy to require signed scripts
First step to tighten security around unauthorized PowerShell scripts is to enforce a domain wide policy that only allows signed scripts to run. To do this we create a Group Policy object and link it at the required level in AD. Set the policy by configuring the Turn on script execution
policy at Computer Configuration - Policies - Administrative Templates - Windows Components - Windows PowerShell
We can see it in action by running (or attempting to run) a script on a client before and after we apply the group policy.
Before:
After:
Create our code signing cert
There are multiple ways to do this depending on the environment and requirements. The simplest method if it was for individual use would be to create a self-signed cert, but for this setup I'm going to create the cert to sign the scripts on a CA server within an ADDS domain which will simplify the process of trusting the signed scripts (more on that later).
First we duplicate Code signing template. There are a lot of options that can be changed in the cert template settings (things like cert expiry etc) but for this example I'm sticking as close to defaults as possible.
Set Compatibility level most suitable to your environment.
Now add out template to our CA active templates which can be issued.
Next we request a new cert via the user Certificate MMC, I'm doing this on the same machine.
Select our newly created template
Finally we need to distribute our cert to clients on the domain. If we don't do this clients will get a Do you want to run software from this untrusted publisher
prompt. To distribute the cert we need to export it to .cer then create a new GP object and link it to our computers OU.
- First export the cert from the server/ computer we created on, default settings and export to DER encoded binary .cer are fine.
- Then create a GP object, import the cert to the
Computer Configuration - Policies - Windows Settings - Security Settings - Public Key Policies - Trusted Publishers
GP setting and link the GP object to our computers OU.
Sign a PowerShell script
To sign our PowerShell script we need to view the thumbprint of our newly created code signing cert via MMC, then run the command below to view our code signing certs. Select the appropriate cert when running the second command by altering the [0]
value, in my case I only have the one matching cert so I use [0]
. Once we have that we can use the command sti sign our cert.
Get-ChildItem cert:\CurrentUser\my -codesigning Set-AuthenticodeSignature .\pc-signed.ps1 @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0]
And finally, we can now copy our signed cert to one of our domain clients and will will now run without the previous error.