miércoles, 28 de enero de 2015

GetRootByGetHostByName

El año va a comenzar como terminó 2014, plagado de grandes éxitos. El que hoy vamos a presentar tiene todos los visos de convertirse en la canción del verano de las veces que vamos a escucharla en los próximos meses. Dentro de unos días, cuando las listas y foros de seguridad se llenen de exploits solo tendréis que echarle un ojo a los registros del IPS para comprobarlo. Con 'shellshock' tenía su gracia, hacer un grep '() { :; }' en los del servidor web, sobre todo del IIS. En fin.

Este "gran éxito" ha sido bautizado como GHOST, tiene su propio logo y de momento (habrá que esperar) no tiene dominio propio y web para hacer pruebas, cuestión de tiempo, para que cumpla con todos los requisitos (resumimos: nombre pegadizo, logo y dominio+web para hacer pruebas). Vamos a lo que nos interesa, quién, qué, cómo y el diámetro del cráter que podría dejar su explotación.

Lo ha descubierto la empresa Qualys, dándolo a conocer Amol Sarwate, jefe de ingeniería, en un post en el blog de la empresa. No se publicarían detalles de GHOST hasta que las principales distribuciones Linux tuvieran los paquetes con el parche correspondiente fuera del horno. Y así ha sido, una vez se han sincronizado los repositorios han liberado los detalles del "fantasma". Un equilibrio casi perfecto entre el anuncio responsable y la cuota de atención que van a tener durante estos días. No le quitemos mérito, investigar es invertir y hasta ahora lo único que han hecho mal es ponerle un nombre antiSEO a la criatura.

Vamos al qué.

Todas las distribuciones Linux que usen la librería glibc (y eglibc) versión 2.17 y anteriores son virtualmente vulnerables. ¿Cómo comprobar la versión?

ldd print | grep libc.so

o directamente ejecutando la librería en la línea de comandos. Sí, puedes ejecutar una librería en Linux. En el caso de libc esta dispone de un punto de entrada hacia __libc_main donde llama a __libc_print_version que no hace otra cosa que imprimir cierta información en formato humano sobre su compilación.

 /lib/i386-linux-gnu$ ./libc.so.6

GNU C Library (Ubuntu EGLIBC 2.19-0ubuntu6.5) stable release version 2.19, by Roland McGrath et al.
Copyright (C) 2014 Free Software Foundation, Inc.

Evidentemente también puedes verificar la versión instalada buscando su paquete correspondiente, pero esto va a variar en función de la distribución usada.

Al grano. El fallo reside en la función '__nss_hostname_digits_dots', definida en el archivo 'gnu/glibc/nss/digits_dots.c'. Esta función es usada por un grupo de funciones de la familia 'gethostbyname' (de ahí el GHOST) y su cometido es comprobar si la cadena que se ha pasado a 'gethostbyname' es una IP. De esta forma el sistema se ahorra una consulta DNS. Básicamente es como si intentases resolver una IP (no una resolución inversa, ojo), algo que carece de sentido.
Vamos a recorrer la vulnerabilidad al revés, el fallo podemos verlos en la línea 157 del código de 'digits_dots.c' (sin el parche):

(157) resbuf->h_name = strcpy (hostname, name);

Ya de entrada el uso de 'strcpy' debería resultar sospechoso, básicamente porque no hace ninguna comprobación sobre los límites del búfer de destino y terminará sobrescribiendo "hostname" hasta que encuentre el carácter '\0' en "name".

Vemos de donde viene el cálculo del tamaño de "hostname".

(125) hostname = (char *) h_alias_ptr + sizeof (*h_alias_ptr);

'h_alias_ptr' es:

(124) h_alias_ptr = (char **) ((char *) h_addr_ptrs + sizeof (*h_addr_ptrs));

nuevamente, a su vez, 'h_alias_ptrs' es:

(122-123) h_addr_ptrs = (host_addr_list_t *) ((char *) host_addr + sizeof (*host_addr));

seguimos, 'host_addr' es un simple casting a 'buffer':

(121) host_addr = (host_addr_t *) *buffer;

'buffer' es donde se ha pasado el puntero que apunta al bloque de memoria reservado en 'new_buf':

(116) *buffer = new_buf;

Ya queda poco. 'new_buf' es donde está recogido el comienzo de la memoria reservada:

(101) *buffer_size = size_needed;
(102) new_buf = (char *) realloc (*buffer, *buffer_size);

Como podemos ver el tamaño viene definido por 'buffer_size' que es definido más arriba, teniendo en cuenta el tamaño de 'host_addr', 'h_addr_ptrs' y 'name'.

(85-86) size_needed = (sizeof (*host_addr) + sizeof (*h_addr_ptrs) + strlen (name) + 1);

