Tuesday, January 27, 2015

You shouldn't be using gethostbyname() anyway

Today's GHOST vulnerability is in gethostbyname(), a Sockets API function from the early 1980s. That function has been obsolete for a decade. What you should be using is getaddrinfo() instead, a newer function that can also handle IPv6.

The great thing about getaddrinfo() is the fact that it allows writing code that is agnostic to the IP version. You can see an example of this in my heartleech.c program.

x = getaddrinfo(hostname, port, 0, &addr);
fd = socket(addr->ai_family, SOCK_STREAM, 0);
x = connect(fd, addr->ai_addr, (int)addr->ai_addrlen);

What you see here is your normal call to socket() and connect() just use the address family returned by getaddrinfo(). It doesn't care if that is IPv4, IPv6, or IPv7.

The function actually returns a list of addresses, which may contain a mixture of IPv4 and IPv6 addresses. An example is when you lookup www.google.com:

[ ] resolving "www.google.com"
[+]  74.125.196.105:443
[+]  74.125.196.147:443
[+]  74.125.196.99:443
[+]  74.125.196.104:443
[+]  74.125.196.106:443
[+]  74.125.196.103:443
[+]  [2607:f8b0:4002:801::1014]:443

My sample code just chooses the first one in the list, whichever is returned by the DNS server. Sometimes Google returns an IPv6 address as the first one. If you prefer a specific version, you can search through the list as demonstrated below:

while (addr && args->ip_ver == 4 && addr->ai_family != AF_INET)
addr = addr->ai_next;

Or, instead of searching the results yourself for an IPv4 or IPv6 address, you can use the third parameter to specify which one you want.

This function has been a POSIX standard for more than a decade. The above code works on WinXP as well as fairly old versions of Linux and Mac OS X. Even if your code is aggressively portable, there is little reason not to use this function. Only in insanely portable code, such as when you worry about 16-bit pointers, should have to worry about backing off to gethostbyname(). Conversely, gethostbyname() is no longer part of POSIX, and thus officially no longer "standard".

If you learn Sockets programming at the university, they still teach gethostbyname(). That's because as far as Internet programming is concerned, academia is decades out of date.

1 comment:

celula_x said...

if it's old; wonder why stocked Debian's Exim still calls it =\