Headline
CVE-2017-2909: TALOS-2017-0416 || Cisco Talos Intelligence Group
An infinite loop programming error exists in the DNS server functionality of Cesanta Mongoose 6.8 library. A specially crafted DNS request can cause an infinite loop resulting in high CPU usage and Denial Of Service. An attacker can send a packet over the network to trigger this vulnerability.
Summary
An infinite loop programming error exists in the DNS server functionality of Cesanta Mongoose 6.8 library. A specially crafted DNS request can cause an infinite loop resulting in high CPU usage and Denial Of Service. An attacker can send a packet over network to trigger this vulnerability.
Tested Versions
Cesanta Mongoose 6.8
Product URLs
https://cesanta.com/
CVSSv3 Score
7.5 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CWE
CWE-835: Loop with Unreachable Exit Condition (‘Infinite Loop’)
Details
Mongoose is a monolithic library implementing a number of networking protocols, including HTTP, MQTT, DNS and others. It is designed with embedded devices in mind and as such is used in many IoT devices and runs on virtually all platforms.
In a DNS request packet, a name can be compressed to save space. The compression in question relies on pointers to parts of the domain name already present in the packet. When decompressing the names, the DNS server software must look up those pointers and substitute them accordingly.
In the Mongoose library, the function mg_dns_uncompress_name is responsible for decompressing names and a special case for pointers is handled:
while ((chunk_len = *data++)) { [3]
int leeway = dst_len - (dst - old_dst);
if (data >= end)
return 0;
if (chunk_len & 0xc0) { [1]
uint16_t off = (data[-1] & (~0xc0)) << 8 | data[0];
if (off >= msg->pkt.len) {
return 0;
data = (unsigned char *) msg->pkt.p + off; [2]
continue;
The name chunk pointer is encoded in a single byte having 2 most significant bits set (0xc0) and rest are an offset to the actual name. In the above code, at [1], a check is performed to see if the current chunk is actually a pointer, and if so, the offset is extracted instead. At [2], this offset is used to advance the parser by adding it to start of the packet. The loop then continues at [3].
In the above code, no check is performed to see if the calculated offset refers to the same position, or if the pointer points to another pointer. No valid DNS query should have a pointer pointing to another pointer and precisely that kind packet will cause an infinite loop in the above code. An example packet:
00000000: 0020 a577 0120 0001 0000 0000 0001 c00c . .w. ..........
00000010: 0000 0000 0100 0100 0029 1000 0000 0000 .........)......
00000020: 0000 0a …
At offset 14 above, we have a start of name chunk, which specifies a pointer (0xc0), followed by 0x0c which represents it’s offset from the start of the packet, past the 2 ID bytes. When parsing this packet, function mg_dns_uncompress_name will enter an infinite loop, because the first chunk points to itself.
This causes 100% CPU usage and Denial Of Service.
Timeline
2017-08-30 - Vendor Disclosure
2017-10-31 - Public Release
Discovered by Aleksandar Nikolic of Cisco Talos.