Разбор CVE-2024-3094: Обнаружение бэкдора SSHD в XZ Utils
29 марта 2024 года была раскрыта уязвимость (закладка/backdoor) CVE-2024-3094, которая получила 10/10 по CVSS. Возникшая в результате компрометации цепочки поставок, она затрагивает версии 5.6.0 и 5.6.1 инструментов и библиотек XZ. CVE была выявлена после обнаружения проблем с производительностью при SSH-соединениях. Это привело к раскрытию крупной атаки на цепочку поставок (Supply Chain attack), в ходе которой скомпрометированная библиотека была использована в sshd и использовалась для её обхода в процессе аутентификации.
В этой статье мы рассмотрим технические последствия этой атаки и объясним ее влияние на инфраструктуру Kubernetes и пользователей, а также рассмотрим способы обнаружения.
Предыстория
23 февраля 2024 года злоумышленник смог закоммитить код в репозитории XZ Utils на Github, который включал обфусцированный вредоносный код, изменяющий процесс сборки. Измененный процесс сборки включал вредоносный файл во время компиляции библиотеки liblzma, при этом вредоносный код ни разу не был представлен в открытом виде, что затрудняет его обнаружение. Основной целью этой атаки являются дистрибутивы Linux, поскольку они включают скомпилированную версию библиотеки liblzma, которую использует SSHD, а также распространяют ее среди многих пользователей.
Деобфусцировав вредоносный код, исследователи выяснили, что он:
- Перехватывает выполнение
- Заменяет crc32_resolve() / crc64_resolve(), которые резолвятся при запуске sshd, на другой код, вызывающий _get_cpuid()
- Производит проверки среды окружения
- Парсит таблицы символов в память (основная причина замедления)
- Устанавливает хук в динамический линковщик, ожидая резолва RSA_public_decrypt@…plt и заменяя его значение для указания на другой код бэкдора
- Вызывает вредоносный код при логине по SSH с помощью ключа + продолжает нормальную аутентификацию
Получив контроль над потоком аутентификации, библиотека может предоставлять доступ на основе критериев, заданных злоумышленником. Скорее всего, это RSA-ключи или другие данные, которые известны только злоумышленнику. Даже если вы используете сложный пароль или RSA ключ для аутентификации – вы остаетесь уязвимы.
Влияние на sshd
Во время аутентификации в службе ssh пользователь обменивается с сервером ключами RSA, вредоносный код вызывается в процессе проверки на стороне сервера:
sshd 1736357 [010] 714318.734008: 1 branches:uH: 5555555ded8c ssh_rsa_verify+0x49c (/usr/sbin/sshd) => 5555555612d0 RSA_public_decrypt@…+0x0 (/usr/sbin/sshd
Затем бэкдор снова обращается к libcrypto, предположительно для выполнения обычной аутентификации:
sshd 1736357 [010] 714318.734009: 1 branches:uH: 7ffff7c137cd [unknown] (/usr/lib/x86_64-linux-gnu/liblzma.so.5.6.0) => 7ffff792a2b0 RSA_get0_key+0x0 (/usr/lib/x86_64-linux-gnu/libcrypto.so.3)
Тем самым, вредоносный код представляет собой бэкдор, позволяющий злоумышленнику обойти аутентификацию, и ко всему прочему получить RCE на целевой системе (вызывая функцию libc system()).
Влияние на Kubernetes
Для пользователей Kubernetes эта критическая уязвимость может подвергнуть риску как весь кластер, так и отдельные контейнеры. Потенциальному риску здесь подвергаются в основном Nodes или Pods, у которых запущен ssh-server и прокинуты наружу порты.
CVE-2024-3094 (как и любую другую 1-day/0-day уязвимость) можно обнаружить в runtime с помощью Luntry.
Для демонстрации обнаружения при эксплуатации CVE-2024-3094 был подготовлен docker-образ с уязвимой версией xz-utils:
Затем мы подготовили следующий манифест:
После запуска приложения в Kubernetes кластере Luntry обучается на поведении приложения, работающего внутри контейнера. На дереве процессов видно, что ssh сервер используется для легального подключения.
Теперь смоделируем ситуацию, когда злоумышленник нашёл наш уязвимый ssh-server и хочет получить RCE. Для этого воспользуемся утилитой xzbot. Но для начала перенаправим порты:
Воспользуемся эксплойтом – запишем результат команды cat /etc/passwd в файл /tmp/.xzk8s:
Перейдя в Monitor Mode мы увидим, что появился аномальный процесс cat и создание файла .xzk8s, которого раньше не было, более того он был порожден от sshd.
Luntry умеет собирать SBOM из docker image и сканировать их на уязвимости. Это можно сделать как в runtime, когда ваше приложение уже работает в кластере, так и на этапе CI или когда образ уже доставлен в registry. Так, например, еще на этапе сканирования образа мы можем обнаружить уязвимую версию библиотеки liblzma5 и принять необходимые меры.
Более того, на вкладке Network Map, где можно просматривать все сетевые соединения в Kubernetes кластере, есть возможность отображать найденные CVE для конкретного приложения. Это дает возможность более гибко подойти к вопросам приоритизации уязвимостей – можно увидеть, какой уязвимый сервис торчит наружу.
Выводы
Для того, чтобы обнаружить эту уязвимость используя сигнатурный подход, необходимо использовать правило (сигнатуру), которое будет сопоставлять версию (имя) используемой библиотеки xzutils с вредоносной. Однако, этот метод эффективен для обнаружения известных угроз, для которых имеются сигнатуры. Он не способен обнаруживать новые или измененные угрозы, не имеющие известных сигнатур.
Не стоит исключать тот факт, что при эксплуатации уязвимости злоумышленник уже имел доступ к системе и мог изменить название вредоносной библиотеки.
В отличие от сигнатурного подхода, поведенческий способен обнаружить новые или неизвестные угрозы, так как не зависит от наличия заранее известных сигнатур. Это в свою очередь даёт возможность обнаруживать 0-day уязвимости.
Ссылки
https://github.com/amlweems/xzbot/
https://www.openwall.com/lists/oss-security/2024/03/29/4
https://gist.github.com/smx-smx/a6112d54777845d389bd7126d6e9f504
https://gist.github.com/q3k/af3d93b6a1f399de28fe194add452d01
https://gist.github.com/keeganryan/a6c22e1045e67c17e88a606dfdf95ae4