[OT] getaddrinfo NXDOMAIN exploit - please test on CentOS 6 64-bit

John Nagle nagle at animats.com
Sun Apr 1 16:41:54 EDT 2012


On 4/1/2012 9:26 AM, Michael Torrie wrote:
> On 03/31/2012 04:58 PM, John Nagle wrote:
>> If you can make this happen, report back the CentOS version and
>> the library version, please.
>
> CentOS release 6.2 (Final)
> glibc-2.12-1.47.el6_2.9.x86_64
>
> example does not ping
> example.com does not resolve to example.com.com
>
> Removed all "search" and "domain" entries from /etc/resolve.conf

It's a design bug in glibc. I just submitted a bug report.

   http://sourceware.org/bugzilla/show_bug.cgi?id=13935

It only appears if you have a machine with a two-component domain
name ending in ".com" as the actual machine name.  Most hosting
services generate some long arbitrary name as the primary name,
but I happen to have a server set up as "companyname.com".

The default rule for looking up domains in glibc is that the
"domain" is everything after the FIRST ".".  Failed lookups
are retried with that "domain" appended.  The idea, back
in the 1980s, was that if you're on "foo.bigcompany.com",
and look up "bar", it's looked up as "bar.bigcompany.com".
This idea backfires when the actual hostname only
has two components, and the search just appends ".com".

There is a "com.com" domain, and this gets them traffic.
They exploit this to send you (where else) to an ad-heavy page.
Try "python.com.com", for example,and you'll get an ad for a
Java database.

The workaround in Python is to add the AI_CANONNAME flag
to getaddrinfo calls, then check that the returned domain
name matches the one put in.

Good case:
 >>> s = "python.org"
 >>> socket.getaddrinfo(s, 80, 0,0, 0, socket.AI_CANONNAME)
[(2, 1, 6, 'python.org', ('82.94.164.162', 80)), (2, 2, 17, '', 
('82.94.164.162', 80)), (2, 3, 0, '', ('82.94.164.162', 80)), (10, 1, 6, 
'', ('2001:888:2000:d::a2', 80, 0, 0)), (10, 2, 17, '', 
('2001:888:2000:d::a2', 80, 0, 0)), (10, 3, 0, '', 
('2001:888:2000:d::a2', 80, 0, 0))]

Bad case:
 >>> s = "noexample.com"
 >>> socket.getaddrinfo(s, 80, 0,0, 0, socket.AI_CANONNAME)
[(2, 1, 6, 'phx1-ss-2-lb.cnet.com', ('64.30.224.112', 80)), (2, 2, 17, 
'', ('64.30.224.112', 80)), (2, 3, 0, '', ('64.30.224.112', 80))]

Note that what went in isn't what came back.  getaddrinfo has
been pwned.

Again, you only get this if you're on a machine whose primary host
name is "something.com", with exactly two components ending in ".com".


				John Nagle




More information about the Python-list mailing list