2 puntos por GN⁺ 2024-04-13 | 1 comentarios | Compartir por WhatsApp
  • La puerta trasera de XZ Utils/liblzma se hizo pública el 29 de marzo de 2024 en la lista de correo OSS-security de Openwall, y es muy probable que el objetivo final del atacante haya sido implantar capacidad de ejecución remota de código en sshd, el servidor OpenSSH de distribuciones basadas en systemd
  • La cadena de infección consistió en una inserción multinivel que utilizó archivos de prueba y la infraestructura de compilación del repositorio de XZ; pasando por build-to-host.m4, bad-3-corrupt_lzma2.xz y good-large_compressed.lzma, un archivo objeto malicioso terminaba enlazándose a liblzma durante la compilación
  • XZ 5.6.0 y 5.6.1, que incluían la puerta trasera, se distribuyeron en compilaciones beta y experimentales de algunos proveedores importantes, y CVE-2024-3094 recibió una gravedad de 10 puntos
  • La puerta trasera binaria se carga abusando de IFUNC de GLIBC y de la ruta de llamadas de cpuid, y luego intenta vigilar las conexiones de la máquina infectada enganchando funciones relacionadas con OpenSSL/libcrypto
  • El código malicioso comprueba si se está ejecutando /usr/bin/sshd y una variable de entorno de apagado de emergencia, y dificulta el análisis y la detección mediante procesamiento de cadenas basado en trie, resolución dinámica de símbolos y parcheo en tiempo de ejecución de rtdl-audit

Resumen del incidente y alcance del impacto

  • El 29 de marzo de 2024 se anunció el hallazgo de la puerta trasera de XZ mediante este mensaje en la lista de correo OSS-security de Openwall
  • XZ es una utilidad de compresión integrada en varias distribuciones importantes de Linux
  • El núcleo del riesgo es que liblzma, que incluía la puerta trasera, podía vincularse con sshd, el proceso servidor de OpenSSH, en algunas distribuciones basadas en systemd
    • Ubuntu, Debian y RedHat/Fedora Linux parchean OpenSSH para que use funciones de systemd, por lo que depende de esta biblioteca
    • Se considera que Arch Linux y Gentoo no se vieron afectados
  • Es muy probable que el objetivo final del atacante haya sido añadir una capacidad de ejecución remota de código en sshd que nadie más pudiera usar
  • A diferencia de otros ataques a la cadena de suministro centrados en un único parche malicioso, paquetes falsos o typosquatting, este caso se parece más a una operación multinivel que estuvo a punto de lograr comprometer servidores SSH en todo el mundo

Cómo se introdujo la puerta trasera

  • La puerta trasera de liblzma se insertó en dos niveles usando a la vez el proceso de compilación y archivos de prueba
    • Se modificó el código fuente de la infraestructura de compilación que genera el paquete final añadiendo build-to-host.m4
    • Durante la compilación se extraían componentes binarios y scripts ocultos dentro de archivos de casos de prueba
  • El flujo de infección giró en torno a tres archivos
    • build-to-host.m4: script de compilación que extrae el script de la siguiente etapa
    • bad-3-corrupt_lzma2.xz: archivo de prueba con un script de shell oculto
    • good-large_compressed.lzma: archivo de prueba con un objeto binario malicioso oculto
  • El componente binario malicioso extraído se enlazaba con la biblioteca legítima durante la compilación y podía terminar distribuido en repositorios Linux
  • Proveedores importantes distribuyeron este componente malicioso en compilaciones beta y experimentales
  • A la intrusión en XZ Utils se le asignó CVE-2024-3094, con una gravedad máxima de 10 puntos

Cronología principal

  • 19 de enero de 2024: el nuevo mantenedor jiaT75 migra el sitio web de XZ a GitHub Pages
  • 15 de febrero de 2024: build-to-host.m4 se añade a .gitignore
  • 23 de febrero de 2024: se agregan dos “archivos de prueba” con etapas del script malicioso
  • 24 de febrero de 2024: se lanza XZ 5.6.0
  • 26 de febrero de 2024: entra un commit en CMakeLists.txt que interfiere con la función de seguridad Landlock
  • 4 de marzo de 2024: la puerta trasera provoca problemas relacionados con Valgrind
  • 9 de marzo de 2024: se actualizan los dos archivos de prueba, se modifica la función CRC y el problema de Valgrind queda “corregido”
  • 9 de marzo de 2024: se lanza XZ 5.6.1
  • 28 de marzo de 2024: se descubre el bug y se notifica a Debian y RedHat
  • 28 de marzo de 2024: Debian revierte XZ 5.6.1 a la versión 5.4.5-0.2
  • 29 de marzo de 2024: se publica el correo en la lista OSS-security
  • 29 de marzo de 2024: RedHat confirma que se distribuyó XZ con puerta trasera en Fedora Rawhide y Fedora Linux 40 beta
  • 30 de marzo de 2024: Debian detiene las compilaciones e inicia el procedimiento de recompilación
  • 2 de abril de 2024: el desarrollador principal de XZ reconoce el incidente de la puerta trasera

