Thursday, September 17, 2020

Micropatch for Zerologon, the "perfect" Windows vulnerability (CVE-2020-1472)



by Mitja Kolsek, the 0patch Team
The Zerologon vulnerability allows an attacker with network access to a Windows Domain Controller to quickly and reliably take complete control of the Windows domain. As such, it is a perfect vulnerability for any attacker and a nightmare for defenders. It was discovered by Tom Tervoort, a security researcher at Secura and privately reported to Microsoft, which issued a patch for supported Windows versions as part of August 2020 updates and assigned it CVE-2020-1472.

Secura has subsequently released a detailed technical paper and a proof-of-concept tool that anyone could use to test whether their domain controllers were vulnerable or not. The paper revealed the underlying cryptographic flaw in Netlogon remote protocol, a legacy protocol that is still supported on all Windows servers to allow old Windows machines to work in a domain environment. The flaw is described in detail in the above-mentioned paper, but the jist of it is that the attacker has a 1:256 chance that if sending a "challenge" of all zeroes, and all subsequent values in the protocol also containing only zeroes, the request will reset server's password to an empty password. Making a sufficient number of attempts, say 2000 as in the proof-of-concept tool, will succeed with extremely high probability, which we can safely approximate to 100%.

Microsoft's Fix

While most of the security community is interested in the vulnerability and its exploitation, we at 0patch care more about the fix. Critical Windows vulnerabilities are most often of memory corruption flavor, and thus generally easy to fix, but when a cryptographic flaw comes by, there's a possibility that the fix will introduce a lot of new complex code. (Spoiler: not in this case.)

Since Netlogon remote protocol still holds together many production environments with old Windows computers, we knew that Microsoft's fix couldn't include any significant design changes unless it was also ported to long-unsupported Windows versions such as Server 2003, Server 2008 and Windows NT; breaking these systems on a global scale would, with only moderate dramatization, take us back to the dark ages.

Fortunately, Microsoft is highly disciplined when it comes to documentation: the Netlogon remote protocol page shows that the protocol specification was last changed in August 2020 - a good sign for us. Furthermore, they provide a handy "diff" document for every version so it's easy to find changes. The August 2020 diff document contains the following relevant changes:

  1. Page 102: A new setting VulnerableChannelAllowList was introduced: "A setting expressed in Security Descriptor Definition Language (SDDL) ([MS-DTYP] section 2.5.1) of Netlogon client allowed to not use secure bindings, see section (VulnerableChannelAllowList is not supported in Windows NT, Windows 2000, Windows Server 2003, and Windows Server 2008.)"

  2. Page 104: A step was added to the session-key negotiation process: "If none of the first 5 bytes of the client challenge is unique, the server MUST fail session-key negotiation without further processing of the following steps. (Windows NT, Windows 2000, Windows Server 2003, and Windows Server 2008 allow the call to succeed.)"

  3. Page 110: Two steps were added to the session-key establishment process: "4. If secure bind is not used, the server MUST deny the request unless client is in the VulnerableChannelAllowList setting. (Windows NT 4.0, Windows 2000, Windows Server 2003, and Windows Server 2008 allow the call to succeed.)" and "6. If none of the first 5 bytes of the ClientStoredCredential computation result (step 1, section is unique, the server MUST fail session-key negotiation without further processing of the following steps. (Windows NT, Windows 2000, Windows Server 2003, and Windows Server 2008 allow the call to succeed. )"


The relevant change for Zerologon is obviously this: "If none of the first 5 bytes of the client challenge is unique, the server MUST fail session-key negotiation without further processing of the following steps." However, what exactly does "if none of the first 5 bytes of the client challenge is unique" mean? The reader is challenged to make a mental image of what this phrase means, as anyone implementing the protocol would have to - and then read on to see how that mental image compares to Microsoft's code.

Diffing of netlogon.dll between July 2020 and August 2020 versions on Windows Server 2012 shows that function NetrServerAuthenticate3 was extended with a call to a previously non-existent function NlIsChallengeCredentialPairVulnerable and a subsequent branch to terminate the protocol in case the latter returns a non-zero value (implying that the challenge-credential pair was vulnerable).


Function NetrServerAuthenticate3 got a new security check in August 2020

Now let's look at the new function, NlIsChallengeCredentialPairVulnerable. The client-provided challenge is stored in a buffer pointed to by rcx. First, some global variable is checked: if it is 1, the function returns 0 ("not vulnerable"). We don't know what this global variable is and we found no write references to it, only three places where it is being read. We suspect it might be an #ifdef'ed global variable that is hard-coded depending on the target Windows version so that even if Microsoft rebuilds netlogon.dll for, e.g., Windows Server 2003, this security check will not work - which would be consistent with the current Netlogon remote protocol specifications.

Then, rcx is checked to be non-null (kind of important, we don't want to cause access violation reading from it), and rdx is also checked to be non-null. We don't know what rdx points to and decided not to go there as rdx's value is not used at all (the register is overwritten with 1 shortly thereafter).

Now to the meat of the function: the first byte of the challenge is stored into r9d, then the next four bytes are compared to it in a loop. If any of these four bytes is different from the first byte, the function returns 0 ("not vulnerable"). Otherwise, it returns 1 ("vulnerable"). This covers the case from the proof-of-concept tool, where the challenge is all zeroes, but it also covers challenges starting with 11111, 22222, 33333, etc., which would also be deemed malicious by this logic. We assume Microsoft asked one of its crypto experts how to fix this and they at least thought it possible (if not outright feasible) that challenges consisting of equal non-zero bytes could also be used for an attack, perhaps a less trivial one. [Update 9/18/2020] If we were any good at reading, we would notice this part in Secura's report: "When an IV consists of only zeroes, there will be one integer 0 ≤ X ≤ 255 for which it holds that a plaintext that starts with n bytes with value X will have a ciphertext that starts with n bytes with value 0. X depends on the encryption key and is randomly distributed." This explains the logic of Microsoft's patch, and all-zero challenge is just the simplest challenge to exploit. 


NlIsChallengeCredentialPairVulnerable checks if the first five challenge bytes are equal.

And why check only the first 5 bytes? We assume it's either because (a) Microsoft calculated that even if a legitimate random challenge could occasionally begin with 5 equal bytes, this would only break approximately 1 in 4 billion requests, or (b) their challenge-generating code in the client makes sure that the first five bytes are not the same (which would only break 1 in 4 billion requests from non-supported Windows computers).

Now, how does this implementation match your mental image of  "if none of the first 5 bytes of the client challenge is unique"? We think something like "if all of the first 5 bytes of the client challenge are identical" would more accurately describe it, and hereby call on Microsoft to reword this sentence in a future version of the protocol.


Our Micropatch

The micropatch we wrote is logically identical to Microsoft's fix. We injected it in function NetrServerAuthenticate3 in roughly the same place where Microsoft added the call to NlIsChallengeCredentialPairVulnerable, but since the latter doesn't exist in old versions of netlogon.dll,  we had to implement its logic in our patch.

The source code of our Zerologon micropatch for Windows Server 2008 R2


The video below shows how 0patch blocks a "Zerologon" attack. The Zerologon test tool is launched against a fully patched Windows Server 2008 R2 without Extended Security Updates (i.e., patched up to January 2020) while 0patch Agent is disabled. As expected, the test tool discovers that the server is vulnerable. After enabling 0patch Agent, which applies an in-memory micropatch for CVE-2020-1472 to lsass.exe without having to reboot the system, the Zerologon test tool no longer succeeds.

This micropatch is immediately available to all 0patch users with a PRO license, and is primarily targeted at Windows Server 2008 R2 users without Extended Security Updates (updated with January 2020 updates!). By the time you're reading this it has already been distributed to all online 0patch Agents with a PRO license and also automatically applied except where Enterprise policies prevented that. If you're not a 0patch user and would like to use this micropatch on your computer(s) along with other micropatches included with a PRO license, create an account in 0patch Central, install 0patch Agent and register it to your account, then purchase a PRO license or contact for a free trial. Note that no computer restart is needed for installing the agent or applying/un-applying any 0patch micropatch.

To learn more about 0patch, please visit our Help Center
We'd like to thank Tom Tervoort from Secura for sharing their analysis and POC, which allowed us to create this micropatch for Windows users without official security updates. We also encourage security researchers to privately share their analyses with us for micropatching and further increase the positive impact of their work.
Most of the analysis was done by our young micropatching experts Blaz Satler and Ziga Sumenjak.

Frequently Asked Questions

Q: Does applying this micropatch require a computer restart?
A: No, both installation of 0patch Agent and application of the patch (to process lsass.exe) are done without restarting the computer, or restarting any process on the computer.

Q: Do we need this micropatch on a server that is not a domain controller?
A: No. Only domain controllers are vulnerable, both according to Microsoft's advisory and our own testing.

Q: How do we know this micropatch actually works on our server?
A: The best way to test is to use a non-destructive test such as the proof-of-concept tool from Secura. You should be able to replicate what is shown in the video above.
Q: Is Windows Server 2008 (non-R2) or Windows Server 2003 (any flavor) or Small Business Server 2008 also affected by this vulnerability?
A: To the best of our knowledge, these servers are not vulnerable to Zerologon.
Q: Does your micropatch work on Small Business Server 2011?
A: We're not specifically testing with SBS2011, but users are telling us that our micropatch applies to this Server 2008 R2-based Windows version. 
Q: We have a Windows Server 2008 R2 but your micropatch doesn't seem to be getting applied as the vulnerability test still succeeds. What is wrong?
A: The most common cause for this problem is the server not fully updated with January 2020 updates.

Q: We have a still-supported Windows server but can't apply the official update for reasons which leaves us vulnerable to Zerologon. Can you help us?
A: Please contact and we'll port the micropatch to your specific version
Q: Is there anything else we need to know?
A: If your organization still has Windows Server 2008 R2 machines, you might also have some Windows 7 systems that aren't getting security patches anymore, so you should know that we're providing critical post-end-of-support security micropatches for both Windows Server 2008 R2 and Windows 7. Here is the list of micropatches we've issued so far as part of this service.