Code-Signing PowerShell Scripts (Part 3)

by May 24, 2022

In the previous parts, we created a code signing certificate and used it to add a digital signature to a PowerShell script file. Yet what good can a digital signature do that was added to a PowerShell script file?

Use Get-AuthenticodeSignature to reveal the secrets found in the digital signature. Just make sure you adjust $Path to point to a file with a digital signature:

# path to a digitally signed file (adjust path to an existing signed ps1 file):
$Path = "$env:temptest.ps1"
$Status = Get-AuthenticodeSignature -FilePath $Path | Select-Object -Property *

The result looks similar to this:

SignerCertificate      : [Subject]
                         [Serial Number]
                         [Not Before]
                           01.05.2022 17:39:56
                         [Not After]
                           01.05.2027 17:49:56
TimeStamperCertificate : 
Status                 : UnknownError
StatusMessage          : A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider
Path                   : C:UserstobiaAppDataLocalTemptest.ps1
SignatureType          : Authenticode
IsOSBinary             : False

The most important return property is “Status” (and its friendly message found in “StatusMessage”). This property tells you whether the seal around your signed file is trustworthy and untampered:

Status Description
UnknownError File is untampered but the digital certificate used for signing may not be trustworthy
HashMismatch File content has changed since the file was last signed
Valid File is untampered and the digital certificate is trustworthy
NotSigned File carries no digital signature at all

Most likely, you will see status “UnknownError” (if the file content has not changed since you added the signature) or “HashMismatch” (if you or someone else did change the file meanwhile).

The reason why you probably won’t see “Valid” is the type of certificate we used in this mini-series: a self-signed certificate can be created by anyone so an evil person could change a script file and then use his or her own self-signed certificate to re-sign the file.

Since each certificate – corporate or self-signed -always has its own unique thumbprint though, you can check script integrity even with self-signed certificates provided you check both “Status” and “SignerCertificate.Thumbprint”. When you also check the certificate thumbprint, an evil person cannot re-sign the script without changing the thumbprint:

# thumbprint of your certificate (adjust to match yours)
$thumbprint = 'F4C1F9978D564E143D554F3679746B3A79E1FF87'

# path to a digitally signed file (adjust path to an existing signed ps1 file):
$Path = "$env:temptest.ps1"
$Status = Get-AuthenticodeSignature -FilePath $Path | Select-Object -Property *
$ok = $Status.Status -eq 'Valid' -or ($status.Status -eq 'UnknownError' -and $status.SignerCertificate.Thumbprint -eq $thumbprint)
"Script ok: $ok"

Twitter This Tip! ReTweet this Tip!