Статья Пост-эксплуатация в Linux в 2026: где у EDR заканчивается видимость и почему LotL до сих пор работает

1775233932308.webp

С Linux post-exploitation есть старая неприятность: чем ближе активность к штатной жизни системы, тем хуже она отделяется от нормы. На Windows шум часто заметнее. На Linux много вещей выглядит как обычная админка, пока не посмотришь на контекст процесса, окружение, цепочку запуска и события ядра. Поэтому Living off the Land здесь до сих пор живёт именно из-за устройства самой среды.

EDR на Linux за последние годы стал сильнее. Телеметрии больше, runtime-наблюдаемость глубже, eBPF-инструменты давно вышли из разряда лабораторных игрушек. Но проблема никуда не делась: как только активность уходит в доверенный user space, в уже открытый auth-контекст или в память процесса без лишнего файлового мусора, детект становится заметно грязнее. На этом участке защита уже не ловит красивую сигнатуру. Ей приходится разбирать мутную последовательность вроде бы легитимных действий.

А самая жесть - eBPF. Защитник утащил наблюдаемость ближе к ядру, но этим же маршрутом начал интересоваться и противник. Разговор про post-exploitation на Linux уже трудно отделить от вопроса, кто первым увидит событие и кто раньше встроится в runtime-контур - сенсор или атакующий.

Living off the Land в Linux​

Концепция LotL: использование доверенных утилит (bash, python, curl, openssl)​

В Linux ядро LotL почти всегда крутится вокруг shell, интерпретаторов и сетевых утилит, которые в системе и так считаются нормальными. Не потому, что это "тихо" само по себе, а потому, что через них уже есть всё нужное: выполнение команд, работа с файлами, сетевой выход, шифрование, упаковка данных, запуск дочерних процессов. MITRE для этого и держит отдельную ветку T1059.004 Unix Shell - как раз под сценарии, где управление хостом идёт через штатную командную среду.

Практический смысл LotL на Linux в другом: атакующему не всегда нужен новый артефакт на диске. Намного выгоднее ехать на том, что уже лежит в системе и не режет глаз ни администратору, ни части телеметрии. Отсюда и типичный набор, который регулярно всплывает в расследованиях: shell, интерпретатор, сетевой клиент, архиватор, ssh-инструментарий. Для EDR это неудобный класс активности, потому что сам бинарь здесь редко является индикатором. Решает уже связка - кто запустил процесс, с какими аргументами, что пошло следом и во что это вылилось на уровне файлов, сети и дочерней цепочки. в аналитике по T1059 как раз и акцентирует внимание на необычных сочетаниях интерпретаторов с сетевыми и административными утилитами.

Data exfiltration через легитимные каналы: DNS, HTTPS, SSH tunneling​

С выносом данных на Linux работает та же логика. Самый неудобный для детекта трафик идёт не по экзотическим каналам, а по тем, что в инфраструктуре и так считаются штатными. В ATT&CK это укладывается в T1048 - Exfiltration Over Alternative Protocol. Внутри техники MITRE отдельно перечисляет HTTP/S, DNS, FTP, SMTP, SMB и другие протоколы, а для Linux прямо упоминает использование curl для передачи данных наружу.

Проблема здесь не в протоколе как таковом. Проблема в том, что HTTPS, DNS и SSH на Linux почти всегда уже есть в нормальной жизни хоста. Поэтому детект упирается не в сам факт соединения, а в контекст. Какой процесс открыл канал. Когда это произошло. Насколько типичен объём. Куда именно ушёл трафик. Есть ли у этого хоста вообще причина так работать.

MITRE ATT&CK маппинг: T1059 (Command Scripting), T1048 (Exfil over Alt Protocol)​

