The new decade has brought an almost shocking number of critical-level vulnerabilities so far, but none quite as impactful as CVE-2020-0601, now better known as the, “CryptoAPI Vulnerability.” With the National Security Agency (NSA) passing this intelligence along to Microsoft, a patch was developed and agencies both government and civilian world-wide, rushed to vet and push the update.
A Refresher in Asymmetric Encryption
Responsible for the integrity and overall security of email, web browsing, applications, and domain security, asymmetric encryption is the foundational framework for how technology keeps your data safe. Each user is issued a key pair consisting of a private key that is confidential to them, and then a mathematically associated public key that is available to anyone who has the privilege to request it. In the example of public key infrastructure (PKI) for email, when you send mail, you encrypt it with the receivers public key, and then they can use their private key to decrypt it. For integrity, to sign the email, you use your private key, and then the integrity of that signature is verified by the sender using your public key. Regardless of the use case, private keys must be kept private, and public keys must be available in order to do anything meaningful.
If a private key is compromised, the whole key pair must be regenerated. The attack we will discuss ultimately spoofs a root CA’s private key, and results in compromise of integrity and confidentiality, without the traditional requirement of stealing a root CA’s private key.
Here’s the TL;DR… this CVE is associated with a vulnerability in Crypt32.dll, the library in Windows 10, Windows Server 2016, and Windows Server 2019, responsible for validating X.509 Certificates (the PKI certificates used to validate webpages, code, and libraries). Windows fails to check critical parameters within root certificates, resulting in an attacker’s ability to spoof the private key of a root CA. From there, they can issue derivative leaf certificates which present as valid to the end-user/underlying OS.
Total Loss of Confidentiality, Total Loss of Integrity
What this really means, is that on a vulnerable version of Windows, there is zero certificate integrity. The little lock icon in the top left of a web browser, which normally identifies that we are operating over TLS with a certificate the browser trusts, now means nothing. Arguably, more importantly, an attacker can now pass code-signing checks by spoofing a root CA’s private key, generating a “valid” certificate, and associating it with their malware. This bypasses validation designed to prevent the execution of unsigned code, a common group policy requirement on most domains.
This means that even if I see a lock icon, which should mean that only the intended recipients can comprehend my session, an attacker could still get in between that transaction and perform a MitM attack, and we would be totally ignorant; this is why we have a complete loss of confidentiality. We also have total loss of integrity as a website’s valid certificates could have been signed by either the real certificate authority or an attacker, and we have no way to tell the difference.
Caching Requirement for Vulnerability
In order to attack this vulnerability, we have to have the root certificates cached, but as almost all the root certificates end up in your key-store due to normal web-browsing activity, this isn’t exactly a huge blockade. If we have the root certificates cached, and the public key matches (which it will by the nature of the attack), Crypt32.dll will skip parameter validation on the root certificate. This is ultimately what was patched by Microsoft.
Elliptic Curve Cryptography (ECC), and ECDSA
For context, DSA (an asymmetric encryption algorithm), uses primes in the formula b = gx mod p, and relies on the difficulty of solving for x when b, g, and p are known but p is prime. Using this formula DSA creates a private key of x, and then can derive a public key of b. Crypt32.dll actually uses ECDSA however, which is just a variant. Instead of using mod p in traditional DSA, as you may have been able to guess, ECDSA replaces that prime with a point computed on a published EC standard such as secp251r1.
DSA or even ECDSA can’t do a whole lot on its own though. In order to use this key pair, we need a framework and that’s where X.509 certificates come in. The X.509 standard is what takes the key pair and associates it with a subject.
Root CA’s, Intermediary CA’s and Leaf Certificates…
Typically you won’t see independent keys, however. More often, they are linked together to form a keychain. This chain is established from a root CA, through intermediary CA’s (as many as there are) until you get to the leaf certificate. By this trust relationship, we can tree out into a network of trust relationships, and the web-browser only needs to keep track of the root certificate authorities, of which there are about 180 in the common ones (chrome, IE, etc.). But this also means that the subordinate key relies on the one above it, and trust starts from the root. If you compromise one of the root certs that a browser or (in this example) Crypt32.dll trusts, then you can generate any leaf key you want and it will appear valid.
This idea is also how bitcoin maintains integrity, and ECDSA is actually the algorithm used to maintain the blockchain that Bitcoin uses. Your wallet is just private keys, and ECDSA ensures that only you can spend your money.
For further context please check out this great article: https://blog.trailofbits.com/2020/01/16/exploiting-the-windows-cryptoapi-vulnerability/
Compromising the Certificate Chain
While typically ECDSA uses an established curve, the user is actually able to define one themselves, and in that case it is another parameter that is part of the X.509 certificate file. The attack is therefor fairly straight forward.
We want to spoof a private key that associates itself bit for bit to the same public key as the CAs, so that we “know” the underlying private key. To do this with plain DSA we just set b to the CA’s public key. Then when we set g=p, x always equals 1. When we bring this back to ECDSA we have essentially the same control as ECDSA allows us to specify the parameters for the curve. Crypt32.dll does not validate these parameters in a vulnerable version of Windows, and as such we can do a thing like setting g=p and deriving our own private key that will pair with the public key by calculating the generator coefficient (g).
This idea was initially outlined by Serge Vaudenay in his 2004 paper titled, “Digital Signature Schemes with Domain Parameters.” It wasn’t until recently that Crypt32.dll was reported as vulnerable to this type of attack.
How to Protect Your Organization
Fortunately, upon identification, Microsoft rushed to create a patch for this CVE, and released it out of band first to the U.S. government, and then included it in the broader patch Tuesday bundle released on 14 January 2020. Ultimately, all they had to do was write in some parameter validation, but this is a heavy vulnerability with incredibly wide-ranging implications.
This goes without saying it needs to be said, but patch your systems yesterday!!