Las 3 etapas de la cadena de infección

  • Etapa 1: build-to-host.m4 modificado

    • Los lanzamientos del repositorio oficial de GitHub de XZ incluían los archivos de prueba maliciosos, pero al principio eran inofensivos porque no tenían oportunidad de ejecutarse
    • El código malicioso que iniciaba la infección parece haber estado incluido en los lanzamientos ofrecidos desde xz[.]tukaani.org, controlado por jiaT75
    • La mayoría de las distribuciones usaban esa URL, y los lanzamientos descargados incluían el archivo build-to-host.m4 con el código malicioso
    • build-to-host.m4 se ejecuta durante la compilación, corrige con tr los datos “rotos” de bad-3-corrupt_lzma2.xz y luego los descomprime con xz -d
    • El resultado de la descompresión contiene un script de shell que más adelante se ejecutará con /bin/bash
  • Etapa 2: script de shell insertado

    • El script insertado por el archivo .m4 malicioso comprueba si se está ejecutando en una máquina Linux y dentro del proceso de compilación previsto
    • La siguiente etapa se ejecuta usando good-large_compressed.lzma
    • Este archivo está comprimido normalmente con XZ, pero los datos descomprimidos contienen datos basura
    • El script extrae los datos ejecutando con eval una tubería de head
    • Cada comando head omite los siguientes 1024 bytes o extrae los siguientes 2048 bytes o 724 bytes
    • En total se extraen 33,492 bytes
    • tail conserva los últimos 31,265 bytes del archivo e ignora el resto
    • Después, tr aplica sustituciones básicas para desofuscar, y un segundo comando de XZ descomprime los bytes transformados como un flujo raw lzma y envía el resultado al shell
  • Etapa 3: extracción del objeto de la puerta trasera

    • El script de shell de la última etapa comprueba varias condiciones para confirmar que se ejecuta en el entorno esperado
    • Verifica si el proyecto está configurado para usar IFUNC
    • Verifica si se compila con GCC
    • Luego comprueba si existen en el proyecto ciertos archivos específicos que el script usará
    • Esta etapa extrae un archivo objeto oculto en otro offset de good-large_compressed.lzma
    • El procedimiento de extracción ejecuta varios comandos en secuencia y pasa la salida de cada uno como entrada del siguiente
    • Extrae good-large_compressed.lzma con la herramienta XZ
    • Usa eval $i y varias llamadas a head
    • Descifra los datos binarios con un algoritmo personalizado similar a RC4
    • Vuelve a extraer con XZ el archivo comprimido ya descifrado
    • Elimina algunos bytes del principio y guarda el resultado como liblzma_la-crc64-fast.o
    • Por último, el script modifica la función is_arch_extension_supported en el archivo crc_x86_clmul.h de liblzma
    • Sustituye la llamada a __get_cpuid por _get_cpuid, quitando un guion bajo
    • Este cambio permite que el objeto de la puerta trasera se enlace a la biblioteca

Cómo se carga la puerta trasera binaria

  • El código original de XZ tiene funciones especiales para calcular CRC, lzma_crc32 y lzma_crc64
  • Ambas funciones se almacenan como tipo IFUNC de GLIBC en la tabla de símbolos ELF
    • IFUNC permite al enlazador dinámico elegir de forma dinámica qué función usar al cargar una biblioteca compartida
    • XZ usa esta función para decidir si debe usar funciones CRC optimizadas después de comprobar capacidades modernas del procesador como CLMUL, SSSE3 y SSE4.1
  • Para comprobar las capacidades del procesador hace falta la instrucción cpuid, y se llama al wrapper __get_cpuid proporcionado por GLIBC
  • Cuando el script malicioso cambia __get_cpuid por _get_cpuid, la llamada del código queda enlazada al símbolo _get_cpuid dentro del archivo objeto de la puerta trasera
  • El código inicial de la puerta trasera se invoca dos veces porque lzma_crc32 y lzma_crc64 usan la misma función modificada _get_cpuid
    • Usa un contador simple para comprobar si ya se ejecutó
    • Cuando IFUNC de lzma_crc64 llama a _get_cpuid y el contador vale 1, comienza la etapa que redirige al punto de entrada final

