In the Patch Tuesday for August 2011, Microsoft released Security Bulletin MS11-058 (CVE-2011-1966) to fix a unauthenticated remote code execution vulnerability in DNS servers. According to the security advisory, a remote code execution vulnerability exists because the Windows DNS Server improperly handles a specially crafted NAPTR query string in memory. An attacker who successfully exploited this vulnerability could run arbitrary code in the context of the system.
We reverse engineered the patch to get a better understanding of the mechanism of the vulnerability and found this vulnerability can be triggered with a few easy steps. While the proof of concept described below demonstrates a denial of service, attackers with malicious intent may be able to get reliable code execution.
QualysGuard detects this vulnerability with QID: 90726 - Microsoft Windows DNS Server Remote Code Execution Vulnerability (MS11-058). Because of the possibility of a code execution attack, Qualys recommends all our customers to scan their environment for QID 90726 and apply this security update as soon as possible.
Unpatched File: dns.exe (version: 6.0.6002.18005)
Patched File: dns.exe (version: 6.0.6002.18486)
- We start the analysis by binary-diffing the unpatched and the patched version of the files that were made available by the MS11-058 security update. This helps us understand the changes that were made in order to fix the vulnerabilities by this patch. To perform binary diffing we use TurboDiff, which is a plugin for IDA pro. TurboDiff shows us a list of all the functions that are identical, changed, unmatched and those that look suspicious. Suspicious functions have unchanged function graphs but changed checksums, which indicates a small code change was made. While most of the functions look identical, TurboDiff lists some of these functions as suspicious (Fig. 1).
Figure 1: Diffing results by TurboDiff.
- As seen in figure 1, TurboDiff lists four of these functions as suspicious. The vulnerability we are investigating is related to CVE-2011-1966, which is related to Name Authority Pointer (NAPTR) DNS resource record. From the names of the four functions marked as suspicious, it is pretty clear the ‘NaptrWireRead(x,x,x,x)’ has something to do with the NAPTR DNS record and this should be the first function to analyze further.
- Taking a closer look at the diffing results for the function NaptrWireRead(x,x,x,x) reveals there is only one change made to the entire function (Figure 2, indicated with green box).
- The signed extended instruction “movsx edi, byte ptr[ebx]” is replaced with zero extended instruction “movzx edi, byte ptr[ebx]”. This value is then further used as the number of bytes to copy from the source buffer to the destination buffer for memcpy().
- The signed extended move instruction is a trouble maker here. If the byte pointed by “byte ptr[ebx]” is greater than 127(0x7F), the resulting value in the edi register will be a very large number. For example if byte pointed by [ebx] is 128, the resulting value in register edi will be 0xFFFFFF80. The next instruction “LEA EAX, DWORD PTR DS:[EDI+1]” will load EAX with 0XFFFFFF81 which is used as a count for memcpy(). This example will try to copy the entire 4Gb of memory, leading the DNS service to crash.
Figure 2: Binary Diff for function NaptrWireRead(x,x,x,x).
- For the proof of concept, you need two DNS servers. Register the domain crasher.test.com on the first server and configure a NAPTR DNS record as shown in figure 3 below. The second DNS server will act as a forwarder DNS server. Of all the fields shown, the “Service String” and “Regular Expression” fields are the ones that can take input greater than 127 characters with no restrictions.
- To exploit this vulnerability we make any of the above mentioned fields have more than 128 characters. In this case we set the "regular expression" field to 128 characters.
- From the forwarder DNS, type the command “nslookup -type=all crasher.test.com. 127.0.0.1”. This command will crash the DNS server working as the forwarder.
Figure 3: DNS NAPTR form.
- To see the vulnerability in action, attach your debugger to the DNS executable and set a break point at the NaptrWireRead(x,x,x,x) function and also set a breakpoint at the memcpy() function in that function.
Figure 4: BreakPoint at memcpy() in NaptrWireRead().
- From Figure 4 (see the values passed on the stack when calling memcpy()), it is clear that setting the value greater than 128 has caused the count parameter for memcpy function to be a really large value causing an access violation and crashing the DNS server.
- The call Stack Trace for the above vulnerability can be seen in Figure 5 below.
Figure 5: Call Stack Trace.
- To analyse the crash via windbg, you can start Windbg with the command “windbg -I” an register it as a default postmortem debugger. When you run the “nslookup -type=all crasher.test.com. 127.0.0.1” again, the DNS server crashes and windbg starts for analysis. Figure 6 shows the output of the !exploitable crasher analyzer.
Figure 6: !exploitable plugin output.
As shown in the analysis above, this vulnerability can be triggered with a few easy steps. While this PoC demonstrates a denial of service, attackers with malicious intent may be able to get reliable code execution. Hence we recommend all our customers to scan their environment for QID 90726 and apply this security update as soon as possible.