SOT

Security Orchestration Tools

Напишите нам на sales@securityvision.ru или закажите демонстрацию

eBPF глазами хакера. Часть 3

eBPF глазами хакера. Часть 3

Екатерина Гайнуллина, Security Vision

 

Введение


Если eBPF даёт атакующему возможность видеть и действовать внутри ядра, то следующим логичным шагом становится вопрос выживания: как остаться в системе как можно дольше? Для любой вредоносной нагрузки этого уровня устойчивость не менее важна, чем сама возможность атаки. Классические руткиты борются за присутствие в системе — скрывают свои файлы, процессы, соединения, переживают перезагрузку. eBPF-руткиты делают то же самое, но другими средствами — куда более изящными и трудноуловимыми.


Уникальность eBPF в том, что его программы, однажды загруженные в ядро, работают независимо от загрузившего их процесса. Код остаётся активным, даже если скрипт или бинарник, который его внедрил, больше не существует. Система как бы «принимает» эту программу внутрь — и больше не контролирует её как часть пользовательского пространства. Для злоумышленника это открывает возможности тонкого и устойчивого закрепления: без следов на диске, без процессов в ps, без портов в netstat.


В этой части будет разбрано, как атакующий может обеспечить устойчивость eBPF-программы: способность переживать перезагрузки, скрывать свою активность и даже защищать саму себя. Также рассмотрим реальные техники — от автозагрузки через systemd до namespace-изоляции, от самозащиты через хуки до примеров атак из практики. И главное — обсудим, что с этим можно делать: какие есть средства противодействия, как выявить такую активность и почему традиционные методы мониторинга здесь бессильны.


Часть 3. Устойчивость и скрытность – закрепление в системе


Итак, мы видели, что eBPF может дать злоумышленнику глаза и руки внутри ядра. Теперь возникает вопрос: как обеспечить постоянное присутствие такого инструмента? Традиционные руткиты стремятся укорениться в системе – переживать перезагрузки, скрывать свои процессы и файлы. eBPF-руткиты – не исключение. В этой части разберём, как злоумышленник может добиться устойчивости eBPF-программы в системе и скрыть её от обнаружения.


Первое, что следует отметить: eBPF-программа, однажды загруженная в ядро, живёт отдельно от пользовательского процесса. То есть после успешной загрузки и прикрепления, eBPF-программа будет работать в ядре даже если выгрузить загрузивший её пользовательский код. Например, наш кейлоггер из части 1 может быть загружен небольшим скриптом, после чего сам скрипт может завершиться – перехватчик останется висеть на вызовах readline. Это уже даёт некоторое упрощение задачи скрытности: нет явного процесса-вредоносца в ps или top. Однако сам факт наличия загруженной eBPF-программы может выдать команду bpftool prog, /sys/fs/bpf файловая система или отладочные точки в /sys/kernel/debug.


Как загрузить eBPF-программу? Атакующий имеет два основных пути:

  • Использовать готовый инструмент bpftool (или его аналог). Например, скомпилировав вредоносную eBPF-программу в файл rootkit.o, он может выполнить:

# Загрузка программы и сохранение (pin) в файловой системе BPF

bpftool prog load rootkit.o /sys/fs/bpf/knock_filter

 

# Прикрепление программы (например, к XDP на интерфейс eth0)

bpftool net attach xdp pinned /sys/fs/bpf/knock_filter dev eth0


Команда prog load загрузит байткод eBPF в ядро и зафиксирует его по указанному пути (в псевдоФС BPF). Далее net attach xdp прикрепит загруженную программу к сетевому интерфейсу. После этого программа начнёт работать, а сам файл rootkit.o можно удалить – он не нужен, так как код уже в ядре.

  • Использовать напрямую системный вызов bpf() или библиотеку libbpf в своем malware-коде. Это более скрытный способ, не требующий внешних утилит. Например, вредонос может содержать байткод eBPF внутри себя или загружать его с сервера, после чего вызвать bpf(BPF_PROG_LOAD, ...) для регистрации программы в ядре. Затем – bpf(BPF_PROG_ATTACH, ...) чтобы привязать её к нужному хуку (например, kprobe, tracepoint, cgroup и т.д.). Всё это делается через API, без создания каких-либо файлов на диске.


