Vulnerabilidades escurridizas, invisibles en el código durante años

ElevenPaths    15 enero, 2014
Hace poco se ha corregido una vulnerabilidad de desbordamiento de pila que afecta al servidor X11. Llevaba “escondida” en el
código desde 1991, presente en muchas de las distribuciones Linux y permitiendo, para quien la conociese, elevar privilegios en el sistema afectado. ¿Existen
otros casos de vulnerabilidades que han pasado desapercibidas durante años?
El caso X11
X11 es un servidor gráfico desarrollador por el MIT a mediados
de los 80 que proporciona interfaz gráfica a los sistemas basados en UNIX. A
principios de 2014, y usando una herramienta llamada cppcheck, se
ha encontrado un desbordamiento de pila a la hora de procesar fuentes BDF con la
librería libXfont. Básicamente, esto permite a un atacante local elevar
privilegios a root haciendo que el sistema procese un tipo de letra
especialmente manipulado
. La sencillez del parche (que simplemente limita el tamaño) explica el problema. Se trata de un desbordamiento de pila
“de libro”).
–        if
(sscanf((char *) line, “STARTCHAR %s”, charName) != 1) {
+        if
(sscanf((char *) line, “STARTCHAR %99s”, charName) != 1) {
            
bdfError(“bad character name in BDF filen”);
             goto
BAILOUT; /* bottom of function, free and return error */
}
Página de descarga de cppcheck.sourceforge.net

X11, aun siendo un software extremadamente usado y popular,
contuvo durante 23 años una vulnerabilidad, en principio, que parecía bastante
sencilla de detectar
 por el ojo humano, pero que en realidad tuvo que se cazada con la ayuda de un programa automático.

Un caso Solaris
El  12 de febrero de 2007 se
da a conocer una vulnerabilidad en (por aquel entonces) Sun Solaris 10 tan simple como sorprendente. El fallo permitía el
acceso trivial como cualquier usuario (incluido root) a través de telnet.
El error fue
ya descubierto y corregido en sistemas UNIX en 1994, pero Solaris lo “reintrodujo”en sus sistemas en noviembre de 2002, con lo que pasó inadvertida durante unos 5 años. A través de un simple parámetro del cliente telnet (“-f”,
utilizado para traspasar las credenciales locales), se podía acceder a un
servidor telnet en Sun Solaris 10 sin necesidad de autenticación. Sólo
conociendo el nombre de usuario. El comando para “explotar” el fallo era:

telnet -l “-froot” [direccion_del_host]
El código del demonio telnet en Solaris 10 es abierto.
Un caso Oracle
El fallo CVE-2012-1675 en Oracle, reconocido por la compañía
en abril de 2012, fue reportado en 2008 por Joxean Koret (@matalaz). Afectaba a
todas las versiones de Oracle Database (desde 8i hasta la versión 11g R2). La
vulnerabilidad permitiría controlar el tráfico cliente-servidor y modificarlo,
a través de un ataque MITM. Aunque se reportó en 2012, la vulnerabilidad estaba
en el código probablemente desde 1999.
 Además de la antiguedad del problema, Oracle protagonizó un episodio vergonzante en la gestión de parches. Koret, creyendo que había sido por fin
solucionado, publicó todos los detalles. Haciendo gala de una respuesta
totalmente absurda, Oracle respondió que en realidad “the vulnerability
was fixed in future releases of the product”, lo que no tenía sentido (fue
corregida en futuras versiones).
Un caso Windows
A principios de 2007, todo el mundo hablaba de la
vulnerabilidad de los Windows MetaFile (WMF) que supuso una pesadilla para
Microsoft por muchas razones (se llegó a sacar un parche extraoficial por la comunidad, antes que la propia Microsoft). Era tan sencilla de explotar que Steve Gibson llegó a insinuar que podría ser intencionada, una puerta trasera incluida a propósito en el sistema
operativo más famoso.

El fallo estaba basado en los registros de tipo META_ESCAPE,
concretamente en el subcódigo SetAbortProc. En ella se deben especificar dos
argumentos, uno que representarían el “Device Context” y el segundo
sería una función a ejecutar ante un evento de cancelación de impresión.
Controlarlos y ejecutar código era tan sencillo como enviarles los comandos
adecuados. Stephen Toulouse escribió además en el blog oficial de Microsoft que
el fallo estaba presente desde los tiempos de Windows 3.0, creado hacia 1990.
SetAbortProc fue programada cuando la seguridad no representaban la mayor de
las prioridades y fue introducida en los tiempos en los que procesar imágenes
era lento y quizás fuese necesario abortar el proceso de impresión antes de que
terminara, mucho antes incluso de que existiera el formato WMF. Aunque la
funcionalidad fue perdiendo importancia, se fue portando junto con muchas
otras, versión tras versión, en lenguaje ensamblador a los siguientes sistemas
operativos que surgieron después. Se mantuvo por tanto unos 17 años en el código
sin que nadie lo detectara
. Ni siquiera los profesionales que se dedican a tiempo completo a encontrar fallos en Windows (que los hay).
¿Cómo puede ocurrir esto?
Los ejemplos expuestos son los más llamativos y escandalosos.
Hay más ejemplos de todo tipo, en código abierto y cerrado. De hecho, todos los días se corrigen vulnerabilidades en sistemas
operativos o programas que llevan años funcionando, y quizás las
vulnerabilidades corregidas hoy llevan ahí ocultas desde que se usa ese sistema.
Por ejemplo, muchas vulnerabilidades que se siguen encontrando en XP puede que estén ahí desde octubre de 2001, cuando fue sacado al mercado.
Las vulnerabilidades son inevitables, tanto en el diseño de
programas como de protocolos. En este sentido, el fallo de Kaminsky en los DNS descubierto en 2008 es un buen ejemplo de un fallo de diseño que pasó
desapercibido durante decenas de años, aun siendo un estándar completamente
abierto aprobado en su teoría e implementado en la práctica por decenas de
compañías.

istruecryptauditedyet.com

Poco parece que tenga que ver la eterna discusión sobre el
código abierto o cerrado y las ventajas frente a la detección “temprana” de
vulnerabilidades.
Sin entrar en el aspecto filosófico del uso de software de
código abierto, ¿en realidad resulta más sencillo encontrar vulnerabilidades en programas muy complejos de código abierto que en programas muy complejos de código cerrado? Un buen ejemplo es el caso TrueCrypt. Aunque sea de código abierto, sus usuarios necesitamos poder fiarnos totalmente de él, dada su importancia para proteger la confidencialidad. Pero para conseguirlo, se ha precisado de una campaña de recogida de fondos para (entre otras cosas) poder permitirse auditar su código, y premiar a los auditores que encuentren fallos en él. Llevan ya varios meses con el proyecto, y su sueño (porque no es fácil) sería realmente conseguir una auditoría completa de un código tan complejo como es cualquiera que trabaje con criptografía. Otro ejemplo de lo difícil que es auditar (o encontrar errores) en código en general y criptográfico en particular, es el desastre ocurrido en el demonio openSSL de Debian, que eliminó la entropía de creación de claves públicas y privadas en 2006. Nadie lo notó durante dos años.

Todo esto viene a recordar que de esos
“miles de ojos” que pueden mirar el código, no son todos igual de
efectivos… que algunos programas son más eficaces que el ojo humano, y que el hecho de que se permita mirar el código no significa que todo el mundo lo mire ni lo entienda realmente. El código abierto tiene muchas ventajas (prácticas y teóricas): en programas muy complejos una que sí se aprovecha en la práctica es que permite entender y mitigar (pero quizás no tanto detectar) las vulnerabilidades más rápidamente. Por supuesto, se puede argumentar que, si no fuese código abierto, no se hubiesen encontrado nunca estos fallos. Es posible. Defender uno u otro modelo es un asunto delicado para muchos. Lo que no hay que olvidar en cualquier caso es que auditar código desnudo es una tarea muy
compleja
que no puede ser delegada exclusivamente a programas. Necesita además del ojo
humano, pero no cualquiera… no los “miles de ojos potenciales”, sino de “pocos pero reales” que cuentan con gran experiencia, que son buenos programadores, profesionales, que saben interpretar correctamente los resultados de los programas automáticos de auditoría, que disponen de paciencia, tiempo… Y no se dedican todos estos recursos a todos los programas de código abierto (ni cerrado) “mágicamente”. De hecho, lamentablemente, encontrar vulnerabilidades es una tarea a la que los atacantes profesionales parecen dedicar mucho más esfuerzo y empeño que cualquier comunidad o auditores y se centran en cualquier programa que les reportes beneficios, independientemente de la filosofía de código.

Sergio de los Santos
ssantos@11paths.com

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *