Comprobar y parchear la vulnerabilidad GHOST de Glibc CVE-2015-0235

Si todavía no has verificado si tus sistemas GNU/Linux son vulnerables al problema de seguridad de la librería Glibc de GNU, deberías hacerlo lo antes posible. Esta vulnerabilidad llamada GHOST y cuyo ID es CVE-2015-0235 fue anunciada el pasado 27 de enero y los parches ya están disponibles para su descarga e instalación.

CVE-2015-0235: A vulnerability was found and fixed in the GNU C Library,
specifically in the function gethostbyname(), that could lead to a local
or remote buffer overflow. (bsc#913646)

Los pasos para verificar si el sistema es vulnerable y corregir dicha vulnerabilidad son los siguientes.

Comprobar la versión de Glibc utilizada en el sistema

El siguiente comando nos muestra el número de versión de la librería C de GNU (glibc):

# ldd --version

La salida es similar en las distintas distribuciones. Ejemplos:

CentOS 7:

# ldd --version
ldd (GNU libc) 2.17
Copyright (C) 2012 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.

Ubuntu:

$ ldd --version
ldd (Ubuntu EGLIBC 2.13-0ubuntu13.2) 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.

Verificar si la versión de glibc es vulnerable

Conociendo el número de versión podemos saber si el sistema es vulnerable al BUG CVE-2015-0235. En resumen, las versiones no parcheadas desde la 2.2 a la 2.17 son vulnerables.

Si queremos asegurarnos al 100%, podemos compilar y ejecutar el siguiente código extraído de openwall.com.

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

Compilamos y ejecutamos:

$ gcc ghosttest.c -o ghosttest
$ ./ghosttest

En la salida del comando nos indicará si el sistema es vulnerable con el texto:

vulnerable

Y si no lo es:

not vulnerable

Otro script de chequeo proporcionado por la Red Hat Network:

#!/bin/bash
#Version 3

echo "Installed glibc version(s)"

rv=0
for glibc_nvr in $( rpm -q --qf '%{name}-%{version}-%{release}.%{arch}\n' glibc ); do
    glibc_ver=$( echo "$glibc_nvr" | awk -F- '{ print $2 }' )
    glibc_maj=$( echo "$glibc_ver" | awk -F. '{ print $1 }')
    glibc_min=$( echo "$glibc_ver" | awk -F. '{ print $2 }')
    
    echo -n "- $glibc_nvr: "
    if [ "$glibc_maj" -gt 2   -o  \
        \( "$glibc_maj" -eq 2  -a  "$glibc_min" -ge 18 \) ]; then
        # fixed upstream version
        echo 'not vulnerable'
    else
        # all RHEL updates include CVE in rpm %changelog
        if rpm -q --changelog "$glibc_nvr" | grep -q 'CVE-2015-0235'; then
            echo "not vulnerable"
        else
            echo "vulnerable"
            rv=1
        fi
    fi
done

if [ $rv -ne 0 ]; then
    cat <
Please refer to <https://access.redhat.com/articles/1332213> for remediation steps
EOF
fi

exit $rv

Cómo Parchear los sistemas

En caso de que la versión sea vulnerable, parcheamos actualizando a través de los repositorios del sistema.

CentOS y RHEL

# yum update glibc

Es necesario reiniciar para aplicar correctamente todos los cambios y que se utilice la nueva versión de glibc por todo el sistema.

Debian y Ubuntu

# apt-get update && apt-get upgrade

Y reiniciamos:

# reboot

SUSE

SUSE Linux Enterprise Software Development Kit 11 SP3:

# zypper in -t patch sdksp3-glibc-10206

SUSE Linux Enterprise Server 11 SP3 for VMware:

# zypper in -t patch slessp3-glibc-10206

SUSE Linux Enterprise Server 11 SP3:

# zypper in -t patch slessp3-glibc-10206

SUSE Linux Enterprise Server 11 SP2 LTSS:

# zypper in -t patch slessp2-glibc-10204

SUSE Linux Enterprise Server 11 SP1 LTSS:

# zypper in -t patch slessp1-glibc-10202

SUSE Linux Enterprise Desktop 11 SP3:

# zypper in -t patch sledsp3-glibc-10206