https://www.youtube.com/watch?v=G1RGpFxPD-w

В конце марта 2024 года в экосистеме Open Source была обнаружена одна из самых изощрённых атак на цепочку поставок (supply chain attack) за всю историю IT. Неизвестная группа под псевдонимом Jia Tan внедрила бэкдор в критически важную библиотеку liblzma (проект XZ Utils), попытавшись получить скрытый root-доступ к миллионам Linux-серверов по всему миру. CVE-2024-3094 получил максимальную оценку CVSS 10.0 (Critical).

1. Анатомия внедрения (2021–2024)

Атака планировалась годами и строилась на социальной инженерии, долгосрочном внедрении в доверие и технической подготовке инфраструктуры.

  • Внедрение агентской учётной записи (2021–2023). Аккаунт Jia Tan (GitHub: JiaT75) появился в 2021 году. Он начал вносить полезные и легитимные правки не только в XZ Utils, но и в смежные проекты (в том числе подозрительный коммит в libarchive, заменявший безопасную функцию на небезопасную). К февралю 2022 года Jia Tan уже коммитил в XZ. Параллельно вносились изменения, которые позже оказались полезны для атаки: поддержка GNU IFUNC (через патчи от «Hans Jansen»), отключение Landlock sandbox (через точку в CMake-проверке, из-за которой проверка всегда падала), обновления CI и инфраструктуры релизов.
  • Давление на мейнтейнера. Сетка фейковых аккаунтов (Jigar Kumar, Dennis Ens и другие) систематически критиковала бессменного автора проекта Лассе Коллина (Lasse Collin) за медленную разработку и «выгорание». Под давлением Коллин передал Jia Tan права соавтора и доступ к релизам (примерно в конце 2022 — начале 2023). Jia Tan постепенно взял на себя контроль над tarball-релизами — критически важный момент, потому что бэкдор жил именно в релизных архивах, а не в Git-истории.
  • Закладка кода (февраль–март 2024). В версии 5.6.0 (24/26 февраля 2024) и 5.6.1 (9 марта 2024) был вшит вредоносный код. Он не находился в открытом исходном коде на GitHub. Вместо этого:
  • В репозиторий были добавлены два бинарных тестовых файла: tests/files/bad-3-corrupt_lzma2.xz и tests/files/good-large_compressed.lzma. Они выглядели как обычные «плохие»/большие тестовые данные для проверки обработки повреждённых LZMA-потоков и не использовались ни в одном реальном тесте.
  • В релизные tarball (но не в Git) был добавлен модифицированный m4/build-to-host.m4. Этот файл был добавлен в .gitignore, чтобы его не было видно в обычном исходнике.
  • Во время ./configure + make (при сборке через dpkg/rpm на x86-64 Linux с glibc + GCC) скрипт из build-to-host.m4 активировался.

Техническая цепочка извлечения payload (многостадийная обфускация):

1. build-to-host.m4 ищет файл по сигнатуре #{4}[[:alnum:]]{5}#{4}$ и находит bad-3-corrupt_lzma2.xz.
2. Выполняется цепочка: sed "r\n" ... | tr "\t \-_" " \t_\-" | xz -d. tr восстанавливает «сломанный» заголовок, xz -d распаковывает Stage 1 — bash-скрипт, начинающийся с ####Hello####.
3. Stage 1 проверяет окружение (uname -a должен быть Linux, архитектура x86_64, наличие определённых файлов CRC и т.д.). Затем он извлекает из good-large_compressed.lzma следующий слой:
xz -dc ... | eval $i | tail -c +31265 (или +31233) | tr "\5-\51\204-\377..." "\0-\377" | xz -F raw --lzma1 -dc | /bin/sh
Здесь head/tail отбрасывают мусор, tr делает RC4-подобную/XOR-деобфускацию, второй xz даёт Stage 2 — ещё один скрипт.
4. Stage 2 компилирует/извлекает готовый объектный файл liblzma_la-crc64-fast.o (prebuilt ELF-объект с бэкдором) и подменяет его в процессе линковки. Одновременно правится crc_x86_clmul.h / crc64_fast.c: вызов __get_cpuid заменяется на _get_cpuid (убирается один underscore). Это критично для последующего hijack.

В результате в финальный liblzma.so попадает вредоносный объект, а IFUNC-резолверы crc32_resolve / crc64_resolve начинают указывать на вредоносный код.

2. Механизм работы бэкдора

Целью был перехват управления демоном OpenSSH (sshd).

Цепочка зависимостей (ключевой вектор):
OpenSSH сам по себе не зависит от liblzma. Однако многие дистрибутивы (Debian, Ubuntu, Fedora, Red Hat и производные) патчат OpenSSH для поддержки sd_notify из systemd. libsystemd зависит от liblzma. Поэтому при запуске sshd через systemd библиотека liblzma загружается в адресное пространство процесса.

Runtime-механизм (IFUNC + GOT/PLT hijack):

