PowerShell – Code Sign and validate files in a folder with optimized logic

Last Updated on February 25, 2024 by Michael Morten Sonne

Intoduction

The script lacks a function to regenerate the _signed file in case the original file is changed and it needs to be updated.

But a -Force argument exitst there will remove all _signed files in the folder and sign the files again.

If you can assist by providing the correct code for this, please share your insights, as I’ve attempted various methods without success as I will not recrate all _signed file every time… 🤔

If a function for this is created, I will update this blog post to reflect it.

As you read, the script is allmost complete (95%) – a small part is missing… the rest of the script works fine👌 As the script is now, it looks for .ps1 files – this can you change to your need!

Let’s delve into what makes this script a valuable asset for script integrity and security in the vast landscape of PowerShell usage.

In a celebration of community collaboration, I shares here a script I created some time ago to help the security of your PowerShell scripts!

In the dynamic realm of cybersecurity, safeguarding the integrity and authenticity of PowerShell scripts is a most. This script simplifies the task of signing all scripts within a specified folder, preserving the originals while generating corresponding “_signed” counterparts to elevate security.

This robust script goes beyond more signing – it includes an intelligent validation mechanism. It checks for unsigned scripts, invalid hash values or missing signatures, ensuring a comprehensive approach to script security and not do stuff not needed to do. Let’s explore the distinctive features that make this script an invaluable asset, ensuring script integrity and security in the landscape of PowerShell use.

Discover how this script enhances not only the reliability of your scripts but also contributes to a more secure scripting environment – Additionally, it boasts user-friendly functionality, effortlessly navigated with just a few arguments, making it ideal for seamless automation too!

What is Code signing

In the intricate realm of cybersecurity, code signing emerges as a fundamental practice, akin to a digital seal of authenticity. At its core, code signing involves the process of attaching a digital signature to software or scripts, affirming the origin and integrity of the code. This cryptographic signature, generated with a private key, is verified using a corresponding public key, establishing trust in the code’s legitimacy.

Why Code Signing is crucial

  • Integrity: Code signing serves as a digital fingerprint, ensuring that the code has not been tampered with since the time of signing. This integrity check is vital for safeguarding against malicious alterations or unauthorized modifications to scripts and software.
  • Authorship Verification: Knowing the source of a script or application is pivotal for establishing trust. Code signing provides a means to verify the identity of the entity responsible for the code, enhancing transparency and aiding in risk assessment.
  • User Confidence: End-users often hesitate to run unsigned scripts or applications due to security concerns. Code signing allays these apprehensions by demonstrating a commitment to security, thereby fostering user confidence and encouraging the adoption of trusted software.
  • Preventing Unauthorized Code Execution: Unsigned code may trigger warnings or be blocked altogether by security measures. Code signing mitigates this risk, allowing authorized scripts and applications to run without impediments, while potentially harmful or unauthorized code is flagged.

In essence, code signing is a cornerstone of cybersecurity strategy, providing a tangible layer of protection against an evolving landscape of threats. As we navigate a digital world rife with potential risks, the adoption of code signing emerges not just as a best practice but as a necessary measure to fortify the trustworthiness and security of software and scripts. The script here epitomizes this commitment to secure coding practices by empowering users to seamlessly integrate code signing into their PowerShell scripts, reinforcing the broader collective effort to enhance cybersecurity.

Supported files for Code Signing

In the context of code signing, the specific file types or extensions that are supported can vary based on the platform and tools being used. Generally, code signing is commonly applied to executable files, libraries, scripts, and installer packages. Some common file extensions for code signing include:

  • Executable Files:
    • .exe (Windows executable)
    • .dll (Dynamic Link Library)
    • .sys (System file)
    • .msi (Windows Installer package)
  • Script Files:
    • .ps1 (PowerShell script)
    • .psm1 (PowerShell Module file)
  • Installer Packages:
    • .msi (Windows Installer package)

It’s important to note that the exact list of supported file types may depend on the code signing tool or platform you are using. Additionally, some tools may allow you to sign files with custom or specific extensions.

But a -Force argument exitst there will remove all _signed files in the folder and sign the files again.

This PowerShell script is supporting the supported file types of the Set-AuthenticodeSignature Cmdlet!

DigiCert have a nice overview of all files types and some tools here for Code Signing – you can check it out if you will: Files supported for signing (digicert.com)

Find the certificate thumbprint you need

Windows MMC console

In Windows, go to Search and find Manage user certificates

  • Open Manage user certificates
  • In certmgr Certificates for Current User, go to Personal > Certificates (the certificate you will use need to be imported/deployed to you). Your view should look like this:
Certificates in my user store
  • Now select your certificate where the Intended Purposes is Code Signing
My Code Sign certificate
  • Now go to Details – it´s here we can see the information needed (for the current v. of the script when this post is written):
Details page of the certificate – in the top of the view
  • Now scroll down to the buttom, where we can find the Thumbprint field and copy it:
Here is the Thumbprint we need for the selected Certificate

Now you have the Certificate trumbprint we need in the argument for the PowerShell script to Code Sign the files (.exe, .ps1 and so on).

PowerShell

In a PowerShell Console we can use this commands to find the trumbprints of certificates in the current users cert store in Windows and show the certificate use also (we need: Code Signing (1.3.6.1.5.5.7.3.3) from Enhanced Key Usage);

# Get the certificates in the Current User store
$certificates = Get-ChildItem -Path Cert:\CurrentUser\My

# Display information about each certificate
foreach ($cert in $certificates) {
    Write-Host "Certificate Subject: $($cert.Subject)"
    Write-Host "Thumbprint: $($cert.Thumbprint)"
    
    # Extract Enhanced Key Usage information
    $eku = $cert.Extensions | Where-Object {$_.Oid.FriendlyName -eq "Enhanced Key Usage"} | ForEach-Object { $_.Format(0) }

    if ($eku) {
        Write-Host "Enhanced Key Usage: $eku"
    } else {
        Write-Host "Enhanced Key Usage information not available."
    }

    Write-Host "-----------------------------------------"
}

The output in your PowerShell Console should view some information like this:

Certificate output – selected the Enhanced Key Usage from certificates

Copy the Thumbprint field and copy it.

Now you have the Certificate trumbprint we need in the argument for the PowerShell script to Code Sign the files (.exe, .ps1 and so on).

The Script

What the script it doing

The primary function of this script is to sign PowerShell scripts using a specified certificate, hash algorithm, and timestamp server. It creates signed copies of the original scripts, ensuring that the integrity of the source remains intact. By importing the complete certificate chain and leveraging timestamping, the script fortifies the assurance of script authenticity.

How to use the Script

To sign your scripts using this script is a straightforward process, thanks to its well-defined parameters you can see here:

  • Path: Specify the path to the folder containing the scripts you want to sign.
  • Hash: Choose the hash algorithm for signing (default is SHA256).
  • Thumbprint: Provide the thumbprint of the code signing certificate in the current user store (you need access to the private key).
  • TimestampServer: Optionally, set the URL of the timestamp server (default is http://timestamp.sectigo.com, but you can change it).
  • WhatIf: An optional switch that allows you to preview the changes without executing the actions (The signing process involves creating ‘_signed‘ files (based on the original names) and deleting any existing ‘_signed’ files).
  • Force: An optional switch that enables the forced deletion of any ‘_signed’ files in the directory, if present.

Here’s an example command:

.\SignAllFilesTo_Signed.ps1 -Path "C:\Scripts" -Hash "SHA256" -Thumbprint "d6a630b8f65c473c19f8b694491130073fccdb32" -TimestampServer "http://timestamp.sectigo.com" -WhatIf

This example signs all PowerShell scripts in the “C:\Scripts” folder using SHA256, the specified certificate, and the provided timestamp server, while the WhatIf switch previews the changes

The script in action

The script lacks a function to regenerate the _signed file in case the original file is changed and it needs to be updated.

If you can assist by providing the correct code for this, please share your insights, as I’ve attempted various methods without success as I will not recrate all _signed file every time 🤔

If a function for this is created, I will update this blog post to reflect it.

Signing

Here, the script in full action where it copy the original file to a corresponding “_signed” file. It proceeds to sign the duplicated file with the specified certificate, showcasing each step and action performed:

The script in full sign action

Re-signing

Here, the script in full action – it skips a _signed file that is already validated as signed and valid with the specified certificate. Subsequently, the script proceeds to re-sign a file with the specified certificate that has been tampered with or altered (changed/edited), rendering the signature as invalid. This showcases each step and action performed:

One script is re-signed and one is still valid and skipped for signing

All files is signed and valid

Here, the script in full action – it skips _signed files that is already validated as signed and valid with the specified certificate. No actions to make:

All is signed and valid

WhatIf

Here, the -WhatIf statement is showcased, indicating that the script won’t make any alterations or sign scripts; rather, it will demonstrate the actions it would take if -WhatIf is not set:

The scripts -WhatIf action

Force

Here, the script in full action with the -force argument set – it will delete any existing _signed files that is already in the folder and will then sign all files again:

Force removal of any exiting files and sign all again

Now you are ready to test it! 🔐👌

Witness the script in full action. It skips a “_signed” file that has already been validated as signed and valid with the specified certificate. Subsequently, the script proceeds to re-sign a file with the specified certificate that has been tampered with or altered, rendering the signature invalid. Each step and action are meticulously showcased.

Moreover, the script allows for customization of the file extension for signing. You can modify it according to your specific requirements. The supported file extensions for code signing include files with extensions can you see here: PowerShell – Code sign and validate files in a folder with optimized logic # supported files for code signing

Here is the script hosted on my GitHub profile:

Conclusion

In a digital world where trust is paramount,this script here emerges as a valuable tool for script integrity. This empowers users to seamlessly sign their PowerShell scripts, ensuring they remain unaltered while benefiting from enhanced security through code signing.

By prioritizing the use of complete certificate chains and timestamping, the script not only provides a robust defense against tampering but also simplifies the process for users committed to securing their PowerShell scripts.

Whether you’re a cybersecurity professional, script developer, or IT administrator, this is a worthy addition to your arsenal for safeguarding PowerShell scripts in an ever-vigilant digital environment! 🔐👌

The script lacks a function to regenerate the _signed file in case the original file is changed and it needs to be updated.

But a -Force argument exitst there will remove all _signed files in the folder and sign the files again.

If you can assist by providing the correct code for this, please share your insights, as I’ve attempted various methods without success as I will not recrate all _signed file every time… 🤔

If a function for this is created, I will update this blog post to reflect it.

Thank you for taking the time to visit my blog. Kindly share it with others if you find it helpful for them! 😉🔐👍

Stay tuned for the new post about something cool! 🥳

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Previous Article

Microsoft Defender for Identity - Updated Advanced Settings Page

Next Article

Honored to receive the Microsoft MVP Award in Security - Febuary 2024!

Related Posts

Discover more from Sonne´s Cloud

Subscribe now to keep reading and get access to the full archive 🤝🧑‍💻

Join 15 other subscribers