1

The ghost vulnerability has the potential to be vulnerable to many many pieces of software that call the gethostbyname() and gethostbyname2() functions. Is there an easy way to scan an executable to determine if it makes use of either of these two vulnerable functions? While this wouldn't tell you if a program was vulnerable, it can tell you if it's NOT vulnerable.

To use either of these functions, I believe the executable (or 3rd party library) must link to it. It seems to me you should be able to scan the executable for a link to the shared library.

Steve Sether
  • 21,480
  • 8
  • 50
  • 76

2 Answers2

1

To find out if this calls are used, you could simply do a

strings -a /bin/ip | grep gethost

Another approach returning more information is

readelf --dyn-syms /bin/ip | grep gethost
ott--
  • 128
  • 1
  • 1
  • 9
0

Yes, there are few ways to get the info, nm and objdump are your friends.


Demo

For demo purposes, I've used a PoC developed by the University of Chicago to test if a system is vulnerable or not to the Ghost vulnerability.

Here's the code:

/*
 * GHOST vulnerability check
 * http://www.openwall.com/lists/oss-security/2015/01/27/9
 * Usage: gcc GHOST.c -o GHOST && ./GHOST
 */ 

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define CANARY "in_the_coal_mine"

struct {
  char buffer[1024];
  char canary[sizeof(CANARY)];
} temp = { "buffer", CANARY };

int main(void) {
  struct hostent resbuf;
  struct hostent *result;
  int herrno;
  int retval;

  /*** strlen (name) = size_needed - sizeof (*host_addr) - sizeof (*h_addr_ptrs) - 1; ***/
  size_t len = sizeof(temp.buffer) - 16*sizeof(unsigned char) - 2*sizeof(char *) - 1;
  char name[sizeof(temp.buffer)];
  memset(name, '0', len);
  name[len] = '\0';

  retval = gethostbyname_r(name, &resbuf, temp.buffer, sizeof(temp.buffer), &result, &herrno);

  if (strcmp(temp.canary, CANARY) != 0) {
    puts("vulnerable");
    exit(EXIT_SUCCESS);
  }
  if (retval == ERANGE) {
    puts("not vulnerable");
    exit(EXIT_SUCCESS);
  }
  puts("should not happen");
  exit(EXIT_FAILURE);
}

Then compile the code to generate the binary:

$ gcc GHOST.c -o ghost

Test if an unstripped binary contains gethostbyname* symbols: $ nm ghost | grep gethost U gethostbyname_r@@GLIBC_2.2.5 ... and sure it does.

Now, it's also possible the binary has been stripped of debugging symbols:

# stripping away debug symbols $ strip -o ghost-stripped ghost $ nm ghost-stripped nm: ghost-stripped: no symbols

In that case, you can use objdump: $ objdump -T ghost-stripped ghost-stripped: file format elf64-x86-64 DYNAMIC SYMBOL TABLE: ... 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 gethostbyname_r ...

... filter to only what we're looking for: $ objdump -T ghost-stripped | grep gethostbyname 0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 gethostbyname_r

fduff
  • 725
  • 1
  • 8
  • 17