SHA1 "Shattered" Collision and Octopus Deploy

Last updated

Shattered logo

Extracted from our blog post in 2017.

In 2017 Google announced an attack that makes it practically possible to generate SHA1 hash collisions.

The risk seems to focus on areas where certificates are used for digital signatures, not encryption. So far we haven't seen any clear reports that this applies to SSL/TLS - our understanding is that there's a risk someone could make a fake certificate and it could be "trusted" as if it were a real one, but not that SSL/TLS data could be decrypted. Of course, I'm no expert!

Either way, SHA1 has been on the way out for some time, and certificate authorities stopped issuing SHA1 certificates quite some time ago. This is just another nail in the coffin for SHA1.

Octopus and Tentacle prior to 3.14 use SHA1 by default

When you install Octopus and the Tentacle agent, they both generate X.509 certificates that are used to encrypt the connection between them (via TLS). When we generated these self-signed certificates in versions before 3.14, we used SHA1. This is the default setting of the certificate generation function that we call in the Windows API, and not something we ever thought to change.

Mitigation

Starting out with Octopus? Install Octopus and Tentacle 3.14 or newer if you are starting from scratch so SHA256 certificates will be generated by default.

Already have Octopus up and running and you are concerned about the SHA1 certificates, you can upgrade to Octopus and Tentacle 3.14 or newer, and use the command-line interface to generate new SHA256 certificates, then tell Octopus and Tentacle to use/trust those instead. For details, check our documentation page on how to use custom certificates with Octopus and Tentacle.

Other things you should check

You'll want to check whether SHA1 is being used in other places. Common examples for Octopus users might include:

  • The certificate used for the Octopus web frontend if you use HTTPS. Normally this is something people provide themselves.
  • Certificates used for authenticating with third party services, like Azure management certificates
  • Certificates used to provide HTTPS for web sites that you deploy

Detecting SHA1 certificates with PowerShell

Given an X509Certificate2 object, here's a PowerShell function that checks whether it uses SHA1:

function Test-CertificateIsSha1{
    [cmdletbinding()]
    param(  
    [Parameter(
        Position=0, 
        Mandatory=$true, 
        ValueFromPipeline=$true)
    ]
    [System.Security.Cryptography.X509Certificates.X509Certificate2[]]$Certificate
    ) 

    process 
    {
       foreach($cert in $Certificate)
       {
           $algorithm = $cert.SignatureAlgorithm.FriendlyName
           $isSha1 = $algorithm.Contains("sha1")
           Write-Output $isSha1
       }
    }
}

Here's a PowerShell script that you can use to check whether a website is using a SHA1 certificate. Kudos to Jason Stangroome for the initial implementation of Get-RemoteSSLCertificate:

function Get-RemoteSSLCertificate {
    [CmdletBinding()]
    param (
        [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
        [System.Uri[]]
        $URI
    )
    process 
    {
       foreach ($u in $URI)
       {
            $Certificate = $null
            $TcpClient = New-Object -TypeName System.Net.Sockets.TcpClient
            try {
                $TcpClient.Connect($u.Host, $u.Port)
                $TcpStream = $TcpClient.GetStream()
                $Callback = { param($sender, $cert, $chain, $errors) return $true }
                $SslStream = New-Object -TypeName System.Net.Security.SslStream -ArgumentList @($TcpStream, $true, $Callback)
                try {
                    $SslStream.AuthenticateAsClient('')
                    $Certificate = $SslStream.RemoteCertificate
                } finally {
                    $SslStream.Dispose()
                }
            } finally {
                $TcpClient.Dispose()
            }
            if ($Certificate) {
                if ($Certificate -isnot [System.Security.Cryptography.X509Certificates.X509Certificate2]) {
                    $Certificate = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $Certificate
                }

                Write-Output $Certificate
            }
        }
    }
}

$sites = @("https://www.yoursite.com", "https://anothersite.com")
$sites | ForEach-Object {
    $site = $_
    $cert = Get-RemoteSSLCertificate -Uri $site
    if (Test-CertificateIsSha1 -Certificate $cert) {
        Write-Warning "Site: $site uses SHA1"
    }
}

And here's a script that checks whether your IIS server is using any SHA1 certificates:

Import-Module WebAdministration

foreach ($site in Get-ChildItem IIS:\Sites)
{
    foreach ($binding in $site.bindings.Collection)
    {
        if ($binding.protocol -eq "https") 
        {
            $hash = $binding.CertificateHash
            $store = $binding.certificateStoreName

            $certs = Get-ChildItem "Cert:\LocalMachine\$store\$hash"

            foreach ($cert in $certs) 
            {
                if (Test-CertificateIsSha1 -Certificate $cert) 
                {
                    Write-Warning "Site: $site.Name uses SHA1"
                }
            } 
        }
    }
}

You can easily run this in the Octopus Script Console across all of your machines:

Running the IIS SHA1 binding detection in the Octopus script console