Pero, ay, cuando se calcula el tamaño se hace con la intención de que en 'buffer' se guarden cuatro objetos, dejando un cuarto fuera del cálculo del tamaño de memoria a reservar: 'h_alias_ptr'.

Esta variable es un puntero a char. Luego la función 'strcpy' va a sobrescribir el tamaño, dependiente de la arquitectura, de un puntero a char. 4 bytes, típicamente, en arquitecturas de 32 bits, 8 bytes en las de 64 bits.

Esta es la cabecera de la función '__nss_hostname_digits_dots':
int
__nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
                            char **buffer, size_t *buffer_size,
                            size_t buflen, struct hostent **result,
                            enum nss_status *status, int af, int *h_errnop)
'name' es el parámetro que puede controlar el atacante. Cuando el servidor a la escucha necesite efectuar una llamada a 'gethostbyname' para resolver un nombre de dominio, es ahí donde comenzará la explotación.

Curiosamente, como apuntan en el anuncio de seguridad de Qualys, llegar a la línea donde se produce el desbordamiento es un camino lleno de obstáculos debido a la comprobación de ciertos valores en la cadena donde se supone que está el nombre del host. Todo un desafío para escribir un exploit.

Consideraciones

La librería 'libc' es omnipresente en todos los sistemas Linux, incluidos sistemas empotrados. Prácticamente casi todo el software nativo y no nativo hace uso de 'libc'. Eso convertiría en virtualmente vulnerable a casi todos los programas que hagan uso del grupo de funciones 'gethostbyname'. La salvedad es la forma en la que se hace uso de dichas funciones y más en el procesamiento previo que se efectúa sobre el nombre de host. Luego no todo es vulnerable, hay muchos condicionantes a tener en cuenta.

Curiosamente, este fallo ya fue parcheado en mayo de 2013, en la versión 2.18 de glibc, aunque en aquel momento no se llegó a tener en cuenta la "militarización" del error. Si vemos el parche aplicado en su día:
size_needed = (sizeof (*host_addr)
+ sizeof (*h_addr_ptrs)
+ sizeof (*h_alias_ptr) + strlen (name) + 1);
Comprobamos como se ha añadido el elemento faltante: 'h_alias_ptr'. Bug neutralizado.

Muchas distribuciones Linux ya contienen una versión corregida de este fallo desde entonces, 2013 y sin saberlo. Pero no es suficiente, ahora mismo, ahí afuera, hay cientos de miles de servicios que podrían estar a tres paquetes TCP de volar por los aires. La vulnerabilidad está presente desde 2000. Una calma que precede a la tempestad. Arriad velas, atrincad la carga y preparémonos para el impacto cuando publiquen los exploits.

Más información:

Qualys Releases Security Advisory for “GHOST” Vulnerability on Linux Systems

Qualys Security Advisory CVE-2015-0235
GHOST: glibc gethostbyname buffer overflow

funciones "gethostbyname*()"

[SECURITY] [DSA 3142-1] eglibc security update

Critical: glibc security update

USN-2485-1: GNU C Library vulnerability




David García
Twitter: @dgn1729

martes, 27 de enero de 2015

Nueva actualización de Adobe Flash Player

Tal y como había anunciado, Adobe ha publicado una nueva actualización para Adobe Flash Player para evitar la segunda vulnerabilidad 0-day que quedaba por solucionar y que está explotándose en la actualidad. Esta vulnerabilidad puede permitir a un atacante tomar el control de los sistemas afectados.

Las vulnerabilidades afectan a las versiones de Adobe Flash Player 16.0.0.287 (y anteriores) para Windows, Adobe Flash Player 13.0.0.262 (y versiones 13.x anteriores) y Adobe Flash Player 11.2.202.438 (y anteriores) para Linux.

Esta actualización, publicada bajo el boletín APSA15-01, resuelve la vulnerabilidad con CVE-2015-0311 que en la actualidad se está empleando en ataques a través de un exploit incluido en un kit de exploits para Flash conocido como Angler (Angler Exploit Kit). Está es una conocida herramienta utilizada para lanzar ataques masivos "drive-by-download", en los que principalmente infecta sistemas de forma transparente (sin intervención del usuario) a través de anuncios maliciosos incluidos sitios web legítimos.

Adobe confirma que los usuarios con la actualización automática activa ya están recibiendo la nueva versión 16.0.0.296 que soluciona el problema. También informa que estará disponible para descarga esta semana. Sin embargo, aunque no ha sido oficialmente anunciada, ya está disponible en el sitio de distribución:

Más información:

Security Advisory for Adobe Flash Player

una-al-dia (22/01/2015) Actualización de Adobe Flash Player para evitar un 0-day

Adobe Flash Player Distribution


Antonio Ropero

Twitter: @aropero