Несмотря на то что Windows остается самой распространенной ОС, о чем знают в том числе атакующие, нельзя оставлять без внимания другие системы, а уж тем более Linux (ладно-ладно, GNU/Linux). Сегодня российские компании все чаще пользуются Linux из соображений импортозамещения, но эта ОС по-прежнему более распространена именно как серверное решение.
А теперь представьте ситуацию: вы работаете на Linux-машине, и вдруг что-то явно идет не так. Уровень нагрузки на процессор резко вырос, начались обращения на неизвестные ресурсы или пользователь www-data неожиданно оказался в группе wheel. Что делать?
Составляем список команд
У вас есть два пути: либо работать с живой системой, либо делать так называемый пост-анализ. Начнем с первого. Я приведу свой список избранных и наиболее часто используемых команд. Универсального порядка здесь нет: вы, как ИБ-специалист, расставляете приоритеты самостоятельно.
Итак, команды.
Помимо базовых команд на просмотр текстовых файлов (а все мы знаем, что в Linux, по сути, все есть файл) типа cat ~/.bash_history, можно использовать более продвинутые варианты:
tail -n 15 /var/log/<file> по умолчанию выводит 10 строк, но при помощи параметра n их количество можно изменять.
tail -f -s 5 /var/log/<file> используется для отслеживания появления новых строк. Это аналог команды watch для тех же журналов. Может быть полезна для отслеживания определенных событий в реальном времени.
grep ― без этой команды предыдущие две могут оказаться бесполезными. Не устану повторять, что grep — наш лучший друг, и не владеть его синтаксисом хотя бы на базовом уровне — просто преступление. В ИБ это так же важно, как уметь гуглить.
Например, историю входов пользователей можно посмотреть разными способами. Если мы имеем дело с SSH-протоколом (один из наиболее популярных способов удаленного управления хостом), можно использовать:
cat /var/log/auth.log | grep "sshd". Фильтрует логи аутентификации исключительно по демону sshd.
cat /var/log/auth.log | grep -iE "session opened for|accepted password|new session|not in sudoers". Помимо базовых сведений о начале и конце сессии, в журналах аутентификации могут быть sudo incidents — нарушения правил, заданных в файле /etc/sudoers. Атакующие не всегда применяют хитрые способы локального повышения привилегий (например, целенаправленное использование уязвимостей системы), поэтому иногда их можно отследить через ошибки выполнения команд sudo.
Основные параметры: -v (исключение параметров), -i (нечувствительность к регистру), -E (регулярные выражения, базовый Egrep), -P (тоже регулярки, но Perl-совместимые), -a — бинарные как файл. Я бы еще добавила -l, -w, -r, -o, но совсем уж переписывать man не хочется. Оставим это в качестве ДЗ :)
find поможет найти нужные файлы не только по имени или маске, расширению, размеру и правам доступа, но и по временным меткам. Например: find / -mtime -2 -ls выводит последние файлы, измененные за два дня.
На практике часто встречаются ситуации, когда все начинается с единичного события. Предположим, ИБ-специалисты зафиксировали выполнение подозрительного файла на хосте N 1 января в 10 утра (pivot point). В этом случае мы можем задать конкретные рамки, включая имеющуюся временную метку, чтобы узнать, что происходило в системе до и после. Для этого используем команду find -newerct "01 Jan 2023 09:00:00" ! -newerct "01 Jan 2023 11:00:00" -ls | sort.
Отмечу, что при помощи find можно не только искать файлы, но и выполнять с ними конкретные действия. Так, можно собрать имеющиеся в заданном каталоге веб-страницы и проверить по хешам, нет ли среди них свежих веб-шеллов: find . type f -exec sha256sum {} \; 2> /dev/null | grep -Ei '.php|.jsp' | sort.
ps auxwf ― дерево процессов. Все привыкли к ps aux, но обратите внимание: здесь есть дерево; netstat -plunto показывает информацию о текущих сетевых соединениях, активных сетевых процессах и сокетах с адресами. Netstat входит в пакет net-tools, поэтому его придется устанавливать, что не всегда возможно. Альтернатива — ss -tupln. Утилита ss также выведет имена процессов с текущими TCP/UDP-соединениями.
last -Faiwx отображает информацию о последних сеансах входа пользователей системы (читает файл /var/log/wtmp);
ls -lta ― привычный всем листинг директории. Важный нюанс: параметр t, сортирующий по дате изменения;
lsof -V используется, чтобы понять, какие файлы открыты и чем заняты. Можно смотреть точечно:
- lsof -i TCP:22 — поиск процессов, работающих на конкретном порту;
- lsof -i -u root информирует, какие файлы и команды использует пользователь;
- lsof -p 1 — поиск по PID.
stat — заключительная команда, которая позволяет смотреть временные метки файлов (а еще, к примеру, информацию о владельце). Здесь есть небольшие особенности. Например, метки создания файла в файловой системе Ext2/3 нет, но есть в Ext4. На этот случай существует statx (stat extended): утилита использует иные системные вызовы, но представленные только начиная с версии ядра 4.11, что нужно учитывать. Дополнительно можно установить istat, работающую на уровне inode, из набора утилит Sleuth Kit.
Ищем аномалии
Итак, команды мы знаем, но что конкретно хотим найти? Запомните: мы всегда ищем аномалии. Здесь нет универсального рецепта, у каждой системы и инфраструктуры они свои. К примеру, вы знаете, что ваши админы — счастливые люди и крепко спят по ночам, поэтому если замечаете вход в систему в два часа ночи, стоит это перепроверить.
Обращайте внимание на каждый параметр: данные пользователя, псевдотерминал это или нет, длительность сессии, время ее начала и окончания, хост-источник.
С сетевыми соединениями (прежде всего установленными), как правило, проще — особенно если ваша система в принципе не должна взаимодействовать с внешним миром. Но аномальные подключения — это не всегда про внешние адреса. Поэтому важно понимать, что происходит у нас в системе, какое установлено прикладное ПО, как оно работает и с чем взаимодействует. Так будет куда проще определить нелегитимную активность.
Используем артефакты
Что если мы наверняка знаем, что хост скомпрометирован? Какие данные нам понадобятся в первую очередь? Приведу тот самый топ-10 артефактов.
1. Прежде всего, на входе у нас есть базовая информация (например, хостнейм и IP-адрес). Скорее всего, мы уже знаем ее сами или от администраторов. В первую очередь стоит убедиться в достоверности этих данных, а также проверить все сетевые интерфейсы (все ли подняты, есть ли публичные адреса?). Отдельно смотрим установленную временную зону: при разборе инцидента это важно, поскольку системные логи обычно пишутся в текущей временной зоне, а с логами приклада все сложнее.
Дополнительно, не на первом этапе, я бы забрала информацию о маршрутах (iptables/netfilter) и каталог /proc/, который содержит командные строки процессов (/proc/[PID]/cmdline). Впоследствии это может пригодиться: например, чтобы выявить файл, который был удален, но процесс которого все еще активен.
2. Лог-файлы. Журналов много, но не все они одинаково полезны. Здесь сложно ограничиться конкретным списком и забыть об остальном. Тем не менее есть ряд основных логов, на которые стоит обратить внимание в первую очередь. Далее я буду приводить конкретные каталоги с файлами, но помните, что здесь могут быть отличия в зависимости от того, какая у вас система — Red-Hat- или Debian-подобная. Например, если мы говорим о логах аутентификации, то для Debian это var/log/auth.log, а для Red Hat — /var/log/secure.
/var/log/lastlog — записи о времени последнего входа в систему каждого пользователя;
/var/log/btmp — неудачные логоны (на основе этого файла удобно отслеживать брутфорсы);
/var/log/wtmp — все входы и выходы пользователей в систему и из нее с момента создания этого файла;
/var/log/cron — события планировщика задач cron. Какие задачи и когда создавались, выполнялись и т.д.;
/var/log/apt/history.log (/var/log/dpkg) — манипуляции с пакетами. Обращаем внимание не только на установленные в данный момент приложения, но и на те, которые устанавливались ранее. Это полезно, когда нужно проверить данные в ретроспективе. Для более быстрого поиска можно использовать следующие команды:
- cat /var/log/dpkg.log | grep installed
- cat /var/lib/dpkg/status | grep -E "Package:|Status:"
/var/log/audit/audit.log — хорошо, когда auditd установлен. А еще лучше, если он настроен и работает с нужным конфигурационным файлом .
3. История вводимых команд /.bash_history. Нужно не только уметь читать логи, но и понимать команды, их последствия и потенциальные возможности (все же помнят, что командой less можно не только читать файлы, но и вносить изменения, получать полноценный интерактивный шелл… Не помните? Тогда вперед — изучать GTFOBins). По умолчанию история команд логируется без временных меток, что может доставить ряд неудобств в будущем: далеко не все собирают журналы с хоста на лету, а уж тем более команды, введенные пользователем. Но вы можете избавить себя от лишних проблем — благодаря следующей команде временные метки будут добавляться к каждой введенной команде:
export HISTTIMEFORMAT="%d.%m.%Y %H:%M:%S " >> ~/.bash_profile
4. Работа с файловой системой заслуживает отдельного внимания. В Windows (а точнее, файловой системе NTFS) есть главная файловая таблица MFT, но в Linux схожего файла нет. Однако можно сгенерировать его самостоятельно при помощи команды ниже, а затем делать собственный таймлайн и использовать его при построении супертаймлайна:
find "${MOUNTPOINT}" -xdev -print0 | xargs -0 -c "%Y %X %Z %A %U %G %n" >> timestamps.dat
Обращайте внимание на недавно измененные файлы, файлы, измененные во временных рамках инцидента, а также скрытые файлы (начинаются со знака «.»), которые могут быть как легитимны, так и намеренно скрыты злоумышленниками. Проверяйте, куда ведут символические ссылки и какой размер у файлов: большой объем может свидетельствовать о выгрузке данных или подготовке к ней. Таким образом можно обнаружить и некоторые инструменты. Не менее важный момент — разрешения. В первую очередь должны бросаться в глаза биты разрешения setuid и setgid, флаги на исполнение и запись для отдельных файлов. Кстати, так можно параллельно найти в системе файлы с явно избыточными правами.
5. Чтобы иметь более полное представление о системе, нужно знать, кто с ней работает ― пришло время учетных записей. Сколько у вас реальных пользователей (учитываем, что при установке прикладного ПО под него обычно создается одноименная или схожая по именованию учетная запись)? Какие у них права в системе и гибко ли они настроены? А может, все пользователи состоят в группах sudo/wheel? Если веб-сервис крутится на этом сервере, он не должен обладать полноценным командным интерпретатором типа /bin/bash или /bin/sh. Увидели что-то подобное? Нужно понять, это legacy или произошло совсем недавно. Найти подобных пользователей и перепроверить их можно так:
find . -name passwd -exec grep -P -H sh$ {} >> ../processed/shell-users.txt \;
Дополнительно я проверяю криптостойкость паролей (хранятся в файле /etc/shadow) при помощи John the Ripper или hashcat. Дальше — в зависимости от результата. Как минимум, можно сообщить администратору или владельцу сервиса, что слабые пароли — плохая практика. Как максимум — найти еще одну зацепку в цепочке недопустимых событий. И конечно, не забудьте заглянуть в домашние каталоги пользователей.
6. Самая интересная часть — публично доступные приложения. Для начала лучше хотя бы на базовом уровне прояснить для себя архитектуру исследуемого сервиса: какие средства безопасности используются (и есть ли они вообще), какой стек технологий (и имеются ли уязвимые компоненты), а также изучить файлы конфигураций и логи (могут настраиваться отдельно в конфигурационном файле). При просмотре журналов снова разбираем каждый параметр. Например, access.log веб-сервиса: выстраиваем картинку по времени (значительный рост запросов в определенное время — это краулер прошелся или нет?). Как вариант, можно извлечь все уникальные IP-адреса, подобрав подходящее регулярное выражение (не нужно досконально выверять правильность каждого октета: то, что в корне неверно, вы легко откинете вручную), и собрать статистику.
grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" file.txt | sort | uniq -с | sort
Особое внимание обратите на «лидеров», причем как в начале, так и в конце списка. Дополнительно можно обогатить данные информацией о местоположении этих адресов.
Аналогично выделяем уникальные URI и частоту их запросов, размер и время ответов сервера, а также тип приложения клиента User-Agent. Некоторые инструменты в явном виде указывают свое название в данном поле, и мало кто его меняет. Здесь сложно привести универсальную команду, однако есть пара лайфхаков. К примеру, для вывода конкретных столбцов можно использовать awk '{print $1 $3}' file, которая позволит вывести столбцы 1 и 3 в заданном файле.
Учитывайте, что по умолчанию awk использует пробел как разделитель. Чтобы изменить символ-разделитель, используйте параметр -F. Но будьте внимательны: если символов в параметре больше одного, все выражение будет восприниматься как регулярное.
Также не забываем смотреть специальные публикуемые директории (если имеем дело с веб-приложением, не завалялась ли там парочка веб-шеллов?). Помимо журнала обращений access.log не стоит пренебрегать журналом ошибок error.log, ведь ошибки в приложении могут возникать и при совершении злонамеренных действий.
7. Переходим к отдельной ветке — техникам закрепления. Как ни крути, их лучше проверять отдельно. Мест здесь действительно много, достаточно взглянуть сюда:
Просматривать, скорее всего, придется всю схему, хотя все зависит от инцидента: бездумно бросаться от одного к другому не стоит. Эту задачу можно автоматизировать, но, если речь идет о базовом уровне, в первую очередь проверяем запланированные задачи cron и сервисы — это наиболее распространенные техники.
Нужно всегда иметь представление, какой сервис и за что отвечает. Повторюсь: знать, что происходит в системе, крайне важно.
8. Далее — файлы конфигураций, хранящиеся в каталоге /etc/. Конечно, вы уже обратили внимание на изменения при работе с файловой системой (п.4), но ведь никто не отменял таймстомпинг, верно? Убедитесь, что все известное вам прикладное ПО работает так, как и должно, особенно самописные приложения. К слову, вы ведь помните, что лог-файлы могут ротироваться? Полезно сразу уточнить, какие и когда, — в файлах /etc/logrotate.conf и/etc/logrotate.d/*.
9. Нельзя не упомянуть про данные приложений — отдельные файлы, создающиеся при работе приклада, чаще всего под конкретного пользователя. Они хранятся в домашних директориях и скрыты от рядовых юзеров.
Обычно это каталоги ~/.local/share/<app>/* и ~ /.config/<app>/* — в соответствии со спецификацией xdg base directory. Некоторые приложения игнорируют этот стандарт и создают собственные скрытые каталоги прямо в корне домашней директории (~/.<app>), а временные лог-файлы — в ~/.local/cache/<app>/*. Здесь можно найти не только историю браузера и настройки текстового редактора, но и кое-что интересное: например, историю команд и просмотренных директорий через Midnight Commander. Та же история команд, но уже выполненная через ранее упомянутый less (GTFOBins!).
10. В Windows-среде в числе популярных среди атакующих директорий можно выделить %APPDATA%, %PROGRAMDATA% или %TEMP%. В Linux тоже есть свои любимчики:
/tmp и /var/tmp — каталоги временных файлов;
/dev/shm — так называемый tmpfs (система виртуальной памяти для реализации механизма межпроцессного взаимодействия IPC);
/var/run — каталог для хранения системных данных, описывающих систему с момента последней ее загрузки (/var/run – символическая ссылка на /run, оба каталога существуют ввиду вопроса совместимости);
/var/spool — каталог временных данных, ожидающих постобработки, после которой они будут удалены;
Если ваше расследование зашло в тупик, рекомендую удостовериться, что в этих каталогах нет ничего лишнего.
Снимаем триаж
Мы обозначили наиболее критичные места, которые будем проверять в первую очередь. Получилось не так уж и мало. А если еще и машина не одна? Как собирать, как анализировать?
Всем респондерам не понаслышке известен термин «триаж» — набор значимых криминалистических артефактов. Несмотря на то что мы отчасти криминалисты, массово собирать образы во время активной фазы реагирования — пагубное дело. Если говорить простыми словами, есть определенный перечень мест, куда тот же криминалист посмотрит в первую очередь, даже если у него есть полный образ системы. Это и есть триаж. Образ для первичного анализа вероятнее всего будет избыточен, тем более когда счет идет на минуты.
Для снятия триажа существует масса готовых инструментов, но можно сделать скрипт для сбора данных самостоятельно. Учитывайте важные для вас параметры, например кроссплатформенность или совместимость. Но не забывайте, что все давно написано и сделано за нас, поэтому главное — поискать, проверить перед использованием и при необходимости дополнить. На GitHub полно отличных инструментов.
Я бы хотела обратить внимание на две утилиты — CatScale и uac. Первая, к примеру, удобна тем, что собирает практически все, о чем я упоминала выше. Кроме того, она удобно архивирует собранные данные в отдельные файлы и потом разбирает отдельно прилагающимся скриптом. С ней сразу идут конфиги для Logstash, и вам не придется выполнять двойную работу при парсинге данных. Утилита uac же собирает все и даже больше. Например, не просто измененные файлы в /etc/, а всю директорию полностью, что бывает крайне полезно. Также она хорошо работает с уже упомянутым statx и генерирует отличный bodyfile. Среди других важных преимуществ — общая поддержка nix-подобных систем (MACOS, AIX, ESXi и др.).
Если нужно собирать данные массово, на помощь придут оркестраторы типа Ansible, Hashicorp Nomad, Chef, Puppet, SaltStack. Хорошо, если у вас уже настроено какое-либо подобное средство централизованного управления, иначе придется мастерить небольшие костыли.
Анализируем систему
Переходим к анализу. Если учесть, что анализ Linux-систем обычно сводится к скрупулезному изучению логов, то начинаем мы с базовых команд типа tail, more, less и grep. Уровень чуть выше — добавляем find для поиска и обработки нескольких файлов (вы же помните про параметр exec?). Также используем sort в связке с uniq и wc. Чаще всего они идут вместе: перед использованием uniq нужно отсортировать все через sort, а wc пригодится для подсчета статистики. Также отмечу sed и awk: первая нужна для выполнения хотя бы базовых замен, вторая ― для вывода определенной колонки (как минимум!). Примеры мы уже рассмотрели ранее. И конечно же, grep с регулярными выражениями! Призываю не бояться их, хотя точно знаю, что на начальном уровне они пугают. Но они и здорово выручают, поэтому настоятельно рекомендую принять и полюбить. И не забудьте про пайпинг (пайп — это символ “|”) ― передачу потока вывода из одной команды в другую.
Если совсем не любите командную строку и все ее интерпретации, замечательная альтернатива — продвинутые текстовые редакторы типа Notepad++ (про который, кажется, знают уже все) и EmEditor. Главные преимущества второго — возможность открытия и быстрого анализа файлов большого (экстрабольшого) размера, гибкая фильтрация и поиск, а также удобство работы с файлами DSV (delimiter-separated values).
Если мы имеем дело с большим объемом данных, то рано или поздно упремся в потолок, да и получить хотя бы минимальную визуализацию не выйдет. Здесь не обойтись без эластика (стека ELK), splunk, graylog — выбирайте, что вам ближе. Главное — помнить, что тот же Elastic с Kibana могут замечательно работать без написания громоздких конфигов Logstash за счет встроенных grok-паттернов. Перед тем как писать что-то самостоятельно, не забывайте гуглить: все давным-давно придумано за вас и для вас.
Еще одна важная утилита — ChopChopGo. Это инструмент для просмотра журналов Linux наподобие chainsaw и Hayabusa, отлично показавших себя при общем анализе системных журналов Windows (через Sigma-правила). Есть нюанс: на момент написания этого материала у утилиты нет возможности загрузки данных из сторонних систем. Можно попробовать альтернативу — Zircolite для журналов подсистемы аудита auditd и Sysmon для Linux. Кроме того, при желании вы всегда сможете воспользоваться теми же Sigma-правилами и конвертером.
Как расследовать инциденты в Linux
1. При реагировании «здесь и сейчас» определяем порядок своих действий в зависимости от инцидента и с помощью ранее описанных или схожих команд ищем аномалии в системе. Для каждой инфраструктуры они уникальны: ищем то, что несвойственно для нашей. В зависимости от исследуемого артефакта обращаем внимание на каждый параметр: будь то данные о пользователе, длительность его сессии или открытые соединения.
2. Используем артефакты — данные, которые понадобятся в первую очередь. Самые важные: базовая информация о системе; лог-файлы; история вводимых команд; файловая система; данные о пользователях; опубликованные в интернете приложения; места закрепления; файлы конфигураций; данные приложений и самые популярные среди атакующих каталоги.
3. При проведении удаленного реагирования или пост-анализа снимаем триаж с помощью существующих инструментов или пишем собственный скрипт.
4. Анализируем систему аналогичным образом, в первую очередь исследуя ранее обозначенные артефакты.
Как ни крути, рано или поздно скриптовать придется. Например, мы понимаем, что уже в который раз сталкиваемся с одной и той же задачей, и повторять одинаковые действия надоедает. Поэтому автоматизируем все, что только возможно: на баше, питоне, других языках высокого уровня. Кому-то вообще будет удобно всю работу выполнять через PowerShell, несмотря на то что вы взаимодействуете с данными другой ОС. Разницы нет, главное — понимать, что делать, знать свои возможности и умения, а также существующие временные рамки. Не время начинать изучать питон, потому что все кругом его нахваливают, когда у вас за спиной «хата в огне».