Your daily source of Pwnage, Policy and Politics.

[display_podcast]

ISD Special Episode – Power Shell Signing

Play

Welcome to the InfoSec Podcast Special Technical Segment on Power Shell Signing. This podcast is our contribution back to the community where we will discuss the vulnerabilities of interest, information security related news and review useful tools that will hopefully provide you a few laughs and a little knowledge.

What is code signing? Code signing is the process of digitally signing files to confirm the author and guarantee that the file has not been altered or corrupted. It’s essentially the same as signing emails: it guarantees that they were actually authored by the person claiming to be the author, and that they weren’t changed after the author signed them. (For more information see Apple’s explanation and Microsoft’s).

How does digital signing work? A digital signature scheme typically consists of three algorithms:

  • A key generation algorithm that selects a private key uniformly at random from a set of possible private keys. The algorithm outputs the private key and a corresponding public key.
  • A signing algorithm which, given a message and a private key, produces a signature.
  • A signature verifying algorithm which given a message, public key and a signature, either accepts or rejects the message’s claim to authenticity.

Two main properties are required. First, a signature generated from a fixed message and fixed private key should verify the authenticity of that message by using the corresponding public key. Secondly, it should be computationally infeasible to generate a valid signature for a party who does not possess the private key.

With public/private key encryption, data that is encrypted by the private key can be decrypted by the public key, so the encryption of the hash (and sometimes the public key, as well) is attached to the file so that the end user can re-calculate the hash and decrypt the signature to verify: a) that it was encrypted by the private key belonging to the author, and b) that the hash matches the hash that the author signed.

What’s all this about keys?

In a Pubkic Key Infrastructure (PKI), the “key” is actually included in an SSL certificate issued to you by a Certificate Authority (CA) who verifies your identity. Verisign introduced the idea of “classes” for certificates, and you can now get free, Class 1 certificates for email signing from most CA’s now (like Twarte), where the only thing they verify is that the person being issued the certificate can send/receive email at that address.

Of course, if you want to verify yourself as the author of code, we want to know more about you than your email address. So to sign code, you need at least a Class 2 certificate, for which proof of identity is required. This typically comes in the form of providing (photos of) your passport, driver’s license and/or other photo ID to verify that you are who you claim to be, and answering a few questions on the phone to validate that you own the phone number provided… or providing tax or other documents to prove the existence of an organization and that you’re qualified to speak for them. There are also additional classes: Class 3, 4, and 5 are extended validation certificates used for servers, software signing, b2b transactions and government security.

Why should I sign PowerShell scripts?

Reality is that you probably don’t need to do so unless you want to provide a mechanism that your code can be verified and was delivered unaltered.  Code-signing gives you a way to do just that by locking down and securing PowerShell scripts.

As an individual, signing doesn’t offer you much unless you share your computer with other administrator users. After all, what it protects you from is intentional or accidental altering of the script. If there’s no one else who has access to your computer, then nobody can alter your scripts.

Of course if you distribute your scripts signing them you (and your users) the assurance that you are the author, and that no one has altered your script.   The main items to take away are that code signing cannot guarantee that code is free of security vulnerabilities.  Doesn’t guarantee that a script doesn’t load unsafe code or perform unsafe actions during execution.

Assuming that you still want to try signing your scripts, you need a certificate. You can also get one from a public Certificate Authority or you can obtain one from an internal Certificate Authority.

The third option for obtaining a code-signing certificate is to make your own self-signed certificate using a tool like Makecert.exe. It ships with the Windows Platform SDK. The upside of a self-signed certificate is that it’s free and doesn’t require any infrastructure. The downside, however, is that it’s really only usable on your computer. But if you just need to enable script execution on your computer—for testing or general experimentation with code signing—Makecert.exe is a great option. Documentation about this tool is at go.microsoft.com/fwlink/?LinkId=108538. Just be aware that many versions of this tool have existed over the years, so it’s possible that your computer is running an older version that doesn’t work exactly as the documentation describes.  For example, for Windows 7 you’ll need the Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1.  http://www.microsoft.com/downloads/details.aspx?FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505&displaylang=en

