На дво­ре вес­на, хочет­ся чего‑то лег­кого, све­жего и нового. Вот, нап­ример, све­жая идея: нель­зя ли вес­ти логи в Linux, не про­писы­вая для auditd сто тысяч раз пути к кри­тич­ным кон­фигам и исполня­емым фай­лам? Рядом девоп­серы обсужда­ли Cilium и какой‑то Tetragon, который может писать логи в JSON. Мы решили тоже поп­робовать!

Tetragon осно­ван на eBPF — это тех­нология, встро­енная в ядро Linux, которая поз­воля­ет безопас­но и эффектив­но запус­кать мини‑прог­раммы пря­мо в ядре. Бла­года­ря это­му eBPF-инс­тру­мен­ты, как пра­вило, быс­трее и пот­ребля­ют мень­ше ресур­сов, чем клас­сичес­кие решения вро­де закос­тенело­го auditd.

Тот, кто хотя бы раз нас­тра­ивал auditd для SOC, навер­няка стал­кивал­ся с самыми раз­ными, в том чис­ле безум­ными, кон­фигура­циями — нап­ример, очень популяр­ный кон­фиг от Neo23x0 нас­читыва­ет более 800 строк. Попыт­ки пре­одо­леть огра­ниче­ния и адап­тировать­ся под кон­крет­ный дис­три­бутив и архи­тек­туру — та еще морока.

info

Сра­зу ого­ворим­ся, что Falco и иные инс­тру­мен­ты и под­ходы мы не рас­смат­рива­ем, — это тема отдель­ной статьи.

Tetragon уни­вер­сален и работа­ет на мно­жес­тве плат­форм, написан на Go, а еще «из короб­ки» прис­пособ­лен к работе с кон­тей­нерами. Но информа­ции по нему (а осо­бен­но тому, как исполь­зовать его эффектив­но) край­не мало.

Да­вай вмес­те раз­бирать­ся, как мож­но играть­ся с Tetragon. Бонусом в кон­це статьи — реаль­ная исто­рия о том, почему Tetragon мес­тами лютый вин.

 

Основные понятия и схема работы

На­чать при­дет­ся с теории, но мы обой­дем­ся без душ­ных деталей. Итак, внут­ри у Tetragon тех­нология eBPF. Изна­чаль­но она была раз­работа­на для Linux, но, кста­ти, и в Microsoft сей­час тоже пилят свою реали­зацию.

Яд­ро Linux — это прог­рам­мный слой меж­ду при­ложе­ниями и обо­рудо­вани­ем, на котором они работа­ют. При­ложе­ния живут в неп­ривиле­гиро­ван­ном слое, называ­емом поль­зователь­ским прос­транс­твом, оно не может получить дос­туп к обо­рудо­ванию нап­рямую. Вмес­то это­го при­ложе­ние дела­ет зап­росы, исполь­зуя интерфейс сис­темных вызовов, так называ­емые syscall, что­бы поп­росить ядро дей­ство­вать от его име­ни.

Этот дос­туп к обо­рудо­ванию может вклю­чать чте­ние и запись в фай­лы, отправ­ку и получе­ние сетево­го тра­фика или даже прос­то дос­туп к памяти. Ядро так­же отве­чает за коор­динацию парал­лель­ных про­цес­сов, поз­воляя мно­гим при­ложе­ниям работать одновре­мен­но.

Примерная схема работы ядра Linux
При­мер­ная схе­ма работы ядра Linux

eBPF, или Extended Berkeley Packet Filter, — фрей­мворк, поз­воля­ющий поль­зовате­лям заг­ружать и запус­кать прог­раммы в ядре опе­раци­онной сис­темы.

А еще BPF — это вир­туаль­ная машина внут­ри Linux, которая выпол­няет код BPF в режиме ядра. Пос­ле заг­рузки прог­рамма eBPF прик­репля­ется к целевой фун­кции ядра, что­бы наш код запус­кался вся­кий раз, ког­да про­исхо­дит ее вызов. Счи­тай, что это некая прос­лой­ка‑над­зиратель.

Так как это все работа­ет на при­виле­гиро­ван­ном уров­не, нуж­на серь­езная безопас­ность. Поэто­му механизм eBPF вклю­чает верифи­катор, который гаран­тиру­ет, что прог­рамма eBPF заг­ружа­ется толь­ко в том слу­чае, если ее запуск безопа­сен. Детали мож­но пос­мотреть в докумен­тации.

Есть готовые биб­лиоте­ки для написа­ния сво­ей ути­литы с при­мене­нием eBPF, но лишь на неболь­шом чис­ле язы­ков. Сре­ди них — C, Go, Rust и Python. Выбор язы­ка усложня­ется еще и тем, что не для всех язы­ков есть либы, реали­зующие под­дер­жку libbpf (популяр­ный вари­ант для обес­печения перено­симос­ти прог­рамм eBPF меж­ду раз­ными вер­сиями ядра). Но мы с тобой не кодеры и будем исполь­зовать готовое решение, раз­работ­чики которо­го уже обо всем позабо­тились.

Схема работы приложения Tetragon
Схе­ма работы при­ложе­ния Tetragon

Да­вай раз­берем основные фун­кци­ональ­ные ком­понен­ты сис­темы.

