Informáticos han dejado al descubierto contraseñas, correos, datos financieros y otros tipos de información sensible potencialmente conectada con miles de millones de personas. Los fallos aparecieron en tres lugares distintos: el software de los servidores web, los iPhones y el sistema operativo Windows, pero todos tenían el mismo origen: errores por descuido de los programadores.
Cada uno de estos fallos: Heartbleed, el «fallo goto», y “exploit de día cero”, los crearon hace años programadores que escribían en lenguaje C
Cada uno de estos fallos: Heartbleed en un programa llamado OpenSSL, el «fallo goto» en los sistemas operativos de Apple, y lo que se ha denominado “exploit de día cero” descubierto en Internet Explorer de Microsoft, los crearon hace años programadores que escribían en lenguaje C, un lenguaje conocido por su potencia, su expresividad y por la facilidad con que conduce a los programadores a cometer toda clase de errores. Usar C para escribir software clave para internet es como usar una cuchilla de muelle para abrir cajas, es muy chulo hasta que te rebanas los dedos.
Lamentablemente, por muy peligroso que sea, no hay visos de que nos vayamos a deshacer de C en un futuro cercano. Los programas escritos en C y su lenguaje relacionado, C++, componen una gran parte del software que mueve internet. Y siguen empezándose nuevos proyectos en estos lenguajes, porque los programadores creen que necesitan la velocidad de C y se creen lo suficientemente buenos para evitar las trampas y zancadillas que les pone.
Aunque no podamos deshacernos del lenguaje, sí podemos obligar a quienes lo usan a que lo hagan mejor. Lo haríamos tomando prestado un concepto cotidiano del mundo físico.
Evidente a posteriori
De los tres fallos, el más importante con diferencia ha sido Heartbleed. Es un error en un programa que pone en marcha un protocolo conocido como Secure Sockets Layer/Transport Layer Security (SSL/TLS), que es el método de encriptado fundamental usado para proteger la gran mayoría de la información financiera, médica y personal que se envía a través de internet. El protocolo SSL original posibilitó la aparición del comercio electrónico en la década de 1990. OpenSSL es una puesta en práctica de código abierto de SSL/TLS que lleva casi el mismo tiempo en funcionamiento. El programa ha ido creciendo y ampliándose a lo largo de los años.
Se cree que los protocolos criptográficos actuales son tan fuertes que en la práctica no existe ninguna forma de romperlos. Pero Heartbleed hizo que el encriptado de SSL resultara irrelevante. A través de esta brecha informática, un atacante de cualquier parte de internet podía acceder al corazón de la memoria de un servidor web y extraer un trocito de datos privados. El nombre del fallo no proviene de esta metáfora, sino del hecho de que Heartbleed (corazón sangrante) es un fallo en el protocolo de «latido» que usan los navegadores web para comunicar a los servidores web que aún están conectados. Básicamente, el atacante podía enviar una señal a los servidores de forma que no solo confirmaba la conexión, sino que también conseguía que el servidor soltara parte de sus contenidos. Es como registrarte en un hotel que olvida vaciar las papeleras de las habitaciones de un huésped a otro. A veces estas pueden contener información muy valiosa.
El fallo Heartbleed se dio por una combinación de factores, entre ellos un error cometido por un voluntario trabajando sobre el programa OpenSSL al poner en marcha el protocolo de latido. Aunque cualquiera de los errores se podrían haber cometido si OpenSSL estuviera escrito en un lenguaje de programación moderno como Java o C#, había más probabilidades de que sucedieran porque OpenSSL está escrito en C.
El fallo de Apple surgió porque algún programador duplicó, sin darse cuenta, una línea de código que irónicamente decía «goto fail» [ve al fallo]. El resultado fue que, en determinadas condiciones, los iPhones y Macs ignoraban errores que surgían al intentar comprobar la legitimidad de un sitio web y no avisaban de ellos. Conociendo este fallo, un atacante podía establecer un punto de acceso inalámbrico capaz de interceptar la comunicación con internet de los usuarios de iPhone con sus bancos, y robar nombres de usuarios y contraseñas, volver a encriptar las comunicaciones y lanzarlas de nuevo. Este ataque se conoce como ataque «de intermediario» y justo para evitarlo es para lo que se diseñó SSL/TLS.
Sorprendentemente, el fallo «goto» ocurrió por una característica del lenguaje de programación C que se sabía resultaba problemática ¡incluso antes de que C se inventara! La orden «goto» hace que un programa de ordenador salte de un sitio a otro. Aunque este tipo de órdenes son habituales dentro del código máquina de los ordenadores, durante más de 40 años los informáticos han intentado evitar usar órdenes «goto» en programas escritos en el denominado «lenguaje de alto nivel». Java (diseñando a principios de la década de 1990), no tiene una orden «goto», pero C (diseñado a principios de la década de 1970), sí que la tiene. Aunque el programador de Apple responsable del problema «fallo goto» podría haber cometido un error parecido sin usar la orden «goto», es algo mucho menos probable.
Sabemos menos del tercer fallo porque el código fuente subyacente, parte del Internet Explorer de Microsoft, aún no se ha hecho público. Lo que sí sabemos es que fue un error «usar cuando esté libre»: el programa informa al sistema operativo de que ha terminado de usar un trozo de memoria y este a continuación vuelve a usar esa memoria. Según la empresa de seguridad FireEye, que fue quien encontró el fallo después de que los piratas empezaran a aprovecharlo contra objetivos de alto valor, el error llevaba en Internet Explorer desde agosto de 2001 y afectaba a más de la mitad de quienes se conectaban a la web a través de un PC tradicional. El fallo era tan importante que el Departamento de Seguridad Nacional de EEUU tomó la medida poco habitual de decirle a la gente que dejara de usar Explorer temporalmente. (Microsoft presentó un parche para el fallo el 1 de mayo).
Inspectores automatizados
Siempre habrá problemas con cualquier cosa diseñada o construida por un humano, evidentemente. Por eso tenemos leyes en el mundo físico que minimizan la posibilidad de que se den esos errores, y también procedimientos diseñados para pillar los errores que se nos cuelan.
Los constructores deben cumplir la ley de edificación, que regula qué materiales de construcción se pueden usar y gobierna determinados aspectos de la arquitectura del edificio, por ejemplo que los pasillos deben tener un ancho mínimo y que las salidas de incendios son obligatorias. Hay inspectores que visitan la obra para revisar el trabajo hecho y asegurarse de que cumple con la norma. Los inspectores obligarán a los constructores a abrir una pared si se ha instalado antes de que se haya podido inspeccionar el trabajo que se ha hecho dentro.
El mundo del desarrollo de software es completamente distinto. Es habitual que los desarrolladores escojan el lenguaje y las herramientas que usarán. ¡Muchos desarrolladores diseñan sus propios tests de fiabilidad y los ejecutan ellos mismos! Las grandes empresas se pueden permitir tener equipos de control de calidad, pero muchas empresas pequeñas trabajan sin ellos. Incluso en las grandes empresas, el código que parece funcionar bien no se suele probar en busca de fallos de seguridad ocultos porque la comprobación manual hecha por humanos es muy cara, a veces más incluso que escribir el software original, dado que las pruebas pueden revelar problemas que a continuación los desarrolladores tendrán que arreglar. Estos fallos se denominan «deuda técnica», puesto que son costes de ingeniería tomados prestados contra el futuro por el interés en lanzar el código ya.
La solución es establecer normas de construcción de software y hacerlas cumplir con un ejército de inspectores sin sueldo.
La clave es que esos inspectores sin sueldo no deberían ser personas, o al menos no sólo personas. Algunos defensores del software de código abierto respaldan la teoría del desarrollo de software con «muchos ojos»: la idea de que si un trozo de código lo revisa una cantidad suficiente de personas, se hallarán las vulnerabilidades de seguridad. Desgraciadamente, Heartbleed demuestra lo falaz de este argumento: aunque OpenSSL es uno de los programas de seguridad de código abierto de uso más generalizado, hicieron falta ingenieros de seguridad a sueldo en Google y en la empresa de seguridad finlandesa Codenomicon para encontrar el fallo, y no lo encontraron hasta dos años después de que los muchos ojos que rondan por internet obtuvieran acceso al código.
Este ejército de inspectores de construcción de software deberían ser las herramientas de desarrollo de software, los programas que los desarrolladores usan para crear programas. Estas herramientas pueden animar, convencer y obligar a los programadores a hacer lo correcto.
Y es algo que ya ha sucedido. En 1988, por ejemplo, el principal vector de infección para el primer internet era otro programa escrito en C. Usaba una función llamada «gets()» que era habitual entonces, pero es inherentemente insegura. Cuando se descubrió el gusano, los ingenieros que mantenían las bibliotecas núcleo del sistema operativo Linux (que ahora usan Linux y MacOS), modificaron la función gets() para que hiciera aparecer el mensaje: «Aviso: este programa usa gets(), que no es seguro». Poco después, los desarrolladores de todo el mundo retiraron gets() de sus programas.
El mismo tipo de enfoque se puede usar para prevenir fallos futuros. En la actualidad hay muchas herramientas de desarrollo de software capaces de analizar los programas y avisarnos de chapuzas estilísticas (por ejemplo, el uso de una orden «goto»), fallos de memoria (como el fallo «usar cuando esté libre»), o código que no sigue los estándares de buena programación. Sin embargo, muchas veces estos avisos están desactivados por defecto, porque resultan irritantes; exigen que el código se reescriba y limpie sin que se produzca una mejora correspondiente en la seguridad. Otras herramientas para encontrar fallos ni siquiera se incluyen en las colecciones de herramientas de desarrollo estándares, sino que hay que descargarlas por separado, instalarlas y ejecutarlas. En consecuencia, muchos desarrolladores ni siquiera saben que existen, y evidentemente no las usan.
Para que internet sea más seguro, las pruebas más exhaustivas tendrán que activarse por defecto, algo que obligará a los programadores a escribir mejor código para empezar. Y como las herramientas de análisis de programas funcionan mejor con lenguajes modernos como C y Java y peor con programas escritos en C, los programadores deberían evitar empezar nuevos proyectos en C o C++, igual que es poco sensato empezar proyectos de construcción usando materiales y técnicas anticuados.
Los programadores son humanos y todo el mundo comete errores. Las empresas de software tienen que aceptar este hecho y hacer que sea más fácil prevenir los fallos.