Monday, February 2, 2015

UPDATED!!! HOWTO Patch a GNU/Debian Linux Distribution against the libc GHOST Vulnerability CVE-2015-0235

The thing is that when you have Shared Web Servers, Storage Clusters, or any other Productive Servers/Systems it is not easy to do a "dist-upgrade", therefore I came across a second Solution:

First Choice: Upgrade libc6 without Dist-Upgrade


1- Check libc Version:
root@xdev:~# dpkg -l | grep libc6
root@xdev:~# ldd --version

2- Like it is descripted below on our Second Solution, check if the System is vulnerable:
root@xdev:~# ./ghosttest 

3- Check which packages/applications depends upon libc:
root@xdev:~# lsof | grep libc | awk '{print $1}' | sort | uniq

4- Let's update only the libraries needed. In our example, will only be:
root@xdev:~# apt-get update
root@xdev:~# apt-get install libc-bin libc6:amd64

5- After the upgrade, let's check the versions:
root@xdev:~# dpkg -l | grep libc6
root@xdev:~# ldd --version

6- And let's check if the Server is still vulnerable (it should not):
root@xdev:~# ./ghosttest

Now, the funny part. :)

7- In Debian Wheezy, we have the swesome "debian-goodies" which, in our case, we will be using "/usr/sbin/checkrestart" that helps to find and restart processes which are using old versions of upgraded files (such as libraries).

In our example:

root@xdev:~# /usr/sbin/checkrestart
Found 27 processes using old versions of upgraded files
(14 distinct programs)
(13 distinct packages)

Of these, 11 seem to contain init scripts which can be used to restart them:
The following packages seem to have init scripts that could be used
to restart them:
nfs-common:
        1721    /usr/sbin/rpc.idmapd
        1685    /sbin/rpc.statd
nbd-server:
        2467    /bin/nbd-server
rpcbind:
        1654    /sbin/rpcbind
apache2.2-bin:
        16641   /usr/lib/apache2/mpm-prefork/apache2
        2098    /usr/lib/apache2/mpm-prefork/apache2
        16636   /usr/lib/apache2/mpm-prefork/apache2
        16637   /usr/lib/apache2/mpm-prefork/apache2
        16635   /usr/lib/apache2/mpm-prefork/apache2
        16634   /usr/lib/apache2/mpm-prefork/apache2
openssh-server:
        18013   /usr/sbin/sshd
        2505    /usr/sbin/sshd
acpid:  
        2061    /usr/sbin/acpid
udev:   
        410     /sbin/udevd
        411     /sbin/udevd
        298     /sbin/udevd
cron:   
        2171    /usr/sbin/cron
at:
        2124    /usr/sbin/atd
rsyslog:
        2031    /usr/sbin/rsyslogd
exim4-daemon-light:
        2444    /usr/sbin/exim4

These are the init scripts:
service nfs-common restart
service nbd-server restart
service rpcbind restart
service apache2 restart
service ssh restart
service acpid restart
service udev-mtab restart
service udev restart
service cron restart
service atd restart
service rsyslog restart
service exim4 restart

These processes do not seem to have an associated init script to restart them:
bash:   
        18015   /bin/bash
root@xdev:~#  

8- Now, you have to choices:
- Restart Carefully all the services!
- Reboot the Server

Happy Patching! :P

Second Choice: Upgrade libc6 performing Dist-Upgrade


First, let's check the version of glibc on your GNU/Debian Linux Distribution:

ximena@xdev:~$ ldd --version
ldd (Debian EGLIBC 2.13-38+deb7u6) 2.13
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

GHOST vulnerability check

You can test or reproduce the bug using the following C Script:

/* ghosttest.c:  GHOST vulnerability tester */
/* Credit: http://www.openwall.com/lists/oss-security/2015/01/27/9 */
#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);
}

Compile it and run it as follows:

ximena@xdev:~$ gcc ghosttest.c -o ghosttest
ximena@xdev:~$ ./ghosttest

Sample outputs from patched Debian Wheezy 7.8 Server:

not vulnerable

Sample outputs from unpatched Debian Wheezy 7.6 Server:

vulnerable

How do list packages/applications depends upon vulnerable Glibc?

Type the following lsof command:

ximena@xdev:~$ lsof | grep libc | awk '{print $1}' | sort | uniq

Sample outputs from my Debian Linux v7.x:

awk
bash
dbus-daem
dbus-laun
gconfd-2
gmain
grep
lsof
sort
ssh
uniq
/usr/bin/

Fix the GHOST vulnerability on a Debian Linux

Type the following apt-get command as the root user:

ximena@xdev:~$ sudo apt-get clean
ximena@xdev:~$ sudo apt-get update
ximena@xdev:~$ sudo apt-get dist-upgrade

Finally, reboot Debian Linux server by typing the following command:

ximena@xdev:~$ sudo reboot

How can I verify that my Linux system no longer vulnerable after the reboot?

Method #1: The easiest way to check vulnerability is to run the following command to verify that you are running an updated version of Glibc:

ximena@xdev:~$ ldd --version
ldd (Debian EGLIBC 2.13-38+deb7u7) 2.13
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

Method #2: Run the Script given in the previous section called GHOST vulnerability check.

I Hope that helps! :)