Del backdoor de SSH por xz/liblzma

1 de abril de 2024 • fjbalon

Como bien se sabe, este no es un blog de noticias. Ni me interesan por regla común, ni mucho menos quiero ser partícipe o servidor de ellas. Este es un blog que se centra en el mundo de las ideas, de la técnica, de lo permanente, de lo relativamente inmutable. No obstante, me gustaría hacer una noble excepción, no para producir ni informar sobre la noticia, sino para analizar la portentosa técnica que encierra.

Y me refiero a la noticia, que habréis visto en diversos foros de GNU/Linux y feudos de noticias técnicas; y no habréis visto en ningún medio de masas, del intento de backdoor en SSH a través de la biblioteca de xz/liblzma.

He considerado que la complejidad del ataque, de una precisión y técnica sobresaliente y digna de un gran intelecto, merece unas letras y un breve análisis.

La biblioteca de lzma comprometida activaría, a través de un enlace de openssh, a sd_notify (systemd notify) para obtener código oculto en liblzma. Así, podría crear una puerta trasera a cualquier servidor SSH de Debian/Fedora/Ubuntu.

Aparentemente, ni siquiera openssh-selinux sería seguro en esas condiciones (glibc, x86-64, fuente de tarball preconfigurada de Github 5.6.0 y 5.6.1, systemd empaquetado, OpenSSH, RPM o DEB, con llamadas habilitadas a systemd a través de openssh.service). Si la fuente se creó a partir de git con autoconf/make limpio nativo, el código malicioso no se habría incluido. Los sistemas musl (Alpine, Gentoo, OpenWRT o Void) no tienen nada de qué preocuparse, simplemente porque ni siquiera pueden compilar sd_notify.

Una cosa muy llamativa es cómo gran parte de la comunidad cruzada contra systemd criticaba a zstd, defendiendo en contraposición al amigable xz. Sospechaban que el propio zstd (o Zstandard, que para quien no lo conozca, es un algoritmo de compresión desarrollado por Facebook para Linux), tenía el riesgo de ser un caballo de Troya para la seguridad y el cifrado, siendo que incluso zstd se construye, mayoritariamente, con la biblioteca lzma habilitada...

«Es sólo un algoritmo de compresión, no se puede usar para explotar la seguridad de un sistema, es imposible» he llegado a leer por feudos del Internet. Pues este backdoor nos ha demostrado que es totalmente posible.

Buena noticia, por lo tanto, para Slackware y otras distros no-systemd: hasta donde los expertos en Debian, Fedora, Arch o Ubuntu han llegado, se necesita necesariamente systemd para 'energizar' la puerta trasera, específicamente un gancho utilizado por Debian para construir openssh de cierta manera para que systemd/dbus/sd-bus/sd-notify ejecute código malicioso para obtener material de un blob de lzma para modificar los binarios en ejecución para abrir la puerta trasera. Es una genialidad, se mire por donde se mire. Y los cruzados contra systemd siguen teniendo, pues, razón.

Este complejísimo ataque sobre librerías y códigos abiertos -apertura que permite a la comunidad, o a cualquiera que entienda, monitorizar los commits y evolución del código- ha llevado prácticamente 2 años a través de la librería xz en Github (llevado a cabo principalmente por la cuenta JiaT75 y otras de dudosa legitimidad), para afectar como decíamos a liblzma, el vector de ataque. Tenga en cuenta el lector, que esta gran complejidad para insertar un backdoor es precisamente por la naturaleza del código abierto, en código cerrado probablemente otro gallo cantaría, incluso para la detección.

Pero incluso la detección tiene tela: Andres Freund, un trabajador de Microsoft (valga el chiste, salvados por Microsoft, xd) mientras realizaba tests de rendimiento notó que el demonio de SSH tardaba 500ms más de lo habitual... ¡Increible!


After observing a few odd symptoms around liblzma (part of the xz package) on
Debian sid installations over the last weeks (logins with ssh taking a lot of
CPU, valgrind errors) I figured out the answer:

The upstream xz repository and the xz tarballs have been backdoored.

[...]

With the backdoored liblzma installed, logins via ssh become a lot slower.

time ssh nonexistant@localhost

before:
nonexistant@localhost: Permission denied (publickey).

before:
real	0m0.299s
user	0m0.202s
sys	0m0.006s

after:
nonexistant@localhost: Permission denied (publickey).

real	0m0.807s
user	0m0.202s
sys	0m0.006s
Fuente: https://lwn.net/ml/oss-security/20240329155126.kjjfduxw2yrlxgzm@awork3.anarazel.de/

Dicen que ejecutando strings `which xz` | grep "(XZ Utils)" detectamos si contamos con una versión seguta (<5.6.0), pero sólo cerciórese en caso de cumplir los requisitos para haber sido afectado por el backdoor.