Code Signing PowerShell Scripts
Updated: Feb 14
In this article, I'll describe the process of Code Signing PowerShell scripts from a Microsoft CA. I'll not cover how Code Signing adds security, simply put Code Signing doesn't provide or was intended to provide a robust security layer.
However, Code Signing does provide both Authenticity and Integrity:
The Authenticity that the script was written or reviewed by a trusted entity and then signed.
Integrity ensures that once signed the script hasn't been modified, useful when deploying scripts or executing scripts by a scheduled task with a service account.
Bypassing Code Signing requirements is simple, open ISE, paste in the code and F8, instant bypass. However, my development 'Enterprise' system is not standard, ISE won't work as Constrained Language Mode prevents all but core functionality from loading, meaning no API's, .Net, Com and most modules.
As a note, even with the script, code signed, ISE is next to useless with Constrained Language Mode enforced. Scripts require both signing and authorising in Applocker\WDAC and will only execute from native PowerShell.
Back to it.....
This is a typical message when executing a PowerShell script with the system requiring Code Signing. To successfully execute the script, the script must be signed with a digital signature from either a CA or Self Signed certificate.
I'm not going to Self Sign, it's filth and I've access to a Microsoft Certificate Authority (CA) as part of the Enterprise.
Login to the CA, launch 'Manage' and locate the 'Code Signing' template, then 'Duplicate Template'.
Complete the new template with the following settings:
Name the new certificate template with something meaningful and up the validity to 3 years or to the maximum the corporate policy allows.
Update the Compatibility Settings and Certificate Recipient to 'Windows Server 2016' and 'Windows 10/Windows Server 2016' respectively.
Check the 'Allow private key to be exported'.
Set 'Minimum key size' to either 1024, 2048, 4096, 8192 or 16,384
Select 'Requests must use one of the following providers:' and check 'Microsoft Enhanced RSA and AES Cryptographic Provider' (description)
Ideally, enrolment is controlled via an AD Group with both READ and Enrol permissions. Do not under any circumstances allow WRITE or FULL.
Save the new template and then issue by right-clicking on 'Certificate Template' > New and 'Certificate Template to Issue'.
From a client and logged on with the account that is a member of the 'CRT_PowerShellCodeSigning' group, launch MMC and add the Certificate snap-in for the Current User.
Browse to Personal > Certificates and right-click in the empty space to the right, then click on 'All Tasks' > 'Request New Certificate.
Select the 'Toyo Code Signing' template and then click on 'Properties' to add in some additional information.
Add a Friendly Name and Description.
Enrol the template.
Now, right-click on the new 'Code Signing' certificate > All Tasks > Export.
Select 'Yes, export the private key'.
Ensure the 2 PKCS options are selected.
Check the 'Group or username (recommended)' and on the Encryption drop-down select 'AES256-SHA256'.
Complete the wizard by exporting the .pfx file
The final step is to sign a script with the .pfx file using PowerShell.
Set-AuthenticodeSignature -FilePath "C:\Downloads\SecureReport9.4.ps1" -cert "C:\Downloads\CodeSigning.pfx"
Open the newly signed script and at the bottom of the script is the digital signature.
Launch PowerShell.exe and run the script.
For those with Applocker\WDAC then the script requires adding to the allow list by file hash. Now I'll be able to execute my own Pentest script on my allegedly secure system and locate any missing settings.....
As always thanks for your support.