On October’s Patch Tuesday 2011, Microsoft released Security Bulletin MS11-082 to fix “Access of Unallocated Memory DoS Vulnerability” within Microsoft Host Integration Server. According to the security advisory, a remote, anonymous attacker who exploited this vulnerability could cause the affected system's SNA Server service to stop responding to new requests. This is caused because the snabase.exe crashes and also kills snarpcsv.exe and mngagent.exe due to the dependencies between them.
To get a better understanding of the cause of this vulnerability, we have reverse engineered the affected server and found the condition that triggers the DoS. This article also has a short Python PoC which uses CVE-2011-2008.
1. Vulnerability Analysis and exploit conditions
The Host Integration server snabase.exe listens on UDP port 1478 or TCP ports 1477 and 1478. Figure 1 shows the code path that it takes when a UDP packet is received and EAX points to the received packet. At location 01029B73, the server moves the third byte (EAX+2) to ECX and then compares it with different values. If the value is greater than 5 the code jumps to 01029EAC. If the value is equal to 5 it jumps to 01029E77. The value can now only be in range 1-4 at 01029B90. Next it decrements the value by 1, step by step, to check if it is 1 , 2, 3 or 4. This is a typical switch statement which compares the value and calls different handlers. The compiler replaces the switch statement with the sub/dec instructions to optimize the program execution.
For a successful exploit there are two conditions that need to be satisfied. The first condition is that the third byte is 0x1. The execution will then goto 01029C42 and then 0101F99D.
The 4th and 5th bytes of the packet contain the “entries” in this message. The server reads the values and then checks these entries one by one in a loop. But if the server was told that there are more than 0x4B entries then the server will try to access memory locations that are not allocated resulting in the process getting terminated. This is the second condition that should be satisfied for a successful exploit. The number of entries must be greater than 0x4b.
For the PoC both the conditions as stated above need to satisfied which just takes 5 bytes. What we need is to set the 3rd byte to 0x1 and then set 4th and 5th byte greater than 0X4B. The first and second byte does not affect our exploit, so any value will work. The Python script should like this:
import socket, sys
from struct import pack
target = sys.argv
port = int(sys.argv)
request = "\x00\x00\x01\x4C\x00"
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print "[+] Sending request"
s.sendto(request, (target, port))
print "[X] Unable to connect to %s" % target
3. How does the Patch Fix this issue?
By using binary diff tool we can see that the patch added a new verify function at 67481133:
The function takes the length and address of the UDP package as parameters.
The packet will be considered as invalid unless the function 67480AE6 returns 0 (return value is stored in EAX). This function first checks the length of the UDP packet. It return error(EAX not 0) if the length is less than 3. Then there is another switch statement on the third byte of the packet.
If the third byte is 0x1 the function jumps to 67480B3F. The value at dwEnableTraces is always 0x6. This means that the patch will drop all packets whose third byte is 0x1. My guess is that this is a temporary fix from Microsoft. EAX will set to 0 at 67480B46 and jump to 67480BE4. At 67480B46 the program will increase EAX by 1 before return and in this way sanitize the input before calling the function that crashed earlier.
The Host Integration Server will crash when a remote attacker sends 5 bytes of malicious UDP packet. There are also other vulnerabilities fixed by MS11-082 which are not analyzed in this article. We recommend customers to scan their environment for QID 90748 and apply this security update as soon as possible.