La profecía de 1984 se hace realidad: cómo manipular la herramienta strip infectó todo un sistema Linux

SeguridadLinuxCódigo AbiertoAtaque a la Cadena de SuministroPuerta Trasera de Compilador

Fuentes:arXiv + Lobsters + web research

En 1984, Ken Thompson subió al estrado de los Premios Turing de la ACM y pronunció un discurso que dejó profundamente inquieto a todo el mundo de la informática. Explicó que, incluso cuando el código fuente de un software es completamente abierto y accesible para cualquiera, pueden existir «puertas traseras invisibles a cualquier auditoría». Un compilador malicioso podría inyectar código malintencionado en los programas durante la compilación y, lo que es crucial, autorreplicar esa misma lógica maliciosa en el binario del compilador de la siguiente generación al compilarse a sí mismo. A partir de ahí, el código fuente malicioso podría eliminarse limpiamente del repositorio, pero la puerta trasera perduraría para siempre en los binarios de generación en generación.

Cuarenta y dos años después, aquella profecía se ha materializado por completo. En un artículo de investigación presentado el 27 de julio en arXiv (2607.24888), investigadores de Télécom Paris (Francia) y del Real Instituto de Tecnología de Suecia (KTH) han demostrado que para lanzar este ataque ni siquiera hace falta un compilador. Bastó con manipular una modesta herramienta de reducción binaria, GNU strip, para que una puerta trasera se propagara silenciosamente a través del proceso de arranque (bootstrap) de la distribución NixOS, infectando en última instancia prácticamente todos los ejecutables del sistema operativo.

Ken Thompson, premio Turing de 1984 y cocreador de Unix (fotografiado en 2019). Fuente: Wikimedia Commons Foto: Ken Thompson, premio Turing de 1984 y cocreador de Unix. Fuente: Wikimedia Commons

Por qué los ataques de compilador fueron «difíciles» durante 42 años

El ataque original concebido por Thompson dependía de un requisito fundamental: el compilador comprometido debía ser capaz de «reconocerse a sí mismo». Cuando compilaba su propio código fuente, tenía que inyectar la carga útil autorreplicable en el binario resultante. Para lograrlo, el atacante debía programar una lógica capaz de identificar patrones léxicos concretos en el código fuente del compilador, creando una especie de quine sumamente delicado.

Esa dependencia hacía que los ataques en compiladores fueran sumamente frágiles. En cuanto la base de código del compilador evolucionaba, sufría refactorizaciones o saltaba a una versión mayor, los patrones de búsqueda se rompían y la cadena de infección se interrumpía. Por ese motivo, el consenso general en la industria de la seguridad era que, si bien el ataque «Trusting Trust» de Thompson era impecable desde el punto de vista teórico, resultaba inviable para sobrevivir en el ciclo de vida del software real: era más un brillante experimento mental que una amenaza práctica duradera.

Los investigadores han sorteado este obstáculo por completo. El vector elegido fue GNU strip, una utilidad de GNU binutils cuya única función consiste en eliminar los símbolos de depuración y las tablas de símbolos de los ejecutables compilados. Ni analiza, ni genera, ni examina una sola línea de código fuente.

El ataque opera exclusivamente a nivel de binarios ELF, sin interactuar en ningún momento con el código fuente. Por mucho que el código fuente cambie o se refactorice, la puerta trasera permanece intacta: es mucho más persistente y difícil de erradicar que cualquier variante basada en compiladores.

Cómo se propaga la puerta trasera de una generación a otra

La ruta del ataque explota el mecanismo de arranque (bootstrap) de NixOS. Cuando NixOS compila el sistema operativo completo a partir del código fuente, el proceso parte de una «semilla binaria» (binary seed) compuesta por unos veinte ejecutables precompilados: la raíz fundacional de la confianza. A partir de esa semilla, el sistema reconstruye progresivamente su cadena de herramientas mediante fases sucesivas. Una vez alcanzado el entorno estándar (stdenv), la clausura de dependencias en tiempo de ejecución deja de referenciar la semilla binaria inicial.

La técnica de los investigadores consistió en manipular el único binario de strip presente en dicha semilla. Cada vez que este strip inicial se invoca durante la compilación por etapas, implanta la carga útil autorreplicable en el strip de la siguiente generación (lo que el artículo denomina «arista sucesora» o successor edge). De este modo, incluso después de que la semilla inicial desaparezca del árbol de dependencias, la carga maliciosa sobrevive y se asienta de lleno en el entorno estándar final.

Diagrama general del diseño e implementación del ataque. Fuente: arXiv 2607.24888 Figura: Diagrama general del diseño e implementación del ataque. Fuente: arXiv 2607.24888