1. glibc IFUNC (GNU Indirect Function) позволяет выбирать реализацию функции во время загрузки shared-библиотеки (обычно для CPU-specific оптимизаций: AVX, CLMUL и т.д.). Бэкдор подменяет резолверы crc64_resolve / crc32_resolve.
2. Когда вызывается _get_cpuid (вместо легитимного __get_cpuid), вредоносный код устанавливает audit-hook (через механизм rtdl-audit / dl_audit) и ждёт загрузки символов OpenSSH/OpenSSL.
3. При появлении RSA_public_decrypt@plt (или связанного символа) бэкдор переписывает запись в GOT/PLT, подменяя указатель на собственную функцию.
4. При SSH public-key authentication клиент передаёт RSA-структуру. Бэкдор смотрит на поле modulus N (полностью контролируется клиентом):

  • Первые ~16 байт используются для вычисления «номера команды» (0–3) через простую арифметику с magic-константами.
  • Последние ~240 байт расшифровываются ChaCha20 с захардкоженным ключом (начинается с 0a 31 fd 3b 2f 1f c6 92 ...).
  • Подпись проверяется по захардкоженному Ed448 (иногда в ранних анализах упоминали Ed25519) публичному ключу атакующего. Без правильного приватного ключа бэкдор молчит и передаёт управление оригинальной функции.

5. В зависимости от команды:

  • 0x01 — обход аутентификации (root login).
  • 0x02 — выполнение произвольной shell-команды через system().
  • 0x03 — выполнение команды с заданными UID/GID.
  • Дополнительно могли закрывать pre-auth сессию.

Бэкдор активировался только при выполнении ряда условий (x86-64, glibc, сборка через dpkg/rpm, запуск sshd из systemd и т.д.). Это сильно ограничивало «случайное» срабатывание и затрудняло обнаружение.

3. Как был обнаружен бэкдор

29 марта 2024 года инженер Microsoft и разработчик PostgreSQL Андрес Фройнд (Andres Freund) заметил аномалию при тестировании PostgreSQL на Debian Sid:

  • SSH-подключения стали задерживаться примерно на 500 мс.
  • Процесс sshd потреблял необычно много CPU.
  • Valgrind выдавал ошибки и краши в некоторых конфигурациях (из-за побочных эффектов IFUNC/GOT-манипуляций и парсинга символов).

Фройнд провёл реверс-инжиниринг: начал с анализа CPU-профиля, затем разобрал скрипты сборки, распаковал тестовые файлы, нашёл build-to-host.m4 и проследил всю цепочку до object-файла и IFUNC-резолверов. Он опубликовал подробный разбор в oss-security mailing list до того, как скомпрометированные версии успели попасть в стабильные релизы большинства дистрибутивов.

4. Реагирование дистрибутивов (на примере Arch Linux и других)

  • Arch Linux (rolling-release) успел получить 5.6.0/5.6.1 в основной репозиторий. Пакет мгновенно откатили до безопасной 5.4.6-1. Важно: в Arch OpenSSH по умолчанию не линкуется с libsystemd, поэтому прямой вектор через sshd был заблокирован архитектурой дистрибутива, хотя сам вредоносный код присутствовал. Отозвали ISO (начиная с 2024.03.01), VM-образы и Docker-контейнеры, собранные с 24 февраля по 28 марта 2024.
  • Debian/Ubuntu/Fedora/Red Hat быстро откатили пакеты в testing/unstable и выпустили advisories. CISA рекомендовала даунгрейд до 5.4.6 и проверку систем.
  • GitHub заархивировал репозиторий XZ за нарушение ToS. Lasse Collin вернул контроль и начал долгую работу по очистке.

5. Атрибуция и следы

По оценкам спецслужб и ведущих аналитических компаний (Mandiant, CISA, Palo Alto Networks и др.), за аккаунтом Jia Tan стоит государственная группировка уровня APT (часто указывают на российские структуры — ГРУ/СВР, APT28/APT29 или аналогичные):

  • Временные зоны: график коммитов идеально совпадает с UTC+2/UTC+3 и рабочей неделей; полное затишье в дни российских государственных праздников.
  • Ложная личность: имя «Jia Tan» имитировало азиатское происхождение, однако языковые маркеры, стиль кода и технические артефакты указывали на русскоязычную среду разработки.
  • Ресурсоёмкость: операция требовала нескольких лет планирования, глубокого знания нюансов glibc IFUNC, динамического линкера, systemd, OpenSSH authentication flow, ChaCha20/Ed448 и обфускации бинарных payload’ов. Это уровень хорошо финансируемой команды, а не одиночки.

Дополнительно Jia Tan пытался влиять на OSS-Fuzz (чтобы fuzzer не ловил аномалии) и продвигал обновления в дистрибутивы прямо перед freeze-периодами.

Итог

Инцидент с XZ Utils стал важнейшим прецедентом в кибербезопасности. Он показал критическую уязвимость модели Open Source, когда ключевые компоненты мировой цифровой инфраструктуры поддерживаются одиночками-волонтёрами, и заставил IT-индустрию пересмотреть подходы к аудиту процессов сборки (особенно tarball vs Git), доверию к мейнтейнерам, использованию IFUNC, зависимостям systemd↔OpenSSH и верификации бинарных артефактов. Бэкдор был обнаружен буквально в последний момент — благодаря внимательности одного инженера и случайной 500-миллисекундной задержке. Если бы не это, последствия могли быть катастрофическими.