Теперь о постоянстве и автозагрузке. Сама по себе eBPF-программа не переживёт перезагрузку – ядро «чистое» при старте. Поэтому злоумышленник позаботится о повторной загрузке. Возможные трюки: добавить команду загрузки eBPF в скрипты автозапуска (rc.local, unit-файл systemd, cron-задачу), замаскировать под легитимную службу. Например, можно создать сервис systemd, который на старте выполняет команду bpftool с заранее подготовленным байткодом. Другой способ – интегрировать загрузку в уже существующий процесс (через уязвимость или патч). В известном случае, описанном компанией Dr.Web, eBPF-руткит устанавливался первым именно для того, чтобы скрыть установку классического модульного руткита. То есть атакеры могут комбинировать техники: модуль ядра получает постоянство (например, через /etc/modules или DKMS), а eBPF-программа защищает этот модуль от обнаружения.


Методы сокрытия. Сокрытие — пожалуй, самая изощрённая и опасная сторона использования eBPF в руках злоумышленника. Одно дело — подслушивать и вмешиваться, но совсем другое — остаться невидимым даже для опытного администратора и большинства защитных средств. И именно здесь eBPF раскрывает себя как инструмент маскировки — не просто руткит, а живущий в ядре призрак, который может править поведением системы и при этом не оставлять следов.


Одним из ключевых направлений скрытности становится обман отладочных и диагностических утилит. Например, утилита bpftool позволяет просматривать загруженные программы и карты eBPF, получая полную информацию о точках крепления и внутренних структурах. Но современные руткиты, такие как ebpfkit, способны вмешиваться в работу этой утилиты, заставляя её отображать неполную или поддельную картину. Это достигается тем, что сама eBPF-программа перехватывает системные вызовы или функции ядра, связанные с получением информации о BPF-объектах, такие как bpf_prog_get_info_by_fd, bpf_map_get_info_by_fd и аналогичные. С помощью kprobe-хуков злоумышленник может изменить содержимое возвращаемых структур, исключая из них собственные идентификаторы. В результате даже при ручном аудите через bpftool prog show вредоносные программы не будут видны: ядро «лжёт», находясь под контролем самого руткита. Получается своеобразная рекурсивная защита — eBPF-программа охраняет саму себя, подавляя попытки её обнаружения.


Другой важный механизм — изоляция и ограничение доступа к объектам eBPF. Архитектура BPF позволяет загружать программы в изолированных namespace’ах или привязывать их к определённым cgroup’ам. Это значит, что eBPF-программа, размещённая в отдельном сетевом пространстве имён, будет недоступна для аудита со стороны других процессов, даже если они имеют root-доступ — без пересечения namespace это попросту невозможно. Кроме того, объекты BPF могут быть закреплены (pinned) в виртуальной файловой системе bpffs, и если злоумышленник монтирует её в нестандартное место (например, /tmp/.hidden_bpf), большинство инструментов, включая автоматизированные сканеры, туда просто не заглянут. Всё это делает вредоносную программу невидимой снаружи, даже если она активно работает внутри ядра.


Классическим элементом маскировки остаётся перехват системных вызовов. Ранее это делалось через модификацию таблицы системных вызовов или через внедрение модулей ядра (LKM-руткиты), но теперь те же цели достигаются через eBPF — без необходимости что-либо изменять на диске. Специальные типы eBPF-программ, такие как LSM-хуки и kprobe override, позволяют не просто наблюдать за системным вызовом, но и менять его поведение — вплоть до возврата поддельных данных. Например, если процесс вызывает getdents() для чтения содержимого каталога, eBPF-программа может вырезать оттуда строки, относящиеся к «невидимому» процессу или файлу. Аналогично, перехват функции open() может скрыть наличие определённого исполняемого файла или конфигурации. Всё это происходит в режиме ядра, через встроенные хуки, без внешних библиотек или изменений в системных таблицах. Фактически, вредонос получает возможность редактировать восприятие системы пользователем или инструментами мониторинга — в режиме реального времени и без признаков подмены.


Не менее важно и то, что eBPF-атаки могут почти полностью обходиться без следов на диске. Программа может быть загружена в память напрямую, а после активации байткод удаляется — в логах ничего нет, в cron — тишина, в файловой системе — пусто. Некоторые руткиты дополнительно шифруют или стирают остатки своего байткода, а для загрузки могут использовать нестандартные пути, обходя ограничения ядра. Например, BPFDoor, один из наиболее известных примеров скрытного бэкдора, использовал eBPF внутри BPF-сокетов, не открывая ни одного порта и не оставляя следов прослушивания. Более того, в ряде случаев использовались уязвимости ядра, такие как CVE-2022-20268, позволявшие загружать eBPF-программы, обходя встроенные проверки и верификатор. Эти уязвимости уже закрыты, но сам факт их существования демонстрирует, насколько изобретательными могут быть злоумышленники, когда речь идёт о внедрении eBPF в систему.