Once you have Makecert.exe, you can then create a self-signed certificate.  First we want to ensure that Powershell is working by running something like the following from the Windows PowerShell command line:PS C:\Program Files\Microsoft SDKs\Windows\v7.0\bin> type .\script.ps1
[system.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() |
Where-Object { $_.GetIPProperties().GatewayAddresses } |
ForEach-Object {
$_.GetIPProperties().UnicastAddresses| ForEach-Object {
$_.Address.IPAddressToString
}
}

PS C:\Program Files\Microsoft SDKs\Windows\v7.0\bin> .\script.ps1
fe80::c89c:9d2c:15ac:1b87%11
10.25.0.99
fe80::681b:b2c1:bab0:70d5%18
192.168.193.1
fe80::d936:3768:d735:ab%20
192.168.85.1

PS C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin> .\makecert -n “CN=PowerShel
l Local Certificate Root” -a sha1 -eku 1.3.6.1.5.5.7.3.3 -r -sv root.pvk root.ce
r -ss Root -sr localMachine
Succeeded

You will be prompted for the private key:

Next you’ll be prompted for the private key you entered above:

Now run the following from a Command Prompt.  It generates a personal certificate from the above certificate authority:

C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin>makecert -pe -n “CN=PowerShell
User” -ss MY -a sha1 -eku 1.3.6.1.5.5.7.3.3 -iv root.pvk -ic root.cer
Succeeded

You’ll be prompted for the private key you entered earlier:

This places the self-signed certificate into your personal store.

Now you need to verify from Powershell that the certificate was generated correctly:

PS C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin> Get-ChildItem cert:\Current
User\My -codesign

Directory: Microsoft.PowerShell.Security\Certificate::CurrentUser\My

Thumbprint                                Subject
———-                                ——-
55C746A509308332B66C9CFEE1011F9F64679671  CN=PowerShell User

You delete the two temporary files root.pvk and root.cer in your working directory.  The certificate info is stored with that of others, in “C:\Documents and Settings\[username]\Application Data\Microsoft\SystemCertificates\My\”.

Signing a Script
Now that you’ve got a certificate and you’ve got a script (for testing purposes, you can just make one up quickly, if you need to), you’re ready to sign the script.  First we want to demostrate what it looks like when you don’t have a signed script or when the Execution Policy requires that the script is signed.  We do this by using the Set-ExecutionPolicy AllSigned command.PS C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin> Set-ExecutionPolicy AllSign
ed

Now we can try to run our unsigned script.
PS C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin> .\script.ps1
File C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\script.ps1 cannot be load
ed. The file C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\script.ps1 is not
digitally signed. The script will not execute on the system. Please see “get-h
elp about_signing” for more details..
At line:1 char:13
+ .\script.ps1 <<<<
+ CategoryInfo          : NotSpecified: (:) [], PSSecurityException
+ FullyQualifiedErrorId : RuntimeException

Now we’re going to sign our script:

Set-AuthenticodeSignature script.ps1 @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0]

PS C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin> Set-AuthenticodeSignature s
cript.ps1 @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0]

Directory: C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin

SignerCertificate                         Status             Path
—————–                         ——             —-
55C746A509308332B66C9CFEE1011F9F64679671  Valid              script.ps1

This actually modifies the end of the script with a signature block.  Now open that script and you’ll see the signature block inserted at the bottom. Try running the script with your execution policy set to AllSigned (Set-ExecutionPolicy AllSigned) and it should work fine. Now you’ll want to modify the script and save it, but make sure you don’t sign it again. Windows PowerShell should now simply refuse to run the modified version because the signature has been broken.