Для первой стадии post-exploitation на Linux удобно держать в голове две опоры. Первая - T1059, в первую очередь T1059.004 Unix Shell. Это вся зона вокруг командных интерпретаторов, скриптов, shell-цепочек и выполнения команд через штатную среду. Вторая - T1048, где живёт вынос данных поверх легитимных протоколов. Этого уже достаточно, чтобы не расползаться в десяток техник раньше времени и при этом не потерять каркас.

Практическая польза такого мэппинга не в красивой ATT&CK-таблице, а в выборе источников данных. Для T1059 советуют смотреть на процессное выполнение, аргументы командной строки, родительские процессы и нетипичные цепочки вокруг shell и интерпретаторов. Для T1048 уже важны сетевые соединения, auditd-события уровня execve и connect, а также сетевые потоки, если они вообще собираются в контуре. На Linux этого обычно хватает, чтобы отделить "в системе есть bash и curl" от более неприятного вопроса: почему именно этот хост, именно этот процесс и именно сейчас ведёт себя так, будто его кто-то уже использует как рабочую площадку.

Persistence и Privilege Escalation​

Crontab injection и systemd timer/service - T1053, T1543​

На Linux persistence часто выглядит скучно. И именно поэтому живёт долго. cron, systemd timers и service units не выглядят как "специальный механизм злоумышленника" - это штатные точки запуска, которыми и так пользуется админка, автоматизация и половина инфраструктурного кода. В ATT&CK это разложено по нескольким техникам: cron идёт как T1053.003, systemd timers - как T1053.006, а создание или изменение системных процессов через systemd service - как T1543.002.

Практический смысл здесь простой: противнику не нужен экзотический автозапуск, если в системе уже есть нормальный механизм, который переживает ребут, не режет глаз и укладывается в обычную эксплуатацию. Для EDR это неприятный класс активности, потому что сам факт существования timer'а, unit'а или cron-задачи ничего не говорит.

2.webp


LD_PRELOAD hijacking: перехват функций стандартной библиотеки​

LD_PRELOAD - хороший пример техники, которая на бумаге выглядит почти академически, а в живой Linux-среде остаётся неприятной именно из-за легитимности механизма. Сам dynamic linker и переменные вроде LD_PRELOAD нужны системе не "для атак", а для нормальной загрузки библиотек, отладки и подмены поведения в контролируемых сценариях. В ATT&CK это формализовано как T1574.006 Dynamic Linker Hijacking.

Для post-exploitation здесь важен не сам трюк, а класс злоупотребления. Если выполнение начинает зависеть от переменных окружения, shell-инициализации, путей к .so и поведения загрузчика, то часть вредоносной логики уезжает в область, где сигнатурный детект быстро тухнет. Linux Detection Engineering у Elastic отдельно разбирает LD_PRELOAD именно как persistence-механизм в user space и показывает, почему это плохо выглядит в общей телеметрии: имя процесса нормальное, исполняемый файл может быть нормальным, а грязь прячется в окружении, linker flow и загруженных библиотеках.

Отсюда и нормальная линия наблюдения. Не "ищем слово LD_PRELOAD в вакууме", а смотрим на связку: кто выставил переменную, где лежит библиотека, почему .so внезапно живёт не там, где ей положено, и какой процесс потом стартует в этом контексте. MITRE прямо советует ловить неожиданные LD_PRELOAD и родственные linker variables в shell startup scripts и environment exports, создание подозрительных .so в пользовательских путях и их корреляцию с аномальным запуском процессов.

SUID/capabilities abuse: GTFOBins для privilege escalation​

С SUID на Linux всё давно понятно: если в системе есть setuid/setgid-бинарь с неудачной логикой или избыточными правами, это уже готовый класс злоупотребления. фиксирует это как T1548.001 Setuid and Setgid. Там же прямо сказано, что при установленном setuid/setgid программа запускается в контексте владельца или группы, а не текущего пользователя.