El experimento se llevó a cabo sobre una versión real de nixpkgs. Los investigadores lograron compilar una imagen ISO completa con instalador gráfico sin un solo error. La clausura resultante integró 1.199 paquetes, 3.799 ejecutables ELF invocables por el usuario y un volumen en disco de 6,16 GB.

El alcance de la infección fue sobrecogedor: de 3.791 ejecutables de línea de comandos (CLI), 3.790 resultaron infectados con la marca de la puerta trasera. El único programa que logró librarse fue Firefox 147.0.3, debido exclusivamente a que su configuración de compilación incluía el modificador --disable-strip, omitiendo por completo la etapa de ejecución de strip.

Que un programa que simplemente desactivó strip fuera el único superviviente demuestra, de forma paradójica, la implacable omnipresencia del ataque.

Independiente del lenguaje de programación y con todos los tests superados

Los binarios infectados abarcan los principales ecosistemas de desarrollo: C y C++ (bash, git, sudo, curl, python3.13), Python (pydoc, idle), Rust (rsvg-convert), Go (captree) y Lua (lua). El ataque no distingue entre lenguajes porque no analiza código fuente, sino que modifica directamente los archivos binarios ELF ya compilados.

Aún más desconcertante fue el resultado de las pruebas de estabilidad. Los investigadores arrancaron una sesión de escritorio completa de NixOS dentro de una máquina virtual: componentes críticos como gnome-shell, mutter y nautilus habían sido procesados por el strip manipulado, y sin embargo no falló ni una sola prueba funcional. El sistema infectado parecía comportarse con total normalidad; y es precisamente esa invisibilidad lo que lo vuelve tan peligroso.

El artículo también analiza un «modo durmiente» (dormancy mode): la puerta trasera puede abstenerse de ejecutar cargas perjudiciales o de seguir propagándose durante el uso ordinario, transmitiéndose en silencio de generación en generación hasta que coincida con un objetivo o disparador predeterminado por el atacante. Esta modalidad latente resulta casi imposible de detectar mediante herramientas diagnósticas convencionales, ya que el sistema responde de forma completamente ordinaria ante cualquier inspección rutinaria.

Una advertencia de hace 42 años que hoy sigue sin escucharse

La conferencia de Thompson en 1984 impulsó décadas de investigación en torno a los «compiladores de confianza». Una de las defensas más destacadas es la Doble Compilación Diversa (Diverse Double-Compiling o DDC), formulada por David A. Wheeler, que contrasta los resultados de compilación cruzando múltiples compiladores independientes. No obstante, en la práctica, las distribuciones Linux convencionales no han implementado este tipo de mecanismos por defecto.

Los debates técnicos en foros como Lobsters revelaron detalles históricos fascinantes: Thompson ya había construido un prototipo plenamente operativo en la época de su discurso; iniciativas como stage0-posix y hex0 en GNU Guix y Nix nacieron con el propósito expreso de contrarrestar esta amenaza construyendo todo desde código fuente a partir de unas pocas decenas de bytes de código máquina (full-source bootstrap); y Russ Cox consiguió en su día el código original de Thompson, lo puso a punto en Unix V6 y creó un entorno web donde cualquiera puede experimentar este ataque de compilador desde el navegador.

Sin embargo, en el terreno pragmático de la ingeniería de sistemas, compilar un sistema operativo completo desde código fuente estricto —eliminando cualquier dependencia de semillas binarias precompiladas— acarrea un coste descomunal en esfuerzo y mantenimiento. Es un precio que la gran mayoría de las distribuciones comerciales y comunitarias aún no están dispuestas a asumir.

La puerta trasera invisible a las auditorías

La conclusión de fondo que arroja esta investigación sacude una convicción muy arraigada: la idea de que «código abierto equivale a seguridad» es un espejismo. Las auditorías exhaustivas de código fuente son capaces de detectar vulnerabilidades y trampas en los repositorios, pero son completamente ciegas ante modificaciones introducidas a nivel binario. Al fin y al cabo, a nadie se le ocurriría sospechar que una simple herramienta pensada para descartar símbolos de depuración esté alterando sibilinamente la cabecera de un archivo ELF.

Ken Thompson demostró en 1984 que, una vez rota la cadena de confianza, la revisión del código fuente no basta para restablecerla. Cuarenta y dos años después, unos investigadores lo han vuelto a demostrar valiéndose de una herramienta mucho más humilde, silenciosa e insospechada: strip.

Mientras las cadenas de inicialización sigan dependiendo de semillas binarias precompiladas, esta brecha continuará abierta. Y el coste de alcanzar una verificación absoluta —el arranque completo desde código fuente— sigue siendo una factura que la industria tecnológica se resiste a pagar.

Enlaces de referencia:

  • Artículo en arXiv 2607.24888
  • Discusión en Lobsters (p5w5j6)
  • Ken Thompson, Reflections on Trusting Trust (1984)