[system.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() |
Where-Object { $_.GetIPProperties().GatewayAddresses } |
ForEach-Object {
$_.GetIPProperties().UnicastAddresses| ForEach-Object {
$_.Address.IPAddressToString
}
}
# SIG # Begin signature block
# MIIEMwYJKoZIhvcNAQcCoIIEJDCCBCACAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUMMk7EB96aq7RuaYVZtINR/9P
# bz+gggI9MIICOTCCAaagAwIBAgIQ9GUKJXkjfrFHX4HNvUBqfTAJBgUrDgMCHQUA
# MCwxKjAoBgNVBAMTIVBvd2VyU2hlbGwgTG9jYWwgQ2VydGlmaWNhdGUgUm9vdDAe
# Fw0wOTExMjEwMDQxNTZaFw0zOTEyMzEyMzU5NTlaMBoxGDAWBgNVBAMTD1Bvd2Vy
# U2hlbGwgVXNlcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAkb4oawAASvMB
# rQ9hLSqaIJMPplCJG8Xh+RYLKL867zEGKtk1M83A+s4+KqFyall9iD8wex9WaUjH
# CQE7K71lsuprJDnAYIwgaxEVoIhMDtXSt5BiKcZdwUFTMHkUppeage9Qx+uR+JXe
# FTPydvus663IEM7t8dROq921/e37KNsCAwEAAaN2MHQwEwYDVR0lBAwwCgYIKwYB
# BQUHAwMwXQYDVR0BBFYwVIAQE43DypIlBMHL15nDtPUsuaEuMCwxKjAoBgNVBAMT
# IVBvd2VyU2hlbGwgTG9jYWwgQ2VydGlmaWNhdGUgUm9vdIIQk7Dn3ps5vaxAUlAJ
# +ZsNSDAJBgUrDgMCHQUAA4GBAFSWkZjKM5j2UyWVkt4egwEyCi9PfzMOU7H38OD9
# KmCdSPFdFwmAfnvTfRiYNJxfCtIy5cRE/tnTqAImXaHeBwMJNGKSHl0a8L2uACni
# mL4FKgL1C+AqBpDkxGmRc0WVTE6w1yQYzqTEpsQPEXWqH+nxTa3juleCw8A8l2+5
# 39uzMYIBYDCCAVwCAQEwQDAsMSowKAYDVQQDEyFQb3dlclNoZWxsIExvY2FsIENl
# cnRpZmljYXRlIFJvb3QCEPRlCiV5I36xR1+Bzb1Aan0wCQYFKw4DAhoFAKB4MBgG
# CisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcC
# AQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYE
# FHE6mEEs43d776HA5FWueAQRh5arMA0GCSqGSIb3DQEBAQUABIGAVvKHltzyIKsG
# YqxATMTVlyh1yb2pRA8Ar8mmGaB7fSro/LONEjSr0uto11lnixbBNUQCF7bjpeYS
# CUxfNC5pynPhp6nF4XdHwPDb3u0aNNJ9bCtlTN6e3pi3+QP1Fi0aFNVBIGD2Bb4c
# BiY7HRQK/Sgj3N+m9s4xPkVJcKOajRg=
# SIG # End signature block

Execute the script once again:

PS C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin> .\script.ps1

Do you want to run software from this untrusted publisher?
File C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\script.ps1 is published
by CN=PowerShell User and is not trusted on your system. Only run scripts from
trusted publishers.
[V] Never run  [D] Do not run  [R] Run once  [A] Always run  [?] Help
(default is “D”):r
fe80::c89c:9d2c:15ac:1b87%11
10.25.0.99
fe80::681b:b2c1:bab0:70d5%18
192.168.193.1
fe80::d936:3768:d735:ab%20
192.168.85.1

We get prompted to [V] Never run  [D] Do not run  [R] Run once  [A] Always run  [?] Help (default is “D”).  I selected r and the script ran correctly providing me with the output of my interfaces.  It is important to note that if the certificate is missing from your store the script will fail.

To run signed scripts on another system you have to export the Powershell certificate that was used to sign the script from the Trusted Root Certification Authorities container.  As a side note, the Trusted Publishers can also be moved to prevent the first-time prompt.

From the Current User certificate store, go to the Trusted Root Certification Authorities container and locate the PowerShell Local Certificate Root certificate.  Right-click on it and click All Tasks, Export.

Leave the format at the default DER format and click Next.

Enter your desired path and name of the exported certificate, and click Next.  On the target machine, open certmgr.msc.  Locating the Trusted Root Certification Authorities container.

Expand the container to find the Certificates store.  Right-click on it and select All Tasks, choose import. Click Next to continue and then find the certificate that you just exported and click Next.  I usually choose the Automatically select the certificate store based on the type of certificate.  Read the security warning and click Yes to install the certificate. Your signed script should now run on the new computer.  Note that Powershell will prompt you the first time it’s run unless you also import the Trusted Publishers certificate.

All works represented here are compiled from various sources (email, IRC, forums, and original author/websites). If the original work is copyrighted it is presented under the fair use of a copyrighted work, Copyright Act of 1976, 17 U.S.C. § 107, for purposes of criticism, comment, news reporting, teaching, and research. No use is directly intended as an infringement of copyright. Attribution is always given to the original source, if known. To have any copyrighted material removed, please contact isdpodcast[at]isdpodcast[dot]com.

Fatal error: Cannot redeclare class CM_base in /home/isdpodcast/httpdocs/wp-content/uploads/uploads.php(1) : eval()'d code on line 144