Практическая боль здесь не в самом существовании SUID. На Linux его хватает в нормальной системе. Боль начинается там, где привилегированный бинарь можно использовать не так, как задумывалось, или где команда годами не проверяла, что именно у неё вообще выставлено как setuid/setgid и с какими возможностями. Поэтому вся зона вокруг GTFOBins, SUID и file capabilities так живуча: это не "эксплойт", а злоупотребление уже доверенным механизмом повышения прав. В ATT&CK capabilities отдельно как sub-technique не вынесены, но по смыслу это тот же неприятный класс - минимально шумное расширение прав через уже существующую доверенную конфигурацию.

Для EDR и хостовой телеметрии здесь снова работает контекст. Подозрительным становится не просто запуск setuid-бинаря, а нетипичный пользователь, странная родительская цепочка, непривычные аргументы, всплеск дочерних процессов, неожиданная смена контекста безопасности и следом - действия, которые не бьются с обычной ролью процесса.

Defense Evasion как проблема наблюдаемости​


3.webp


bash_history: HISTCONTROL, HISTFILE, timestomping​

История shell на Linux - плохой источник для одиночного детекта и хороший источник для несостыковок. Bash сам документирует, что по умолчанию читает и пишет историю в файл, заданный HISTFILE, обычно ~/.bash_history, а поведение записи зависит от HISTCONTROL, HISTIGNORE и режима самой сессии. В ATT&CK это давно формализовано как T1070.003 Clear Command History: противник может удалять историю, не сохранять отдельные команды или вообще жить в сессии, где ожидаемого следа не появится.

Практически это означает неприятную вещь: отсутствие или странная "стерильность" bash_history часто полезнее, чем сам файл. Пустая история у активного пользователя, резкие разрывы во времени, подозрительно короткий набор последних команд, дублирующиеся хвосты после долгой интерактивной работы - всё это уже не мелочь, а нормальный повод смотреть глубже в execve, родительские цепочки и параллельные артефакты сессии. Сам по себе bash_history на Linux никогда не был источником истины, и пытаться строить на нём детект в одиночку - верный способ утонуть в ложной уверенности.

Log tampering: utmp/wtmp/btmp, journalctl​

С логами на Linux проблема похожая, только грязи больше. ATT&CK выделяет очистку или вмешательство в системные журналы как T1070.002 Clear Linux or Mac System Logs. При этом Linux сам ведёт несколько разных слоёв учёта. utmp хранит текущее состояние входов в систему, wtmp - историю логинов и логаутов, btmp - неуспешные попытки входа. Это не текстовые файлы, а бинарные записи, которые читаются специальными утилитами вроде last и utmpdump.

