By: Jan Schnellbächer and Martin Stecher, McAfee Germany GmbH
This week security researches around the world were very busy working on Microsoft’s major crypto-spoofing vulnerability (CVE-2020-0601) otherwise known as Curveball. The majority of research went into attacks with malicious binaries that are signed with a spoofed Certificate Authority (CA) which unpatched Win10 systems would in turn trust. The other attack vector —HTTPS-Server-Certificates— got less attention until Saleem Rashid posted a first working POC on Twitter, followed by Kudelski Security and “Ollypwn” who published more details on how the Proof-Of-Concepts are created.
McAfee Security experts followed the same approach and were able to reproduce the attack. In addition, they confirmed that users browsing via unpatched Windows-Systems were protected provided their clients were deployed behind McAfee’s Web Gateway or Web Gateway Cloud Service and running the certificate verification policy. This is typically part of the SSL Scanner but is also available as a separate policy even if no SSL inspection should be done (see KB92322 for details).
In our first attempt, we used the spoofed version of a CA from the Windows Root CA Trust store to sign a server certificate and then only provided the server certificate when the HTTPS connection wanted to be established. That attempt failed and we assumed that we did not get the spoofing right. Then we learned that the spoofed CA actually needs to be included together with the server certificate and that chain of certificates is then accepted by an unpatched Windows 10 system.
But why is that? By sending the spoofed version, it becomes obvious that this is not the same certificate that exists in the trust store and should be denied immediately. Also, in the beginning, we tried hard to make the spoofed CA as similar to the original CA as possible (same common name, same serial number, etc.). In fact, we found that none of that plays any role when Windows does the certificate verification.
A good indication of what’s happening behind the scenes, is already provided by Windows’ own certificate information dialogs. We started with the “UserTrust ECC Certificate” in the Windows Trusted Root CA catalog which carries the friendly name “Sectigo ECC”. Then we created a spoofed version of that CA and gave it a new common name “EVIL CA”. With that, it was easy to set up a new test HTTPS server in our test network and manipulate the routing of a test client so that it would reach our server when the user types https://www.google.com into the browser. The test server was presenting SSL session information for debugging purposes instead of any Google content.
When you click onto the lock symbol, the browser tells you that the connection has been accepted as valid and trusted and that the original “Sectigo ECC” root CA had signed the server certificate.
But we know that this was not the case, and in contrast to our own original assumptions, Windows did not even verify the server certificate against the “Sectigo ECC. It compared it against the included spoofed CA. That can be seen, when you do another click to “View certificates”:
As the screenshot shows, we are still in the same SSL session (the master key is the same on both pictures), but now Windows is showing that the (correct) issuer of the server certificate is our spoofed “EVIL CA”.
Windows’ cryptographic signature verification works correctly
The good news is that Windows does not really have an issue with the cryptographic functions to validate the signature of an elliptic curve certificate! That verification works correctly. The problem is how the trust chain comparison is done to prove that the chain of signatures is correctly ending in the catalog of trusted root CAs.
We assumed that an attack would use a signing CA that points to an entry in the trusted Root CA store and verification of the signature would be limited so that the signature would be accepted although it was not signed with that original CA but a spoofed CA. But in fact, Windows is validating the embedded certificate chain — which is perfectly valid and cryptographically correct— and then matches the signing certificate with the entries in the trusted Root CA store. This last piece is what has not been done correctly (prior to the system patch).
Our tests revealed that Windows does not even try to match the certificates. It only matches the public key of the certificates (and a few more comparisons and checks) – making the comparison incomplete. That was the actual bug of this vulnerability (at least as web site certificates are concerned).
The Trusted Certificate Store is actually a Trusted Public Key Store
When we talk about the trust chain in SSL/TLS communication, we mean a chain of certificates that are signed by a CA until we reach a trusted Root CA. But Microsoft appears to ignore the certificates for the most part and manages a chain of the public keys of certificates. The comparison is also comparing the algorithm. At a time where only RSA certificates were used, that was sufficient. It was not possible for an attacker to create his own key pair with the same public key as the trusted certificate. With the introduction of Elliptic Curve Cryptography (ECC), Microsoft’s comparison of only the algorithm and the public key is failing. It is failing to also compare the characteristics of the elliptic curve itself. Without this additional parameter, it simply creates the same public key (curve point) again on a different curve. This is what was fixed on Patch-Tuesday — the comparison of the public key information now includes the curve characteristics.
This screenshot shows that the original certificate on the right side and the spoofed CA on the left are very different. Different common name, and a totally different elliptic curve (a standard curve for the original CA and a handcrafted for the spoofed version), but the signature seen under the “pub” entry is identical. That has been sufficient to make Windows believe that the embedded spoofed CA was the same as the trusted CA in the certificate store.
Why not comparing certificates by name or serial number?
A different (and maybe more natural) algorithm is to compare certificates by their common name and/or their serial number and whenever you have a match, continue the trust chain and verification with the certificate in the trust store. Why is Windows comparing public keys instead? We can only speculate but the advantage might be for Enterprises who want to swap their certificates without rolling out new root CAs to all client computers. Imagine an organization that maintains its own PKI and installs its own Root CA in the store of trusted certificates. When these companies go through mergers and acquisitions and the company name may change. This would be a good time to also change the common name of your signing certificate. However, if you do not have a good way to remote maintain all clients and update the certificate in the trusted store, it is easier to tell the Cooperation to use the original key pair of public and private keys and create a new certificate with that same key pair. The new cert will still match the old cert and no other client update is necessary. Convenient! But Is it secure? At this point it is not really a chain of trusted certificates but a chain of trusted public keys.
We tested whether this could also be mis-used to create a new cert when the old one has expired but that is not the case. After comparing the public keys, Windows is still using the expiration date of the certificate in the trusted store to determine whether the chain is still valid, which is good.
How to harden the process?
The root problem of this approach is that the complete cryptographic verification happens with the embedded certificates and only after verification the match against the entry in the trusted Root CAs store is done. That always has room for oversights and incomplete matching algorithms as we have seen with this vulnerability. A safe approach is to first match the certificates (or public keys), find the corresponding entry in the Trusted Root CA store and then use that trusted certificate to continue the signature verification. That way, the verification fails on the safe side and broken chains can be identified easily.
We do not know whether that has been changed with the patched Windows version or if only the matching algorithm has been improved. If not, we recommend reviewing this alternative approach and further hardening the implementation in the operating system and browser.