По­лити­ки трас­сиров­ки (tracing policy) — это для нас основной инс­тру­мент работы. Они поз­воля­ют нас­тра­ивать как реак­ции для монито­рин­га (логиро­вания), так и активные дей­ствия (бло­киро­вание дос­тупа, убий­ство про­цес­са и про­чее) на осно­ве задан­ных кри­тери­ев. Полити­ки зада­ются в фай­лах YAML и скла­диру­ются в каталог /etc/tetragon/tetragon.tp.d/. В качес­тве кри­тери­ев могут выс­тупать наз­вания сис­колов, вызовы фун­кций ядра, зна­чения вызыва­емых аргу­мен­тов. Мож­но добав­лять кас­томный текст, который добавит­ся в алерт.

Что­бы сос­тавить собс­твен­ную полити­ку ауди­та, надо раз­бирать­ся в прин­ципах работы ядра Linux. Клю­чевые сущ­ности, на которые мож­но навесить генера­цию событий (или выпол­нение иных дей­ствий), сле­дующие:

  • LSM (Linux Security Modules) BPF, они же хуки безопас­ности SELinux/AppArmor. Для их исполь­зования необ­ходимо выпол­нение ря­да усло­вий — модули дол­жны быть заг­ружены, вклю­чены и про­чее. Наз­вания фун­кций мож­но взять из ис­ходни­ков Linux. Из пре­иму­ществ — воз­можность рас­счи­тывать хеши для фай­лов и обо­гащать ими генери­руемые события. Обыч­но в ком­пани­ях, где исполь­зуют­ся полити­ки безопас­ности, с хар­денин­гом и так все неп­лохо, поэто­му дви­жем­ся даль­ше.
  • Kprobes (Kernel probes), или зон­ды ядра. По сути, дают воз­можность соз­дания брейк‑пой­нта перед вызовом инс­трук­ции ядра с выпол­нени­ем про­изволь­ного кода. Нап­ример, мож­но заменить аргу­мен­ты — кста­ти, не толь­ко вход­ные. Но kprobes могут менять­ся меж­ду вер­сиями ядра опе­раци­онки, что сде­лает наши полити­ки нес­табиль­ными. Что­бы вывес­ти спи­сок дос­тупных kprobes, выпол­ни в тер­минале cat /proc/kallsyms. В полити­ках Tetragon для сис­темных вызовов (syscall) рекомен­дует­ся исполь­зовать обоб­щенное наз­вание вызова, нап­ример вмес­то зна­чений do_sys_open, __x64_sys_open или __ia32_sys_open в полити­ке мож­но ука­зывать прос­то sys_open. Tetragon умный, сам раз­берет­ся и адап­тиру­ется под архи­тек­туру, на которой работа­ет.
  • Uprobes. В целом ана­логич­ны kprobes, толь­ко при­меня­ются к прог­раммам в прос­транс­тве поль­зовате­ля. Здесь работу с uprobes мы рас­смат­ривать не будем, пос­коль­ку хуки ядра и так дают нам дос­таточ­но воз­можнос­тей для тон­кой нас­трой­ки политик.
  • Tracepoints. Точ­ки трас­сиров­ки ста­тичес­ки про­писа­ны в ядре. Имен­но они счи­тают­ся наибо­лее удач­ным вари­антом для отсле­жива­ния и прик­репле­ния сво­его кода для отладки. Основное пре­иму­щес­тво перед зон­дами — ста­биль­ность меж­ду релиза­ми.

Что­бы узнать дос­тупные трей­спой­нты в сво­ей сис­теме, выпол­ни такую коман­ду:

cat /sys/kernel/debug/tracing/available_events

Вы­вод будет в фор­мате «катего­рия:имя»; пос­леднее — как раз то, за что может уце­пить­ся eBPF.

В некото­рых сис­темах ряд точек недос­тупен, про­верить их спи­сок мож­но так:

cat /sys/kernel/debug/krpobes/blacklist

Из минусов трей­спой­нтов — они есть далеко не для всех фун­кций ядра, и, если нуж­ного нет, при­дет­ся смот­реть в сто­рону kprobes.

К чему в ито­ге луч­ше хукать­ся и как пос­мотреть все позиции дан­ного меню? При выборе меж­ду наз­вани­ем syscall, фун­кции ядра, kprobe и tracepoint пред­почти­тель­нее ори­енти­ровать­ся на трей­спой­нты, пос­коль­ку они име­ют более ста­биль­ный интерфейс, чем эле­мен­ты ядра. Фун­кции ядра могут пери­оди­чес­ки менять­ся, что в дол­госроч­ной пер­спек­тиве может при­вес­ти к проб­лемам. Если сов­сем лень раз­бирать­ся, мож­но прос­то гре­пать в выводе ути­литы bpftrace: bpftrace -l — она покажет прос­то всё, за что мож­но зацепить­ся.

Мы в статье будем исполь­зовать микс на осно­ве отдель­ных сис­колов и фун­кций ядра. Это обес­печит плав­ный переход от auditd (который срав­нитель­но известен) к при­мене­нию eBPF на осно­ве kprobes и tracepoints.

 

Шпаргалка по хукам

Что­бы упростить себе и кол­легам жизнь, мы сос­тавили таб­лицу по самым популяр­ным или инте­рес­ным активнос­тям, которые обыч­но хотят видеть безопас­ники. В таб­лице мы све­ли име­на отдель­ных сис­колов, как их при­вык­ли записы­вать в пра­вилах auditd. Рядом ука­зыва­ем наз­вания фун­кций ядра, сопос­тавля­емых с дан­ными сис­колов, — это уже мож­но пытать­ся исполь­зовать в eBPF-решени­ях, в том чис­ле в Tetragon.

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии