Skip to content ↓ | Skip to navigation ↓

 

There’s a lot of chatter going on right now related to the GHOST vulnerability that was announced yesterday. Lots of folks are talking about the vulnerability, particularly focused on the threat advisory published by Qualys. However, I thought I would spend a little time looking at the history of this vulnerability and how its underlying bug was originally discovered.

HISTORY

The flaw underlying the GHOST vulnerability was discovered by a developer who noticed an inconsistent return code in gethostbyname_r(). Particularly, modifying the size of a user-supplied (caller-supplied) buffer would change the code’s behavior and error response.

Essentially, the “trick” to properly using the gethostbyname_r() function in an application is to properly adjust a buffer’s size based on gethostbyname_r() returning the ERANGE  error code. If the user supplied buffer used by gethostbyame_r() is too small, ERANGE will be returned and the application should increase the supplied buffer’s size appropriately and try again.

However, the developer noticed that, with certain buffer sizes, EINVAL would be returned (incorrectly) instead of ERANGE. This inconsistency turns out to have been due to a bug in the __nss_hostname_digits_dots() function where a size calculation using the sizeof() function was missing.

The developer who submitted the original bug back in January, 2013 might not have known it, but he was actually “fuzz testing” this library. He did this by dynamically adjusting the initial size of a given buffer and then checked for certain responses. Here is the code he submitted with the bug that would trigger the issue:

#include <netdb.h>
#include <errno.h>
#include <iostream>
int main(int argc, char** argv)
{
   const std::string name=argc==1?"":argv[1];
   unsigned int size = DNS_BUFFER_SIZE;
   char* tmp = new char[size];   struct hostent* res = NULL;
   hostent buf;
   int err = 0;
   int result=0;
   while( (result=::gethostbyname_r( name.c_str(), 
      &buf, tmp, size, &res, &err )) == ERANGE )
   {
      delete[] tmp;
      tmp = new char[size*=2];
   }
   delete[] tmp;
   if (res==0)
      std::cout << "error: " << result << " (" 
         << hstrerror(result) << ")" << std::endl;
   return 0;
}

Running this code on a system with the vulnerable library as follows triggers the wrong error:

$> g++ -W -Wall -DDNS_BUFFER_SIZE=37 dnslookup.cpp -o dnslookup
$> ./dnslookup USER_SUPPLIED_HOSTNAME
error: 22 (Unknown resolver error)

Specifically, the code is returning error number 22 (EINVAL). Changing the argument “-DDNS_BUFFER_SIZE=37” to “-DDNS_BUFFER_SIZE=38” would cause this program to run successfully.

So, about 4 months passed after the bug was discovered, then library was fixed and the bug was closed. However, it appears that the issue was not readily viewed as a buffer overflow flaw, and, hence, the bug was not classified (originally) as a security issue. As such, the bug fix did not receive the attention it deserved, especially amongst the bigger Linux distributors such as RedHat, Ubuntu, and Debian.

IMPACT

There are numerous researchers and blogs [see links below] out there already where experts are agreeing that the bug will have low security impact. For example, Craig Young and I were comparing GHOST to Shellshock. Both of these vulnerabilities have far reaching impact due to the vulnerable code’s pervasiveness. However, GHOST is no Shellshock. Shellshock was not only remotely exploitable across many different services and platforms, but it was also remotely exploitable with virtually the same payload. The same cannot be said for GHOST. Each service that will be vulnerable to GHOST (via calls to the appropriate vulnerable libc functions) will very likely require unique payloads. This will require a lot of development efforts for an attacker. And, as many have pointed out, the resulting return on investment for development of exploits will be low since the bug has been fixed since 2013.

PEACE OF MIND

Tripwire’s VERT has developed generic vulnerability coverage for GHOST, which will be shipping in ASPL-599 on Wednesday, January 28, 2015. VERT will continue to expand GHOST vulnerability coverage over the next few weeks as more and more vendors ship updates that address the GHOST vulnerability.

 

LINKS