libspf2-parsing.txt
Posted on 23 October 2008
Advisory: DNS TXT Record Parsing Bug in LibSPF2 Author: Dan Kaminsky, Director of Penetration Testing, IOActive Inc, Dan.Kaminsky@ioactive.com (PGP Key In Appendix) Abstract: A relatively common bug parsing TXT records delivered over DNS, dating at least back to 2002 in Sendmail 8.2.0 and almost certainly much earlier, has been found in LibSPF2, a library frequently used to retrieve SPF (Sender Policy Framework) records and apply policy according to those records. This implementation flaw allows for relatively flexible memory corruption, and should thus be treated as a path to anonymous remote code execution. Of particular note is that the remote code execution would occur on servers specifically designed to receive E-Mail from the Internet, and that these systems may in fact be high volume mail exchangers. This creates privacy implications. It is also the case that a corrupted email server is a useful “jumping off” point for attackers to corrupt desktop machines, since attachments can be corrupted with malware while the containing message stays intact. So there are internal security implications as well, above and beyond corruption of the mail server on the DMZ. Recommendations: If you are a major mail exchange, you should determine whether the SPAM filters that protect your systems use LibSPF2. If you are a vendor of anti-SPAM devices, or the author of an operating system with components that may use LibSPF2, you should determine whether LibSPF2 is used in any of your configurations and migrate to LibSPF 1.2.8, found at: http://www.libspf2.org/index.html If your product has a dependency on DNS TXT records, we recommend you test it for the parsing bug that LibSPF2 was vulnerable to, since this has been a problem for some time. Name server implementations may want to consider adding filtering themselves, though record validation is not normally their job. Details: DNS TXT records have long been a little tricky to parse, due to them containing two length fields. First, there is the length field of the record as a whole. Then, there is a sublength field, from 0 to 255, that describes the length of a particular character string inside the larger record. There is nothing that links the two values, and DNS servers to not themselves enforce sanity checks here. As such, there is always a risk that when receiving a DNS TXT record, the outer record length will be the amount allocated, but the inner length will be copied. In the past, we’ve seen this particular bug all over the place, including in Sendmail. This is just the same bug, showing up in LibSPF2 1.2.5: Spf_dns_resolv.c#SPF_dns_resolv_lookup(): case ns_t_txt: if ( rdlen > 1 ) { u_char *src, *dst; size_t len; if ( SPF_dns_rr_buf_realloc( spfrr, cnt, rdlen ) != SPF_E_SUCCESS ) // allocate rdlen bytes at spf->rr[cn]->txt return spfrr; dst = spfrr->rr[cnt]->txt; len = 0; src = (u_char *)rdata; while ( rdlen > 0 ) { len = *src; // get a second length from the attacker controlled datastream -- some value from 0 to 255, unbound to rdlen src++; memcpy( dst, src, len ); // copy that second length to rdlen byte buffer. dst += len; src += len; rdlen -= len + 1; } *dst = '