One of the interesting things about security research, and I guess research in general, is that all too often the only research that is publicized is research that proves something or shows something especially amazing. Research that is incomplete, where the original hypothesis or idea ends up being incorrect, or that ends up at non-spectacular conclusions rarely ends up getting published. I feel that this trend is doing a disservice to the research community because the paths that the authors of this unpublished research took remain unknown to like-minded individuals, perhaps resulting in duplicate efforts in the future. Furthermore, much like with life, its not the destination that matters but rather the journey itself -- the methodologies used in this unpublished research may help unlock other areas of interest. With this thinking in mind, I am publishing this little bit of research I've done on and off over the past month or so.
As part of Rapid7's Project Sonar, we routinely scan the entire public IPv4 Internet (minus any hosts that we've been asked to exclude -- we are nice like that) looking for data that indicates something interesting from a security perspective. As anyone who has done large scale scanning like this will likely attest to, you see the strangest of things. It all started when we were analyzing what seemed to be empty UDP messages (a UDP datagram with no data) in response to some of our UDP probes. As it turns out, it was just another instance of the "etherleak" bug I reported back in 2002 that ultimately became CVE-2003-0001. But my curiosity was piqued and I wondered if there were any circumstances where a UDP service would reply to a UDP message that contained no data.
What follows is my research in using empty UDP messages as probes to elicit responses from UDP services.
Background: UDP Scanning
Any sort of UDP scanning, even when not done at an Internet-wide scale, is tricky. When looking for open UDP ports and trying to identify the protocol spoken on an open port, reactions to your probes will fall into one of three categories -- no response at all, no response from the service but a response by the IP stack of the target indicating that your connection failed for one reason or another, or, if you are lucky, you get some sort of response directly from the service.
If you get no response, this could mean one of:
- The port is not open
- The service was too busy to respond
- Your probe was incorrect for whatever reason (for example, you sent a non-NTP message to an NTP service)
If you get a response from the IP stack of the target in the form of an ICMP message, this could mean one of:
- The port is not open and the stack is configured to send ICMP port unreachable messages
- The port may be open but your connection was denied by ACLs or similar
To further complicate things for the above mentioned scenario, many systems are configured to rate limit the number of ICMP responses sent in an effort to prevent scanning abuse as well as mitigate DDoS attacks and their stealthier, harder-hitting cousin, DRDoS attacks. So, while ICMPs are useful in identifying closed ports, because they are often rate limited this means a scanner must properly rate limit the UDP probes in order to not trigger more ICMP messages (again, indicating closed ports).
If you do get a response from the service, you can be certain that the port is open but you cannot yet be sure what protocol the service listening on that port speaks. To do that, you must analyze the response with knowledge of the probe you sent.
Empty UDP Scanning
As previously alluded to and likely obvious by now, empty UDP scanning is simply sending a UDP datagram with no data to a particular UDP port. More specifically, the length field at layer 4 is 8 and there is no data after the 8 bytes representing UDP. Assuming the port in question really is open, you will get a response for one of several reasons:
- The protocol implemented by the service is truly verbose or promiscuous, meaning the data of the request is irrelevant and ignored by the service and a reply is sent regardless
- The protocol implementation is designed to respond with some sort of message specified by the protocol, for example an error message when the format of the request was wrong
Both of these conditions are a little interesting from a security perspective. Port scanners and tools used to identify services/protocols can send empty UDP datagrams as a fall-back way to both discover open UDP ports and identify the protocol implemented by the service. Nmap, among others, has been using this technique for years.
On September 19th, 2014, I released a very simple Metasploit auxiliary module, empty_udp, that I wrote to help better understand how systems would respond. What follows are the results of my findings from scanning our 1000-odd system lab that is filled with all manner of interesting targets. While our lab is absolutely not representative of the what we'd encounter on the wild Internet, what I found was sufficient to satisfy me for now. I had and still am considering running a much more focused version of this as part of Sonar, so if you are reading this and can think of reasons (and ports) to do an Internet-wide audit, let me know in the comments. My biggest hesitation is that empty UDP packets have been the cause of DoS conditions in several protocols/services over the years and I am trying to play nice.
Microsoft Windows RPC
When IANA assigns TCP and UDP ports to a particular service, more often than not the service in question is allocated both the TCP and UDP ports regardless of whether or not it currently uses both. For example, DNS, which typically uses port 53, legitimately uses both TCP and UDP, but SSH, which typically uses port 22, is assigned both TCP and UDP ports but never uses UDP to the best of my knowledge.
Port 135 is assigned to the Microsoft Windows DCE-RPC endpoint mapper and clients wishing to communicate with DCE-RPC services on a Windows host must communicate with the endpoint mapper to figure out which other, generally high, ephemeral port the desired RPC service is listening on. In all my years, I have never seen a legitimate Windows system listening on and responding to UDP port 135, hence my surprise when I saw several Windows systems in our lab responding to empty UDP probes to UDP port 135.
While I can't reproduce this on a regular basis, what I saw was that Windows systems that were still vulnerable to MS03-026 were occasionally responding to the empty UDP packets with endpoint mapper responses seemingly constructed entirely from uninitialized memory, leading to a minor and nearly un-exploitable information disclosure. This makes me wonder if, as part of the patch for MS03-026, Microsoft changed the endpoint mapper to not listen on and/or respond to UDP port 135. This idea is backed up by MS03-039, which Microsoft claims supersedes MS03-026, where it states that a suitable workaround for MS03-039 includes blocking a pile of TCP and UDP ports specific to various Windows services, including TCP 135 but it does not mention UDP port 135. This has interesting implications -- were there other vulnerabilities or methods of exploitation lurking in the UDP endpoint mapper that nobody discovered or disclosed? Could there have been a lethal one-shot UDP exploit that could have used spoofed source IPs and devastated all hosts un-patched against MS03-026?
Old UNIX/BSD Services
I cut my security teeth, so to speak, on all manner of UNIX/BSD systems, but I still jump a bit when I encounter some of the largely useless services like quote of the day (quotd, port 17), character generator (chargen, port 19), good 'ole time of day (port 13), time (port 37) and the thing that came before DNS, named (port 42). It is equivalent to me, a Bostonian living in Los Angeles, visiting the Mid-west or quaint towns and finding doors are left unlocked, complete strangers waving at you from across the street and people greeting you warmly wherever you go -- you know places like that exist but you are still a bit startled when it happens to you.
So, while scanning, don't forget about these services. Hit both the TCP and UDP ports and try the empty UDP trick -- you might discover things you wouldn't otherwise find.
In certain configurations, ISAKMP implementations will respond to empty UDP messages with an ISAKMP notification message indicating that the message length in the ISAKMP header does not match the sum of the actual payload lengths. This UNEQUAL-PAYLOAD-LENGTHS message is optional, so it may be possible to fingerprint different ISAKMP implementations using this knowledge.
I like to pick on NAT-PMP. My Apple Airport Express runs it so it gets my attention from time to time. In the case of using empty UDP messages as a probe for NAT-PMP, the situation is interesting. The smallest, valid request that a NAT-PMP implementation should respond to is the 4-byte external address request, which must consist of 4 null bytes. It shouldn't come as too much of a surprise that at least some implementations will respond to shorter responses that only include the first 2-bytes, the version. In this case, if the version does not match (it isn't version 0), the service may send back a response with a result code of 1 indicating that the version is unsupported. But, in at least the case of Apple's Airport Express, an empty UDP message also results in a result code of 1, which makes you wonder what version the service thought the message was speaking when there was no data to interpret.
If you've ever had to scan for and/or exploit TFTP vulnerabilities or misconfigurations, you'll know the pain I am about to describe. TFTP, which generally runs on UDP port 69, is the worst-case scenario. In addition to being UDP and therefore problematic to scan for (as mentioned earlier), typically port 69 is used as the command port and any data is sent from a different port. It gets worse -- lets say you want to retrieve a file off of a TFTP server. You'd send the request from some high, ephemeral port (say, 12345) to the TFTP server's UDP port 69, and assuming all was well, it would respond with the contents of the file from a different port entirely but send it to the source port that initiated the original request on UDP 69, in this case 12345. This means you have to be careful while trying to scan for TFTP -- you can't just assume that any and all responses will come from port 69. Interestingly, some implementations will reply on UDP 69 with messages like "Packet only has 0 bytes" or "Access violation", in particular at least the TFTP server used by ManageEngine products. Others, like VMware Studio and some unknown TFTP implementations available for Linux, reply from a high, ephemeral port saying "Missing mode".
Beyond the findings for Windows DCE-RPC endpoint mapper and MS03-026, all of this has only very, very minor security implications, but it was a fun exercise, I (re)learned some things, saw some unexpected results, and perhaps this knowledge will come in handy for someone in the future. If you know of other useful information related to empty UDP scanning or anything posted here, let me know in the comments.