Реальные кейсы укрепляют эти выводы. Например, упомянутый ebpfkit – это концепт-руткит, продемонстрированный в 2021 году, который умел скрывать свои карты и программы от bpftool и других мониторингов. Атака 2024 года в Юго-Восточной Азии показала сочетание eBPF и классического руткита: eBPF-модуль первым скрывал присутствие всего остального зловреда. Open-source проект boopkit в 2022 году выложил пример бэкдора, который при получении особого сетевого пакета открывает обратный шелл – и всё это реализовано чисто через eBPF на уровне TCP. Такие инструменты трудно обнаружить традиционными методами.


Обнаружение и противодействие eBPF-руткитам. Устойчивость eBPF-руткита определяется его главной особенностью: он работает в ядре, на тех же правах, что и операционная система. При этом он не требует установки модулей, не оставляет явных следов в файловой системе, может быть загружен динамически, закреплён в памяти и замаскирован даже от таких инструментов, как bpftool и bpftrace. В совокупности это превращает его в одну из самых трудновыявляемых форм вредоносного ПО на Linux — особенно если система уже скомпрометирована и атакующий обладает root-доступом.


Классические методы обнаружения вредоносной активности в Linux — поиск подозрительных процессов, аномальных cron-задач, незнакомых бинарников в автозагрузке или открытых сокетов — в случае с eBPF бессильны. Никаких процессов в ps, никаких логов в journald, никаких подключённых модулей в lsmod. Всё исполняется глубоко внутри ядра — в рамках заранее одобренной eBPF-программы, уже прошедшей верификацию. Более того, вредонос может использовать хуки и подмену, чтобы подделывать или фильтровать любую информацию, возвращаемую стандартными средствами анализа, включая вызовы stat, readlink, getdents, netstat и даже bpftool или bpf().


Тем не менее, существуют технические и архитектурные подходы к защите, но они требуют перехода от реактивной модели к проактивной. Первое и базовое — это запрет загрузки eBPF-программ непривилегированными пользователями. Параметр kernel.unprivileged_bpf_disabled=1 позволяет отключить возможность использования eBPF в пространстве пользователя без специальных прав (начиная с Linux 5.8 и выше, он рекомендуется как обязательный в системах безопасности). Однако важно понимать, что этот механизм не поможет, если атакующий уже получил root-доступ — а именно такой уровень доступа чаще всего нужен для загрузки более опасных eBPF-программ (например, LSM-хуков или XDP).


Следующий уровень — мониторинг самого факта загрузки eBPF-программ. Это возможно, поскольку в ядре используется системный вызов bpf(), и его можно отслеживать, например, через auditd, eBPF-программы наблюдения или другие системные трассировщики. Аналогично можно отслеживать активность утилиты bpftool, особенно команды prog load, map create, prog attach и т.п. Хотя эти события не указывают напрямую на вредоносную активность, они позволяют выявить подозрительное поведение на ранней стадии — особенно в нестандартных скриптах, в неразрешённых сессиях или изолированных контейнерах.


Также крайне важно регулярно аудировать содержимое виртуальных файловых систем /sys/fs/bpf и /sys/kernel/debug/bpf/, где хранятся закреплённые объекты eBPF. Если злоумышленник воспользовался нестандартной точкой монтирования bpffs, стоит искать признаки её существования: например, вручную просканировать /proc/mounts, системные вызовы mount, umount, или использовать средства типа findmnt. Обнаружение новых mount’ов с типом bpf вне стандартного пути — уже потенциальный индикатор компрометации.


Некоторые современные EDR и антивирусные решения начали учитывать поведение eBPF-программ как возможный признак атаки. Например, резкое увеличение количества BPF-карт, динамическая регистрация хуков kprobe, нестандартные LSM-программы и активное использование bpf_trace_printk без явных причин — всё это может быть отмечено как подозрительное. Но, как и в случае с другими технологиями, проблема заключается в том, что вредонос может первым получить контроль и отключить наблюдение за собой. В этом смысле eBPF — идеальный руткит: он может встроиться в ядро и подавить попытки его обнаружения с помощью тех же механизмов, которые используют защитники.


Отсюда следует важный вывод: противодействие eBPF-злоупотреблениям должно быть в первую очередь превентивным, а не реактивным. Прежде всего, это:

  • Постоянный аудит загруженных eBPF-программ и точек их крепления (не только в стандартных путях, но и по всей системе).

  • Обновление ядра и всех зависимых компонентов: eBPF активно развивается, но вместе с функциональностью появляются и уязвимости. Только за последние годы выявлено более 200 CVE, связанных с BPF и его верификатором.

  • Жёсткое ограничение на запуск привилегированных программ. Если можно — через AppArmor, SELinux или аналогичные системы. Если нельзя — через ограниченные контейнеры, cgroup и seccomp.

  • Использование BPF LSM — нового механизма, который позволяет реализовывать «белые списки» доверенных eBPF-программ на уровне ядра, аналогично подписанным модулям ядра.


В конечном итоге, eBPF — это не только угроза, но и возможность. В руках администратора это мощный инструмент отладки, анализа, профилирования и даже политики безопасности. Но в руках хакера — это полноценный фреймворк для создания живущих в ядре, неуловимых и самозащищённых руткитов. Цикл «eBPF глазами хакера» показывает, насколько опасной может быть эта технология при неправильном контроле. И, скорее всего, сообществу безопасности предстоит в ближайшие годы выстроить новую парадигму защиты, в которой ядро перестанет быть «чёрным ящиком» — и станет контролируемым пространством, в том числе и в отношении eBPF.


Заключение


Всё, что делает классический руткит — маскирует, вмешивается, перехватывает, сохраняется — eBPF делает лучше. Он не требует модулей ядра, не создаёт процессов, может жить в изолированных пространствах имён, фильтровать любые данные на лету и подменять восприятие системы для пользователя. Он может загружаться из памяти, сам себя защищать и удалять свои следы. При этом выглядит как корректная, валидная часть ядра — проверенная, верифицированная и допустимая.


В заключительной части мы увидели, что eBPF-руткиты — это не гипотеза, а реальность. От boopkit и ebpfkit до примеров атак в дикой природе, от Sabotage-as-a-Service до скрытых шеллов, активируемых сетевыми пакетами — всё это уже происходило. Для защиты от такого уровня угрозы требуется переосмысление архитектуры наблюдаемости и доверия. Контроль за пользовательскими процессами уже не спасает. Теперь важно знать, что загружено в ядро, к чему оно прикреплено, и кто этим управляет.

Нарушители ИБ Практика ИБ Управление ИБ

Похожие статьи

Масштабное обновление Security Vision SIEM
Масштабное обновление Security Vision SIEM
Технологии защиты от deepfake
Технологии защиты от deepfake
Антифрод системы - что это и как работает
Антифрод системы - что это и как работает
Эволюция CVSS и разбор примера оценки уязвимости
Эволюция CVSS и разбор примера оценки уязвимости
CVSS: система оценки уязвимостей - что это такое и как использовать калькулятор
CVSS: система оценки уязвимостей - что это такое и как использовать калькулятор
CyBOK. Глава 3. Законы и регуляторные нормы. Часть 1
CyBOK. Глава 3. Законы и регуляторные нормы. Часть 1
Сравнительный обзор: Shodan, ZoomEye, Netlas, Censys, FOFA и Criminal IP. Часть 2
Сравнительный обзор: Shodan, ZoomEye, Netlas, Censys, FOFA и Criminal IP. Часть 2
Fingerprint браузера - что это
Fingerprint браузера - что это
Что такое Single Sign-On (SSO)
Что такое Single Sign-On (SSO)
Спам – что это такое, каким бывает и есть ли в нем польза
Спам – что это такое, каким бывает и есть ли в нем польза
CyBOK. Глава 1. Введение
CyBOK. Глава 1. Введение

Похожие статьи

Масштабное обновление Security Vision SIEM
Масштабное обновление Security Vision SIEM
Технологии защиты от deepfake
Технологии защиты от deepfake
Антифрод системы - что это и как работает
Антифрод системы - что это и как работает
Эволюция CVSS и разбор примера оценки уязвимости
Эволюция CVSS и разбор примера оценки уязвимости
CVSS: система оценки уязвимостей - что это такое и как использовать калькулятор
CVSS: система оценки уязвимостей - что это такое и как использовать калькулятор
CyBOK. Глава 3. Законы и регуляторные нормы. Часть 1
CyBOK. Глава 3. Законы и регуляторные нормы. Часть 1
Сравнительный обзор: Shodan, ZoomEye, Netlas, Censys, FOFA и Criminal IP. Часть 2
Сравнительный обзор: Shodan, ZoomEye, Netlas, Censys, FOFA и Criminal IP. Часть 2
Fingerprint браузера - что это
Fingerprint браузера - что это
Что такое Single Sign-On (SSO)
Что такое Single Sign-On (SSO)
Спам – что это такое, каким бывает и есть ли в нем польза
Спам – что это такое, каким бывает и есть ли в нем польза
CyBOK. Глава 1. Введение
CyBOK. Глава 1. Введение