CVE-2015-7547: vuelven los fantasmas de los resolvers de glibc

Tampoco nosotros podemos obviar una vulnerabilidad tan importante como la que se está hablando estos días y que afecta a miles (o millones?) de dispositivos Linux en todo el mundo. Lo habéis adivinado: se trata de CVE-2015-7547 a la que muchos están empezando a llamar GHOST 2.0 por su similitud con la que se encontró el año pasado (afecta a los resolvers) y se trata de un desbordamiento de pila mediante respuestas DNS debido a un fallo en la función getaddrinfo() del cliente DNS de glibc, desde la versión 2.9.

Fermín J. Serna alias Zhodiac nos contaba en el blog de seguridad de Google que empezaron a investigar un fallo de segmentación que se producía en el cliente SSH de un ingeniero cuando intentaba conectarse con un host en concreto. Pronto se dieron cuenta que eso podía derivar en la ejecución remota de código y consiguieron desarrollar un exploit totalmente funcional. Cuando se pusieron a investigar en mayor profundidad vieron que, sorprendentemente, el bug ya se notificó a los mantenedores de glibc en julio de 2005. Paralelamente Florian Weimer y Carlos O’Donell de Red Hat también estaban estudiando el impacto del bug y juntos desarrollaron un parche para proteger a todos los usuarios de glibc.


En el esquema de la derecha podéis ver de forma gráfica cómo se produce el desbordamiento de buffer que, en resumen, es cuando se recibe una respuesta DNS (TCP o UDP) de más de 2048 bits seguida por otra respuesta que desborda la pila.
 
glibc reserva 2048 bytes en la pila a través de la función alloca() para la respuesta DNS (_nss_dns_ gethostbyname4_r()).
Después, en send_dg() y send_vc(), si la respuesta es mayor de 2048 bytes, se asigna un nuevo buffer y toda la información se actualiza (puntero buffer, nuevo tamaño del buffer y tamaño de respuesta).
Bajo ciertas condiciones, puede ocurrir un desajuste entre el búfer de la pila y la nueva asignación del heap. El efecto final es que el búfer de pila se utiliza para almacenar la respuesta DNS, incluso si la respuesta es mayor que el búfer, conduciendo al desbordamiento de pila.

Como consecuencia es posible la ejecución remota de código, por supuesto siempre que no haya medidas de seguridad como ASLR en el sistema que lo impidan.

El gran problema es que al tratarse de un bug en la librería estándar de C de GNU afecta a muchísimos programas de un sistema Linux. Además, este fallo existe desde el 2008, así que podéis imaginaros la cantidad de servidores, estaciones de trabajo, sistemas embebidos como routers y otros cacharros que se ven afectados. Por suerte muchos de ellos, sobretodo smatphones y otros dispositivos algunos de la Internet de las Cosas (IoT), no se ven afectados ya que usan otras implementaciones más ligeras como bionic en Android o uClibc.

En las distros que si lo utilizan, si actualizamos glibc, todas las aplicaciones por ende dejarán inmediatamente de ser vulnerables. Por ejemplo ya se han confirmado vulnerables Debian 7, CentOS 6, Ubuntu 12.04, 14.04 y 15.10, RHEL/CentOS 6 y 7, ...la lista es larga. Sin embargo e irónicamente otras como Slackware que usan viejas versiones no son vulnerables.

Por otro lado, las aplicaciones compiladas con una versión vulnerable de glibc deberán recompilarse y ojo con actualizar otras aplicaciones como Zend Framework v2, Wordpress...

Para los sistemas que no podemos parchear inmediatamente, una manera de prevenir la explotación es configurar los resolvers para evitar que envíen respuestas mayores de 2048 bytes. Por ejemplo:

- en BIND - añade la siguiente línea en la sección de options de named.conf:
 

max-udp-size 2048;

- en Unbound - añade la siguiente línea en la sección de server de unbound.conf:


max-udp-size: 2048

Tampoco es mala idea activar ASLR:

sysctl -w kernel.randomize_va_space=2

    0 - nada de aleatorización, todo es estático
    1 - aleatorización conservadora, es decir, sólo librerías compartidas, stack, mmap(), VDSO y heap.
    2 - aleatorización completa incluida la memoria administrada mediante brk()

Por último, gracias a Fermín J. Serna existe una prueba de concepto "desarmada" que podemos probar para determinar si estamos afectados y/o si las mitigaciones son efectivas:

https://github.com/fjserna/CVE-2015-7547

Pero como siempre... ya sabes... ¡parchea!


[1] Disclosure: https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html
[2] Disclosure: https://googleonlinesecurity.blogspot.de/2016/02/cve-2015-7547-glibc-getaddrinfo-stack.html
[3] Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=18665

Comentarios