Authenticode verification vulnerability pattern


There is a common vulnerability pattern in various implementations of authenticode signature verification in .NET. It was found multiple times in different products in the past and I have seen it myself during security audits.

Its name is X509Certificate.CreateFromSignedFile. Frankly saying it is hard to blame developers - .NET Framework libraries are quite mature and there is API for almost anything you ever needed. Yet as far as I know the only way to verify the signature is to P/Invoke WinVerifyTrust. It is inconvenient and hacky for an average .NET developer, so when they are tasked with adding authenticode signature verification of an executable the method X509Certificate.CreateFromSignedFile catches their eye.

On top of that internet is a mix of good advises and misleading(to say the least) articles (some even blogged by Microsoft). So the developers usually come with something like:

try
{
    var cert = X509Certificate.CreateFromSignedFile(filePath);
    var cert2 = new X509Certificate2(cert);
    return cert2.Verify();
}
catch // or catch CryptographicException
{
    return false;
}

Testing shows that the code correctly returns true for properly signed executables and false for the ones without a signature. When in fact it is vulnerable.
The flaw here is that X509Certificate.CreateFromSignedFile doesn’t verify if a signature of the executable is valid. It only extracts the certificate from the file and verifies the certificate itself. Attackers may tamper valid signed executables or transfer a valid certificate to an unsigned file. There are tools for transplanting certificates from one executable to another like SigPirate or SigThief.

I decided to look around for the pattern in popular open-source projects and have found the vulnerability in two of them.

The first one was in Dynamo BIM by Autodesk. The vulnerable code can be found here. As a PoC I have built an unsigned .NET assembly and used SigPirate to transplant a certificate from one of Microsoft signed assemblies. Autodesk has issued CVE-2020-7079 for the vulnerability and released an advisory. The diff of the fix can be found here.

The other vulnerable code was in SoundSwitch project. The vulnerable code can be found here. There were two options to bypass the check. The first one was to transplant the certificate from the official SoundSwitch executable. The second one - to create a self signed certificate with arbitrary Subject and Issuer:

  • Run powershell New-SelfSignedCertificate -Type CodeSigningCert -certstorelocation cert:\CurrentUser\my -Subject "CN=Antoine Aflalo soundswitch" -Issuer "CN=Certum"
  • export the certificate to a file cert.pfx
  • signtool.exe sign /p a /f cert.pfx Legit.exe

The signature wouldn’t be valid on other machine, but it would pass IsCertumSigned and demonstrates possible Subject and Issuer collisions with other certificates. The diff of the fix can be found here.

Timeline

2020.02.19 - Report to the owner of SoundSwitch is sent.
2020.02.20 - Report to Autodesk is sent.
2020.03.01 - Autodesk merges a fix.
2020.03.05 - Dynamo BIM version 2.5.2 is released.
2020.04.01 - Autodesk releases the advisory and assigns CVE-2020-7079.
2020.04.04 - SoundSwitch version 5.0.2 is released.