Comportamiento en tiempo de ejecución y objetivos del hooking

  • La puerta trasera inicializa estructuras con información clave del proceso en ejecución
  • Encuentra la dirección de la Global Offset Table (GOT) mediante offsets codificados y localiza dentro de ella el puntero cpuid
  • Después reemplaza ese puntero por la función maliciosa principal para invocarla como si estuviera llamando a cpuid
  • El objetivo principal es enganchar funciones específicas para vigilar conexiones entrantes en la máquina infectada
  • Las funciones objetivo están relacionadas con libcrypto
    • RSA_public_decrypt: se usa al descifrar texto cifrado firmado con una clave privada
    • EVP_PKEY_set1_RSA: se usa al establecer una clave RSA para un contexto específico
      • No aparece en versiones recientes del servidor SSH, pero sí se usa en una herramienta independiente de generación de claves SSH
    • RSA_get0_key: se usa al obtener una clave RSA
  • El proceso de hooking requiere acceder a varias estructuras internas y manipular estructuras específicas del proceso, y el código malicioso realiza comprobaciones adicionales para evitar el análisis

Comprobaciones del entorno de ejecución y técnicas de evasión de análisis

  • Verificación de sshd y apagado de emergencia

    • La puerta trasera primero analiza el enlazador dinámico ld-linux para resolver direcciones de símbolos dinámicamente
    • Comprueba si el entorno de ejecución actual cumple sus criterios
    • Verifica si el proceso actual es /usr/bin/sshd
    • Verifica si existe un apagado de emergencia
    • El nombre del proceso actual se extrae de argv[0]
    • Analiza todas las variables de entorno del proceso y comprueba si coinciden con valores de su tabla interna de cadenas
    • Si hay una variable de entorno coincidente o el proceso no es sshd, el código malicioso deja de ejecutarse
    • La única variable de la tabla interna, yolAbejyiejuvnup=Evjtgvsh5okmkAvj, funciona en este contexto como apagado de emergencia
  • Procesamiento de cadenas basado en trie

    • Una característica de la puerta trasera es que usa una sola estructura trie para operaciones con cadenas
    • En lugar de comparar directamente constantes como nombres de funciones o usar hashes de cadenas, comprueba si el resultado de la búsqueda en el trie coincide con un valor constante específico
    • El valor mágico del encabezado ELF hace que el trie devuelva 0x300
    • El nombre de función system coincide con el valor de retorno 0x9F8
    • El trie no solo se usa para comparaciones, sino también para encontrar cadenas dentro del binario anfitrión
    • Por ejemplo, las funciones que usan punteros a cadenas como ssh-2.0 buscan esas cadenas dentro del binario anfitrión para no dejar datos sospechosos en el cuerpo de la puerta trasera
    • La implementación usa una máscara de bits de 16 bytes
    • Cada mitad corresponde a los rangos de bytes de entrada 0x00-0x3F y 0x40-0x7F
    • Los nodos hoja del trie ocupan 2 bytes; 3 bits se usan como banderas y el resto se reserva para el valor o la ubicación del siguiente nodo

