
Уязвимость BDU:2024-01187 в модуле nf_tables_api.c ядра Linux
Уязвимость BDU:2024-01187 (CVE-2024-1086) связана с ошибкой в функции nft_verdict_init() модуля net/netfilter/nf_tables_api.c
ядра Linux. Проблема возникает из-за некорректного управления памятью при обработке вердиктов в Netfilter, что приводит к возможности повторного использования освобожденной памяти (use-after-free или double free). Это позволяет злоумышленнику выполнить произвольный код, повысить привилегии и нарушить конфиденциальность, целостность и доступность системы.
Условия эксплуатации
-
Ядро Linux версий от 6.2 до 6.6.14, от 6.7.0 до 6.7.2, от 4.0 до 4.19.306, от 4.20 до 5.4.268, от 5.5 до 5.10.209, от 5.11 до 5.15.148,от 5.16 до 6.1.75.
-
Наличие CAP_NET_ADMIN у атакующего процесса (локальный доступ).
Технический разбор эксплойта
Основные этапы работы эксплойта
-
Создание изолированного окружения:
-
Использует
unshare()
для создания новых пространств имен (user и network), чтобы изолировать сетевые настройки. -
Настраивает UID/GID mapping для эмуляции привилегий root в пространстве имен.
-
-
Настройка Netfilter через libnftnl:
-
Создает таблицу, цепочку и правило в Netfilter, используя Netlink.
-
Правило фильтрует пакеты по протоколу и данным в заголовке, чтобы триггерить уязвимость.
-
-
Триггеринг уязвимости:
-
Double Free в skb (сетевых буферах):
-
Отправка специально сформированных IP-пакетов через RAW-сокет.
-
Функции
trigger_double_free_hdr()
иalloc_intermed_buf_hdr()
вызывают двойное освобождение памяти, манипулируя фрагментацией пакетов. -
Управление таймаутом фрагментации (
ipfrag_time
) для контроля момента освобождения памяти.
-
-
-
Маскировка double free:
-
spray skb: Массовое выделение и освобождение UDP-пакетов, чтобы скрыть corrupted skb от детекторов ядра.
-
-
Перехват контроля через spray PTEs:
-
Распыление Page Table Entries (PTE):
-
Аллокация большого количества страниц памяти для перезаписи освобожденных структур ядра.
-
Поиск пересечений между распылёнными PTE и PMD (Page Middle Directory) для получения контроля над физической памятью.
-
-
-
Поиск и подмена modprobe_path:
-
Поиск физического адреса ядра: Сканирование памяти для обнаружения сигнатур кода ядра.
-
Перезапись modprobe_path: Замена пути
/sbin/modprobe
на скрипт, выполняющий шелл с правами root. -
Использование
memfd_create()
иfexecve()
для триггерирования выполнения модифицированного пути.
-
Ключевые компоненты эксплойта
-
Netfilter Rules:
-
Использует
nftnl
для создания правил, которые фильтруют пакеты с определённым протоколом (70) и данными (0x41414141
). -
Вердикт
NFT_RETURN
возвращает управление, но некорректная обработка вnft_verdict_init()
вызывает ошибку.
-
-
Манипуляции с skb:
-
Отправка фрагментированных пакетов провоцирует аллокацию и освобождение skb в ядре.
-
Управление
ipfrag_time
позволяет задержать освобождение, создавая условия для race condition.
-
-
Spray PTEs/PMD:
-
Аллокация тысяч страниц через
mmap()
с фиксированными адресами. -
Коррупция структур пагинации для доступа к физической памяти ядра.
-
-
Обход KASLR:
-
Поиск физических адресов ядра через сигнатуры стартового кода.
-
Использование
is_kernel_base()
для идентификации точек входа ядра.
-
Способы защиты
1. Обновление ядра
Установите патчи для ядра Linux, устраняющие уязвимость. Проверьте актуальность версии:
uname -r Убедитесь, что версия выше упомянутых в начале статьи.
2. Ограничение CAP_NET_ADMIN
Минимизируйте количество процессов с CAP_NET_ADMIN:
# Пример: Лишение пользователя CAP_NET_ADMIN setcap cap_net_admin-ep /path/to/binary
3. Использование защитных механизмов
-
Kernel Hardening:
-
Включите
CONFIG_SLAB_FREELIST_HARDENED
для защиты от перехвата freelist. -
Активируйте
CONFIG_STATIC_USERMODEHELPER
для фиксации пути к usermode helper.
-
-
SELinux/AppArmor:
-
Настройте политики, запрещающие выполнение RAW-сокетов для непривилегированных пользователей.
-
4. Мониторинг Netfilter
Используйте инструменты вроде auditd для отслеживания подозрительных правил:
auditctl -a always,exit -F arch=b64 -S socket -F a0=AF_NETLINK -F a1=SOCK_RAW
5. Изоляция сетевых пространств
Запускайте ненадёжные процессы в отдельных network namespaces:
unshare --net --map-root-user bash
