Windows PowerShell is based on the runtime (CLR) of the .NET framework and is shipped with Windows as part of the Windows Management Framework (WMF). Powershell scripts can thus be used to read and edit all essential parts of a Windows operating system, assuming the respective rights.
Since Powershell is also used by malware, the operating systems usually prohibit the execution of scripts downloaded from the Internet or unsigned scripts in general.
A digital signature is the result of a cryptographic process that uses a secret signing key to calculate a value from any data: the signature. This value makes it possible to use the publicly known key to verify two important properties of information security management:
Here in this context, it means that before executing a script, the operating system checks whether the signature matches the content of the scripts and whether the signature was made with a key that can be trusted.
If the signature is not correct, for example, a malicious actor could have manipulated the contents of the script.
Run the following code in Powershell as a normal user. A certificate is stored in its own certificate store.
New-SelfSignedCertificate -Subject 'CN=Powershell Code Signing Cert' -Type CodeSigningCert -CertStoreLocation Cert:\CurrentUser\My -HashAlgorithm 'sha256'
Using Powershell, the certificate could now be moved to the trusted root certificate store. It is easier to do this using certmgr.msc
.
Now move the certificate you just created from “My Certificates” to the “Trusted Root Certification Authorities” store.
## sign_file.ps
## Signs the named file with the first codesigning certificate from the user's root certificate store
param([string] $file=$(throw "Please specify a filename."))
Set-AuthenticodeSignature $file @(Get-ChildItem Cert:\CurrentUser\Root -CodeSigningCert)[0]
Now we need to sign the signature script itself before we can use it:
Set-AuthenticodeSignature .\sign_file.ps @(Get-ChildItem Cert:\CurrentUser\Root -CodeSigningCert)[0]
Don’t forget to adjust the policy so that all scripts must have a valid signature:
Set-ExecutionPolicy -ExecutionPolicy AllSigned
Voilà. Now we can sign our scripts using
.\sign_file.ps file.ps
The signature is attached to the code in the script itself. Each time a change is made, it must be re-signed.
To be a bit more secure, instead of taking the first signature key, it would be better to take exactly the key that was created. This can be done using its ID.