Resolución de símbolos y hooking de rtdl-audit

  • Rutinas de resolución de símbolos

    • La puerta trasera incluye al menos 3 rutinas de resolución de símbolos para localizar estructuras ELF Symbol
    • Todas las funciones de resolución reciben como entrada una clave a buscar en el trie
    • Una de las rutinas recorre todos los símbolos para encontrar el que tenga la clave deseada y, si lo encuentra, devuelve la estructura Elf64_Sym
    • Esa estructura luego se usa para rellenar estructuras internas de la puerta trasera y guardar los punteros a función necesarios
    • Este proceso se parece a las rutinas de hashing de API comunes en amenazas de Windows
    • Después la puerta trasera busca numerosas funciones de OpenSSL libcrypto que usará en su rutina de cifrado
    • Lleva la cuenta de cuántas funciones encontró y resolvió, y usa ese valor para decidir si continúa o se detiene
  • Allocator falso que abusa de lzma_alloc

    • Otro resolvedor de símbolos abusa de lzma_alloc, una función de liblzma
    • lzma_alloc ayuda a asignar memoria de forma eficiente usando el allocator predeterminado malloc o un allocator personalizado
    • En la puerta trasera de XZ, esta función actúa como otro resolvedor de símbolos por medio de un allocator falso
    • El parámetro que normalmente se usaría como “tamaño de asignación” se usa en realidad como la clave de símbolo dentro del trie
    • Este truco busca dificultar el análisis de la puerta trasera
    • La puerta trasera resuelve símbolos dinámicamente en tiempo de ejecución, sin limitarse a resolver todos de una vez o solo cuando los necesita
    • Entre los símbolos que resuelve hay desde funciones legítimas de OpenSSL hasta system, que ejecuta comandos en la máquina
  • Parcheo en tiempo de ejecución de rtdl-audit

    • La puerta trasera usa la función rtdl-audit del enlazador dinámico para enganchar funciones
    • Normalmente, rtdl-audit permite que un desarrollador cree una biblioteca compartida personalizada para recibir notificaciones de eventos del enlazador como la resolución de símbolos
    • En lugar de crear una biblioteca compartida aparte, la puerta trasera de XZ parchea en tiempo de ejecución la interfaz predeterminada ya registrada en memoria y secuestra la rutina de resolución de símbolos
    • La estructura maliciosa audit_iface, almacenada en la variable global dl_audit del área de memoria del enlazador dinámico, contiene la dirección del callback symbind64
    • Cuando el enlazador dinámico invoca este callback, toda la información de símbolos pasa a control de la puerta trasera, y para las funciones objetivo devuelve direcciones maliciosas, logrando así el hooking
    • Las direcciones de dl_audit y dl_naudit se obtienen desensamblando las funciones dl_main y dl_audit_symbind_alt
    • La puerta trasera incluye un desensamblador interno mínimo para decodificar instrucciones, y lo usa ampliamente al buscar valores específicos como direcciones *audit

Distribuciones confirmadas con puerta trasera e información de detección

  • Distribuciones de código fuente con puerta trasera

    • xz-5.6.0
      • MD5: c518d573a716b2b2bc2413e6c9b5dbde
      • SHA1: e7bbec6f99b6b06c46420d4b6e5b6daa86948d3b
      • SHA256: 0f5c81f14171b74fcc9777d302304d964e63ffc2d7b634ef023a7249d9b5d875
    • xz-5.6.1
      • MD5: 5aeddab53ee2cbd694f901a080f84bf1
      • SHA1: 675fd58f48dba5eceaf8bfc259d0ea1aab7ad0a7
      • SHA256: 2398f4a8e53345325f44bdd9f0cc7401bd9025d736c6d43b372f4dea77bf75b8
  • Artefactos principales analizados

    • bad-3-corrupt_lzma2.xz: 86fc2c94f8fa3938e3261d0b9eb4836be289f8ae
    • build-to-host.m4: b4dd2661a7c69e85f19216a6dbbb1664
    • good-large_compressed.lzma: 540c665dfcd4e5cfba5b72b4787fec4f
    • liblzma_la-crc64-fast.o: 212ffa0b24bb7d749532425a46764433
  • Bibliotecas conocidas con puerta trasera

    • Debian Sid liblzma.so.5.6.0
      • MD5: 4f0cf1d2a2d44b75079b3ea5ed28fe54
      • SHA1: 72e8163734d586b6360b24167a3aff2a3c961efb
      • SHA256: 319feb5a9cddd81955d915b5632b4a5f8f9080281fb46e2f6d69d53f693c23ae
    • Debian Sid liblzma.so.5.6.1
      • MD5: 53d82bb511b71a5d4794cf2d8a2072c1
      • SHA1: 8a75968834fc11ba774d7bbdc566d272ff45476c
      • SHA256: 605861f833fc181c7cdcabd5577ddb8989bea332648a8f498b4eef89b8f85ad4
  • Nombres de detección

    • Los productos de Kaspersky detectan los objetos maliciosos relacionados con el ataque como HEUR:Trojan.Script.XZ y Trojan.Shell.XZ
    • Kaspersky Endpoint Security for Linux detecta el código malicioso en la memoria del proceso SSHD como MEM:Trojan.Linux.XZ como parte de la tarea Critical Areas Scan
    • La regla Yara proporcionada es liblzma_get_cpuid_function, para encontrar la función maliciosa get_cpuid relacionada con CVE-2024-3094