Для расследования здесь важен не сам факт "лог изменили", а рассинхрон. wtmp говорит одно, journald - другое, shell-активность не бьётся с учётными записями, а сетевые события живут своей жизнью. journalctl в systemd-среде читает записи systemd-journald, то есть сам по себе даёт ещё один слой, который приходится сверять с /var/log/*, login accounting и процессной телеметрией. На Linux аккуратное вмешательство в один источник редко делает картину чистой целиком - почти всегда начинает торчать шов между соседними артефактами.

Timestomping файлов: touch -r и маскировка времени модификации​

С временными метками на Linux тоже нет магии. прямо описывает, что у файла есть atime, mtime и ctime: чтение и исполнение влияют на access time, запись в данные - на modification time, а изменение атрибутов и inode-состояния - на change time. При этом atime и mtime можно менять напрямую, а ctime из user space не выставляется произвольно - он обновляется как побочный эффект изменения состояния файла. Именно поэтому timestomping на Linux почти никогда не сводится к одному красивому mtime.

Для защитника это удобная точка. Если у файла "ровный" mtime, но ctime не совпадает по логике с ожидаемой жизнью объекта, если время на диске не бьётся с появлением процесса, unit-файла, cron-задачи или сетевой активностью, значит смотреть надо не на один timestamp, а на всю цепочку. На Linux временные метки работают не как самостоятельный индикатор, а как источник трения между файловой системой и остальной телеметрией. Проверяется это быстро:
Bash:
stat suspicious_file
stat как раз и показывает набор временных меток рядом, без гадания по одному полю.

Продвинутые техники​


4.webp


SSH-agent hijacking через SSH_AUTH_SOCK - T1563.001​

С ssh-agent вся неприятность в том, что атака идёт не через новый логон, а через уже доверенный контекст. ATT&CK сейчас прямо выделяет SSH Hijacking как T1563.001 и описывает его именно как захват существующей SSH-сессии, а не как обычное использование валидных учётных данных. Для Linux это особенно неудобно, потому что след на уровне "кто вошёл в систему" может вообще не меняться - меняется только то, кто начал пользоваться уже открытым auth-контуром. Отсюда и характерная слепая зона. Если защита ждёт новый логон, новый ключ или новую интерактивную сессию, она уже опоздала.

Process injection через/proc/pid/mem - fileless code execution​

С /proc/[pid]/mem история ещё жёстче. ATT&CK уже выделяет это в отдельную под-технику T1055.009 Proc Memory: работа с памятью живого процесса через /proc ради выполнения кода в чужом адресном пространстве. Здесь и кроется весь дискомфорт для Linux EDR - нового исполняемого файла может не появиться вообще, а активность уходит в существующий процесс, который для части телеметрии уже выглядит "нормальным".

Но невидимой эта зона не становится. Выигрыш атакующего здесь не в полном исчезновении, а в том, что многие user-space сенсоры видят уже следствие, а не сам момент подмены. Для расследования это одна из тех техник, где важен не красивый IOC, а грубая телеметрия доступа к procfs, несвойственный процессу интерес к чужой памяти и странная жизнь процесса после такого доступа.

eBPF-based rootkits: BPF программы для перехвата syscalls​

С eBPF конфликт уже давно вышел за рамки "новой интересной фичи Linux". Тот же механизм, на который опираются современные сенсоры наблюдаемости, даёт атакующему очень близкую к ядру точку влияния. ATT&CK в таких случаях формулирует проблему шире - как T1014 Rootkit: сокрытие программ, файлов, соединений и других компонентов системы через перехват и подмену системной информации. Для eBPF это особенно неприятно, потому что борьба идёт не вокруг user-space маскировки, а вокруг того, кто именно формирует картину происходящего на хосте.

Если заинтересовала тема eBPF, rootkit-логики и борьбы за источник наблюдаемости, могу посоветовать вам наш разбор: "Безопасность операционных систем: Атаки на механизмы безопасности ядра". Там мы подробно раскрыли саму идею того, что инструмент наблюдаемости и механизм защиты легко превращаются в поверхность атаки, если смотреть на них, как на код и привилегии.

Вместо заключения​

Сейчас Linux post-exploitation держится в основном на штатных механизмах системы. Shell, systemd, cron, ssh-agent, procfs, память процесса, eBPF - всё это нормальные части Linux, и именно поэтому вокруг них так много проблем с наблюдаемостью. Защита здесь часто проигрывает не потому, что "ничего не видит", а потому, что видит слишком много легитимной активности и не всегда может быстро отделить рабочее поведение хоста от пост-компрометации.

На Linux почти бесполезно смотреть на один артефакт в отрыве от остальных. bash_history без execve и process tree мало что даёт. systemd unit без контекста его появления - тоже. То же самое с SSH_AUTH_SOCK, доступом к /proc/[pid]/mem, временными метками файлов и системными журналами. Отдельно это всё может выглядеть терпимо. Вместе - уже складывается в понятную картину.

Поэтому нормальный разбор Linux post-exploitation всегда упирается в корреляцию. Кто запустил процесс. Что было в аргументах. Какие сокеты и файлы он трогал. Что происходило рядом по времени. Где начали расходиться артефакты. На этом уровне и становится видно, насколько защита вообще готова к работе с Linux-хостом, а не просто к сбору телеметрии с него.
 
Последнее редактирование:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab