Déjà vu
CVE-2020-1350 is an integer overflow vulnerability in the SigWireRead() parser function of the DNS service in Windows Server OS, resulting in heap-based buffer overflow. Integer overflow leads to allocation of memory of incorrect size to uncompress signature data while parsing Signature Resource Record (Sig RR), which enables DNS Security Extension (DNSSEC). If successfully exploited, CVE-2020-1350 can lead to remote code execution (RCE) attacks on the Windows Server OS. It affects Microsoft’s implementation of DNS servers running on Windows Server 2008 and later versions. Microsoft tagged the CVE-2020-1350 as wormable and has been rated as a CRITICAL SEVERITY vulnerability. Other DNS servers are not impacted by this vulnerability.
This is yet another vulnerability in Windows service compression/decompression function, similar to SMBGhost (CVE-2020-0796) which was reported and patched in March 2020, in Windows SMB implementation.
Working of DNS
When we request a webpage, the DNS client requests the DNS resolver which performs multiple lookups (recursive and iterative) to provide the IP address of that web server. Here’s what happens behind the scenes:
- Cloudlfare.com is accessed in the browser
- DNS client asks the DNS resolver for the IP address (in this case, your DNS server)
- The request is then forwarded to the DNS Root Nameserver
- The resolver then calls the .com Top Level Domain (TLD) Nameserver for the domain’s Nameserver record
- Lastly, a request is sent to the domain’s Nameserver for the IP address
For a subdomain or any other record pertaining to that domain, the domain’s Nameserver will be an Authoritative Nameserver.
Note that the above image explains only one scenario. There are numerous scenarios in which some of the steps may be skipped or repeated. More information about DNS resolving is available here.
Vulnerability
Signature Resource Record (SIG RR) is a security extension to DNS (DNSSEC), enabling authentication of various DNS record types using Public Key Infrastructure (PKI). The integrity of the RDATA portion of SIG RR is protected by the signature field. Figure 2 shows different fields of the SIG RR record for a locally configured DNS server on Windows Server 2012 when queried from Windows Powershell.
The vulnerability lies in the SigWireRead() parser function in DNS.exe, which processes compressed DNS data present in SIG RR via TCP.
Before we get into the details of the vulnerability, let’s see the attack scenarios for this vulnerability. There are two attack scenarios that were observed in the SigWireRead() function:
- Query DNS server directly with the compressed DNS data along with SIG record
- Query a domain that DNS forwards the query to and receives the compressed DNS data from the malicious Nameserver
Attack Scenario 1
This is a straightforward attack where the DNS server accepts dynamic updates and is directly accessible to the attacker for querying (case of publicly available Windows DNS servers). Attacker sends a DNS query with malicious SIG RR for dynamic update.
Attack Scenario 2
This is the case in corporate environments, where DNS servers are available for most of the internal networks. Here are the steps for the second attack scenario:
- Victim is tricked to click on a malicious URL whose Authoritative Nameserver is controlled by the attacker
- DNS query is then sent to the Windows DNS server
- Windows DNS server looks up in the cache and forwards the request to the public DNS server for lookup
- Public DNS server responds with the Nameserver of the domain
- Windows DNS server caches the malicious Nameserver for future use
- Victim requests for SIG record for the same domain
- Malicious Nameserver responds with a malicious SIG resource record
- While allocating the memory for the parsed compressed data, overflow occurs resulting in DoS or RCE
In this blog, we’ll discuss the first attack scenario. By passing a huge SIG RR in a DNS query, we crash the DNS service exploiting DNS.exe’s SIG parser in Windows Server. Let’s look at the parsing code at dns!SigWireRead().
When the parser receives the SIG RR, it parses them and allocates memory by computing the required memory size using certain fields from the packet. The first word in the DNS query mentioned in Figure 5 shows the length i.e. 2 bytes which can accommodate a maximum of 64KB. Note that this is only for DNS over TCP.
Figure 5 shows the maliciously crafted SIG RR, sent to our local DNS server. Let’s try to understand the packet. To reduce repetition and the data size, DNS uses message compression technique, using compression pointers. A compression pointer takes the two octets that start with the first two higher-order bits set to 1 as shown in Figure 6. The value in hex for the first octet in our case is C0. The 6 LSB and the next octet will be used as an offset to the original location of data from the start of the packet.
In Figure 5, the bytes 0xC0 0x0C, is a compression pointer to the domain name example.com, which is at offset 0x0C from the header. Similarly, for signer’s name, the compression pointer is 0xC0 0x29, which is a series of ‘A’ followed by the domain ‘example.com’.
The parser computes allocation size as
effective_name_length + 0x14 + signature field’s length
to allocate the memory for the parsed SIG record (signer’s name and signature). Thus, when the huge data is sent in the signature field like in the above case, it makes the computed size more than 0xFFFF, which is more than what a 16bit register can store, resulting in an integer overflow. As a result of this overflow, the system allocates a heap of a much lesser memory size than what is actually required.
Figure 8 below, shows values of registers CX [1] and DI [2] before and after execution of add instruction [3] and call stack. Since CX and DI are 16bit registers, addition operation results in an overflow resetting values of CX register and CF flag. In this case, MSB of the result, one, is stored in CF [5] and CX register is reset to all zeros [4].
So, when the parsed signature record is copied into the recently allocated buffer memory, it overwrites the buffer resulting in an out-of-bounds (OOB) write.
Here, register RDI is the signature field’s length, register RBP is the signature record and register RSI is the allocated buffer.
Figure 10 below shows the call stack and arguments passed when memcpy() function is called which results in the crashing of the DNS service as a result of OOB write. The signature that we observed in Figure 5, has been passed as a parameter directly to the memcpy() function, which then overwrites the buffer.
When successfully exploited, the DNS service crashes or results in a RCE attack.
Patch Diffing
Microsoft has patched the function with multiple overflow checks. For reference, we used an old DNS server executable from Windows Server 2012, as this function has not been touched for years. The versions of files that we analyzed are :
- Vulnerable file: 6.3.9600.16384 (Primary)
- Patched file: 6.3.9600.19759 (Secondary)
Although the difference between these patches is not big, the difference between their builds is huge (almost 7 years).
Let’s analyze the new code blocks in the patched version (Figure 11). Microsoft has added a few checks before allocating the memory, i.e. before the call to RR_AllocateEx() is made. The three code blocks have checks as mentioned below (Figure 12):
- Check if Signature field is less than 0xFFFF (basic bounds check)
- Check if effective_name_length + 0x14 is less than 0x12 (bounds check )
- Check if total computed size is less than signature field’s length
Only if all these checks are passed, the buffer is safely allocated for processing the signature.
Mitigation
The patch has been made available for this vulnerability in July 2020 Microsoft patch release. Update your Windows Server by installing the security patch.
If you are unable to install the updates for any reason, you can follow the workaround by creating a registry entry as shown below:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters
DWORD = TcpReceivePacketSize
Value = 0xFF00
This registry entry blocks your DNS TCP traffic size that goes above 0xFF00 which is way higher than usual DNS packet size.
Recommendations
- Disable dynamic updates in your DNS server if not required
- Do not expose your DNS server via public IP address unless required
- Turn on your firewall at all times
- Avoid using the administrator account as the main account on critical machines
- Ensure your systems are up-to-date for OS patches and allow updates to install by default
- Use a reputed security product like K7 Endpoint Security and K7 Total Security to stay protected from the latest threats
K7 Antivirus actively detects and prevents attempts to exploit CVE-2020-1350 vulnerability under IDS (Rule:intrusion attack – ID:000200E9, ID:000200EA)