1 comentarios

 
GN⁺ 2024-04-13
Opiniones de Hacker News
  • Esta frase en realidad parece minimizar lo que ocurrió.
    Más aterrador que el aspecto técnico del backdoor es la cantidad y el nivel de ingeniería social. El backdoor fue el producto final, y se pudo introducir porque para ese momento todo el proyecto xz ya llevaba mucho tiempo bajo el control de actores maliciosos, es decir, “Jia Tan” y su entorno. Llevaron a cabo una guerra psicológica contra el mantenedor durante más de un año, y ni el mantenedor ni nadie más se dio cuenta.
    Es algo digno de una novela de espionaje, y si algo así es posible, uno se pregunta qué estará pasando ahora mismo en otros proyectos.
    El mismo modo de pensar también se ve en el código del backdoor. No se trataba simplemente de parecer inofensivo, sino de construir activamente una narrativa sobre lo que supuestamente hacía, mediante mensajes de commit, comentarios, nombres de variables, elección de comandos, etc., mientras en realidad hacía algo completamente distinto. La estructura estaba pensada para que quien revisara primero el código dudara de su propia comprensión, luego sospechara de un bug y solo mucho después sospechara de mala intención.

    • Es realmente increíble. Puede sonar a teoría conspirativa, pero también me pregunto si no hubo una operación psicológica en el mundo real para hacer que el autor original ya no pudiera dedicarle tiempo y finalmente cediera la propiedad a un mal actor.
      Espero que alguna agencia de inteligencia esté investigando este caso más a fondo.
    • Ojalá tomemos esto como lección. En realidad pasan muchas cosas. Entre las agencias financiadas por gobiernos de todo el mundo y las organizaciones del mercado negro, hay muchas cuyo trabajo es conseguir backdoors, y tienen fondos de sobra. Ese es su trabajo.
      Me frustra ver que en cada hilo de HN sobre backdoors se niega esta posibilidad tratándola como paranoia o como cosa de sombrero de papel aluminio. Se la trata como si no ocurriera, pero este es solo un caso concreto que fue atrapado, y hay incontables más que aún no lo han sido.
      En este caso, al tratarse de un proyecto open source, descubrirlo era relativamente más fácil, y aun así hubo suerte. Ahora pensemos en los productos de código cerrado: insertar un backdoor se reduce a infiltrarse en una organización o presionarla. Estas cosas pasan con frecuencia. Nadie quiere creerlo, pero son comunes. Cualquiera que haya trabajado en una empresa de infraestructura tecnológica tendrá algunas historias. Es difícil contarlas por NDA o por razones peores, pero realmente ocurren.
    • Estoy totalmente de acuerdo en que hace que quien revisa el código dude de su propia comprensión. La manipulación, meticulosidad, paciencia y persistencia invertidas en esto son asombrosas.
      Puede ser el resultado de la obsesión de alguien, o el trabajo de una empresa privada de seguridad o de un actor estatal que hace este tipo de cosas contra varios proyectos como si fuera una jornada laboral de 9 a 5.
  • Es natural que hasta ahora la atención se haya centrado en si el backdoor funcionaba y en cómo lograba sus objetivos.
    Aun así, me gustaría ver un análisis más profundo de los errores y de las partes sobrediseñadas. En la entrevista de Bryan Cantril [1], Andrés dice que esto parece un componente de backdoor prefabricado, no necesariamente diseñado con pleno conocimiento de cómo iba a distribuirse, y que por eso tiene muchas partes tontas. Por ejemplo, la consulta a la tabla de símbolos que lo llevó a investigar.
    Del mismo modo, también me intriga por qué recortaba 48 bytes con RC4 [2].
    Me gustaría escuchar cómo podrían haberlo hecho mejor si hubieran tenido más tiempo o un mejor equipo, o en qué se equivocaron más gravemente.
    [1] https://youtu.be/jg5F9UupL6I?si=gvXsYFXgagkGOMd4
    [2] https://twitter.com/matthew_d_green/status/17744729080201014...

  • Si entiendo bien, una medida de endurecimiento útil sería hacer que cada biblioteca de enlace dinámico tenga su propia GOT y, cuando termine el enlazado dinámico, marcar la tabla como solo lectura. Es decir, impedir que se puedan parchear entradas ifunc del otro lado al cruzar límites dinámicos.
    Esto podría mejorar la seguridad de la cadena de suministro del código que se enlaza en algún lugar pero no se ejecuta.
    Más aún, quizá sería mejor implementar ifunc de forma declarativa, para que cada biblioteca enlazada no pueda provocar ejecución arbitraria de código. Por compatibilidad hacia atrás, implementarlo ahora sería difícil, pero a largo plazo parece posible introducirlo por niveles. Por ejemplo, si una biblioteca se compila con un bit de funcionalidad de “ifunc de enlace declarativo”, el enlazador dinámico podría fallar la ejecución cuando no todas las bibliotecas enlazadas tengan la misma bandera de funcionalidad.

    • Desde otro ángulo, el problema es el sistema de build.
      Hoy, la mayoría de las compilaciones de bibliotecas ejecutan scripts muy complejos y opacos que requieren un entorno Turing completo. Eso les da a los atacantes una superficie de ataque interminable, y si el proceso de build es secuestrado, se abre una oportunidad.
      Ayudaría pasar a un proceso de build declarativo en el que el ejecutor sea solo una máquina de estados limitada. También valdría la pena considerar exigir que todos los bloques de código fuente sean reproducibles.
    • Sí y no, pero en general no. Ese enfoque impediría usar ifunc simplemente de esta forma, pero lo importante es que el autor de este backdoor pudo inyectar código arbitrario en una biblioteca que entra en el espacio de direcciones de un proceso sensible.
      A partir de ese punto, todas las defensas quedan anuladas. Si quiere, puede volver a mapear la GOT como escribible, y aunque ese comportamiento pueda detectarse como “sospechoso” o el sistema operativo pueda bloquear la transición, el código inyectado puede desviar el flujo de control de cientos de otras maneras. Lectura/escritura arbitraria, ejecución de código, todo es posible. No hay mitigación de seguridad que pueda impedir una intrusión en esta etapa. Si quiere, puede exfiltrar la clave privada y enviársela directamente al atacante, o abrir una shell. Intentar diseñar protección en esta etapa es inútil.
    • Marcar la tabla como solo lectura después de completar el enlazado dinámico lamentablemente no funciona. El enlazado dinámico es diferido, así que no existe un momento en que “termine”.
      El puntero correcto a la función se carga la primera vez que se llama y se inserta en la tabla en lugar del stub, y ese momento puede estar arbitrariamente lejos en el futuro. De hecho, en grandes ecosistemas de bibliotecas como las apps gtk, la mayoría de las funciones enlazadas nunca se llaman.
    • Si compilas para la arquitectura host, puedes desactivar ifunc por completo sin pérdida. En Gentoo es común compilar con -march=native, y desactivar ifunc es sencillo configurando -multiarch en las USE flags de glibc. No he visto efectos negativos.
    • ¿Existe algún lenguaje de programación que pueda ejecutar el import de bibliotecas en un sandbox?
  • Sobre las primeras 3 etapas, este artículo no agrega mucho respecto de lo que se supo en las últimas 2 semanas. Es más bien un buen resumen con diagrama de flujo.
    Pero la parte donde analizan el binario con ese nivel de detalle sí parece nueva.
    ¿Cómo se habrá generado el código fuente que aparece ahí? ¿Corrieron un desensamblador, entendieron qué hacía el código y luego cambiaron todos los nombres por nombres descriptivos? Parece un logro considerable para haberlo hecho en 2 semanas.

    • El autor es GReAT.
      Global Research & Analysis Team, Kaspersky Lab
      https://securelist.com/author/great/
      Como quien escribió el artículo parece ser el equipo de análisis de malware de Kaspersky Lab, es muy probable que sean bastante buenos en ingeniería inversa de binarios.
    • La herramienta usada en las capturas blancas es IDA Pro, un descompilador.
      https://hex-rays.com/ida-pro/
  • Lo que realmente me da curiosidad es qué causó exactamente la demora inicial de SSH que disparó la investigación de xz. ¿Alguien lo averiguó?

    • Realiza una operación ECC adicional por conexión, pero eso no debería tomar 500 ms en una CPU moderna.
      Según quienes hicieron ingeniería inversa del código, el mensaje de comando también debía vincularse con la clave de host SSH. Así que, si la clave de host era RSA, quizá también se ejecutaba una operación adicional de descifrado RSA por conexión.
      Eso sí parecería suficiente para explicar la demora.
    • Puede que haya sido intencional.
      Es una forma fácil de saber desde afuera si un servidor está infectado, sin intentar primero inyectar código.
  • Los autores conocen muy a fondo las estructuras internas de glibc. Es el tipo de cosas que solo se saben si uno está metido hasta el cuello en el código fuente, y hay muchas técnicas nuevas.
    El parser ELF y el desensamblador personalizados son tan complejos que cuesta imaginar que ese código no se haya usado antes en otro lado, o que no se vaya a reutilizar en el futuro.
    Me pregunto si este caso recibirá el nivel de investigación seria que merece, pero no parece probable.

  • ¿Alguien analizó el bug del backdoor que terminó exponiendo todo esto al causar el error de Valgrind y la lentitud en SSH?

    • Al parecer era una escritura de memoria claramente incorrecta: https://www.mail-archive.com/valgrind-users@lists.sourceforg...
      La “corrección” de Valgrind fue desactivar ifunc, y como resultado se desactivó el backdoor y desapareció el error.
      Hasta donde sé, la lentitud venía de todas las búsquedas de símbolos e instrucciones que hacía el backdoor.
  • Mirándolo como giro inesperado, considerando el esfuerzo que puso el atacante para evitar la detección en scripts y código, todo este proyecto podría ser una distracción o un plan de respaldo mientras se ejecutaban varios intentos en paralelo.
    ¿Cómo se puede ir un paso adelante de cosas como esta? ¿Que la comunidad se concentre en SSHD afectará a otras partes del sistema? ¿A otros aspectos técnicos o sociales?
    El sombrero de papel aluminio es divertido.

    • No soy optimista. Casi nadie audita realmente el contenido de los binarios flatpak de Flathub. ¿De verdad fueron compilados desde el código fuente? Es más bien que el autor afirma que sí. Quizá ni siquiera haga falta un mecanismo de entrega tan sofisticado como el de este backdoor.
    • Se podría escribir todo uno mismo y contar con un equipo dedicado de desarrolladores verificados.
      O comprar software cerrado de lugares como Microsoft y esperar que tengan los recursos y la voluntad de revisar el código con más rigor.
      Y siempre está el enfoque de tener un gran equipo de operaciones de seguridad que detecte actividad de red extraña e intentos de escalamiento de privilegios.
    • Como forma de ir un paso adelante de backdoors similares, se me ocurre envolver el tráfico de sshd en un túnel spiped. Spiped se compila desde el código fuente y se enlaza estáticamente, y su última versión estable es de 2021.
    • Mi idea de sombrero de papel aluminio es desconfiar de los contribuidores de código abierto. No por venir de cierto país, ni porque parezca que nadie los haya conocido en persona.
      Pero, de ahora en adelante, un contribuidor sin historial ni huella fuera del proyecto en el que trabaja debería verse como una señal de alerta.
    • No hace falta sombrero de papel aluminio. Los proyectos FOSS han tenido backdoors desde antes de volverse famosos; la diferencia esta vez es que lo hace un actor patrocinado por un Estado.
      Grupos antiguos como GOBBLES, ADM, ac1db1tch3z y ~el8 también hacían cosas así, igual que “investigadores de seguridad” privados como isec.pl.
      Esto es un problema ahora porque los actores estatales están explotando el capitalismo corporativo que creó una era en la que proyectos base se sostienen con salarios bajos. Los actores maliciosos tienen recursos prácticamente ilimitados para cumplir sus objetivos.
      Eso, al final, generó la demanda y el surgimiento de organizaciones como NSO y Zerodium.
      Antes de eso, los exploits y backdoors casi no tenían valor, y los hackers esperaban patrocinio o contratación de empresas como Qualys.
  • Vi varias veces los análisis de Google sobre hacks de vulnerabilidades de día cero y también eran increíblemente impresionantes, pero este hack probablemente quede entre los más grandes de la historia.

  • Vi que el repositorio de xz volvió a GitHub, y Lasse junto con un nuevo contribuidor lo estaban ordenando. Eliminaron el soporte de ifunc y commitearon al repositorio el código de generación de archivos de prueba para poder crear archivos de prueba sin blobs. Parece que están trabajando en una buena dirección.