Настройка auditd для обнаружения и расследования инцидентов информационной безопасности

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Одной из важных составляющих информационной безопасности инфраструктуры компании является SIEM - система управлением событиями и информацией безопасности. Такую систему можно условно поделить на 2 основные части — подсистему сбора событий и подсистему анализа полученных событий. Правильная настройка первой поможет обнаружить вторжение на ранних этапах проникновения, облегчит написание событий тревоги (алертов), а если вас всё-таки взломали, то позволит разобраться, как и почему это произошло, какие действия выполняли злоумышленники. Основным инструментом для сбора системных событий в линукс-системах является auditd. На основе этого инструмента созданы и другие, например, auditbeat, go-audit, которые дополняют основной функционал auditd. Поэтому, разобравшись с основными принципами работы базового инструмента, вам не составит труда воспользоваться и всеми остальными.

Структура статьи:

  • Краткое знакомство с инструментом: общее описание auditd, плюсы и минусы, синтаксис;

  • Принципы написания правил: практические советы по специфике инструмента, которые позволят делать меньше ошибок при работе с ним;

  • Как тестировать правила: порядок действий, который позволит внедрить наборы правил в инфраструктуру любого размера;

  • Алгоритм тестирования правил: упорядоченный список действий для проверки отдельно каждого правила и фильтров к нему;

  • Модель угроз: как рассматривать систему с точки зрения атакующего, чтобы ничего не забыть;

  • Пример: применяем полученные знания на практике.

Общее описание auditd

auditd (сокращение от Linux Audit Daemon) — нативный инструмент предназначенный для мониторинга событий операционной системы и записи их в журналы событий, разрабатываемый и поддерживаемый компанией RedHat. Был создан для тесного взаимодействия с ядром операционной системы — во время своей работы наблюдает за системными вызовами и может записывать события — чтение, запись, выполнение, изменение прав - связанные с файлами ОС. Таким образом, с его помощью можно отслеживать практически любые события, происходящие в операционной системе.

Плюсы auditd:
- работает на низком уровне мониторинга — отслеживает системные вызовы и действия с файлами;
- имеет неплохой набор утилит в комплекте для удобства работы;
- постоянно развивается и обновляется;
- бесплатен и легко устанавливается.

Минусы auditd:
- большинство событий, возникающих при атаках характерных для конкретного приложения, практически невозможно отслеживать поскольку на уровне системных вызовов и работе с файлами трудно отличить взлом от нормальной работы приложения. Такие события лучше отслеживать на уровне самих приложений;
- auditd может замедлять работу ОС. Это связанно с тем, что подсистеме аудита необходимо проводить анализ системных вызовов;
- не слишком гибок в настройке правил;
- на данный момент это не лучший инструмент для работы с контейнерами.

Файлы конфигурации и синтаксис

Рассмотрим основные примеры настроек и параметров, которые будут использоваться далее. Более полное руководство по auditd вы можете найти здесь. Основную информацию можно найти в мануалах к auditd и его инструментам.

Файлы конфигурации хранятся в /etc/audit/. Правила желательно хранить в /etc/audit/rules.d/*.rules, по умолчанию доступ к этой директории только у root'а. Обратите внимание на то, что файл с правилами в этой директории должен иметь название *.rules, иначе auditd не прочитает его без явного указания. Если вы решили хранить правила в другом месте, то владелец файла должен быть root. Помимо этого рекомендую выставить группу файла root и права 600, чтобы никто кроме root'а не мог работать с файлом конфигурации auditd, т.к. зная что логируется, атакующий может избежать обнаружения. То же самое касается и файлов с правилами для других инструментов.

Правила для логирования можно добавлять следующими способами:
- записать его в файл(ы) /etc/audit/rules.d/<имя файла>.rules и перезапустить сервис;
- записать в файл по произвольному пути и указать его явно: auditctl -R <путь к файлу>;
- добавить правило утилитой auditctl [-A,-a] <правило>.

Синтаксис

Подробное описание синтаксиса на русском языке можно посмотреть здесь.

-D - удалить все правила. Обычно используется в начале файла, чтобы избежать неожиданностей;
-a [list,action],[action,list] - добавляет правило в конец списка правил. Списки и действия рассмотрим далее.

Основные варианты списков:
exit - Добавить правило к списку, отвечающему за точки выхода из системных вызовов. Этот список применяется, когда необходимо создать событие для аудита, привязанное к точкам выхода из системных вызовов.
exclude - Добавить правило к списку, отвечающего за фильтрацию событий определенного типа. Этот список используется, чтобы отфильтровывать ненужные события. Например, если вы не хотите видеть avc сообщения, вы должны использовать этот список. Тип сообщения задается в поле msgtype.

Варианты действий:
always - установить контекст аудита. Всегда заполнять его во время входа в системный вызов и всегда генерировать запись во время выхода из системного вызова;
never - аудит не будет генерировать никаких записей. Это может быть использовано для подавления генерации событий. Обычно необходимо подавлять генерацию вверху списка, а не внизу, т.к. событие инициируется на первом совпавшем правиле.

-A list,action - добавить правило в начало списка. Например, для удобство чтения правило находится ниже, чем должно быть по логике настроек, тогда можно использовать этот параметр.

-F [n=v | n!=v | n<v | n>v | n<=v | n>=v | n&v | n&=v] - задать поле сравнения для правила. Атрибуты поля следующие: объект, операция, значение. Вы можете задать до 64 полей сравнения в одной команде. Каждое новое поле должно начинаться с -F. Аудит будет генерировать запись, если произошло совпадение по всем полями сравнения. Допустимо использование одного из следующих 8 операторов: равно, не равно, меньше, больше, меньше либо равно, больше либо равно, битовая маска (n&v) и битовая проверка (n&=v). Битовая проверка выполняет операцию «and» над значениями и проверяет, равны ли они. Битовая маска просто выполняет операцию «and». Поля, оперирующие с идентификатором пользователя, могут также работать с именем пользователя — программа автоматически получит идентификатор пользователя из его имени. То же самое можно сказать и про имя группы.

Поля сравнения и их описание:

  • a0, a1, a2, a3 - первые 4 аргумента системного вызова соответственно;

  • arch - так как система ориентируется на номера (не названия) системных вызовов, а для многих системных вызовов номера отличаются для 32 и 64 разрядных систем, то необходимо указывать для какой архитектуры мы пишем правило;

  • auid - ID пользователя, с которым он вошёл в систему. Системные сервисы, как правило, имеют auid=-1 (или 4294967295);

  • dir - директория, за которой необходимо наблюдать. Будут залогированы и все события связанные с файлами и поддиректориями в указанной директории рекурсивно;

  • euid - действительный идентификатор пользователя;

  • exe - полный путь к исполняемому файлу. Может использоваться только с exit;

  • exit - значение, возвращаемое системным вызовом при выходе;

  • key - установка поля для фильтра. Добавляет поле с заданным именем в событие, что облегчает поиск событий в журналах;

  • msgtype - тип события. Весь список событий можно посмотреть здесь;

  • path - полный путь к файлу, за которым необходимо следить, может использоваться только с exit;

  • perm - то же, что и параметр -p, будет рассмотрен ниже;

  • success - если значение, возвращаемое системным вызовом, больше либо равно 0, данный объект будет равен «true/yes», иначе «false/no». При создании правила используйте 1 вместо «true/yes» и 0 вместо «false/no»;

  • uid - идентификатор пользователя;

Вместо числовых идентификаторов пользователей можно указывать имена (www-data, mail, irc), таким образом вам не придется учитывать их числовые различия на разных серверах.

-p - [r|w|x|a] - описывает разрешение доступа файла за которым нужно следить: чтение, запись, выполнение или изменение прав доступа соответственно;
-w <path> - устанавливает наблюдение за директорией (рекурсивно) или файлом;
-W <path> - исключает наблюдение за указанной директорией или файлом.

Стоит упомянуть про встроенные инструменты анализа полученных событий: ausearch, aureport. С их помощью удобно тестировать правила "на месте". Много интересных примеров правил можно посмотреть здесь.

Общие принципы написания правил

Некоторые специалисты предпочитают писать правила максимально широкими, а логику фильтрации и обработки событий уже настраивать в подсистеме анализа событий, чтобы атакующий не знал какие его действия собираются и анализируются. На мой взгляд, у такого подхода есть недостаток: порождается большое количество событий из-за чего могут возникнуть проблемы с производительностью на серверах, где ведется сбор событий, и далее по цепочке архитектуры SIEM, особенно если источников логов много. Помимо этого в большой инфраструктуре сильно возрастает нагрузка по выявлению полезных событий среди общего потока в конечной точке.

Чтобы избежать случаев, когда атакующий может узнать, какие его действия анализируются, нужно установить мониторинг за файлом с правилами логирования таким образом, чтобы при чтении этого файла любым пользователем возникало событие, а также перечислить команды, позволяющие узнать правила без чтения файлов конфигурации такие как audictl -l.
На основе этих событий можно сделать алерты. Если логи передаются по сети, то, помимо установки наблюдения за доступом к правилам, необходимо настроить шифрование данных.

В независимости от того, какой подход будет выбран вами между ними есть много общего и, не смотря на то что в примерах далее почти вся логика будет настраиваться на источнике событий, фильтры/правила можно писать как на стороне источника событий, так и в подсистеме анализа событий (или даже на промежуточном этапе).

При написании правил auditd необходимо учитывать следующее:

  1. Для каждого события отрабатывает лишь то подходящее правило, которое встретилось первым. Поэтому сначала пишутся фильтры и только потом правила. То же самое касается и выбора между несколькими правилами - выше размещать стоит то правило, которое важнее учитывать.

  2. Писать правила лучше от частного к общему. Допустим, вы хотите журналировать действия в директории /etc/. Чтобы потом в логах не искать прикладными утилитами (grep, sed или средствами SIEM) все события, связанные, например, с ssh, sudoers, passwd и т.д., сначала указываете правила для мониторинга конкретных директорий/файлов в /etc/ и только после этого размещаете правило для самой директории /etc/.

  3. В auditd есть преднастроенные правила и иногда возникают ситуации, когда они срабатывают и наши правила не учитываются. Поэтому каждое правило лучше предварительно тестировать отдельно.

  4. Если вы хотите написать правила с целью выявления конкретного случая (атаки, ситуации), то лучше определить общее звено и написать правило для него. Так, например, для обнаружения запуска интерактивных шеллов можно использовать обращения к /dev/tty, /dev/pts/. Чем лучше вы понимаете как работает ваша операционная система, тем лучше. Используя такой подход, злоумышленнику станет тяжелее избежать обнаружения.

  5. Для одного и того же действия с точки зрения пользователя может существовать несколько системных вызовов. Так для открытия файла могут использоваться: open, openat, creat, open_by_handle_at. Об этом стоит помнить, при создании правил на базе выборочных системных вызовов.

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

Как тестировать правила

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

  1. Проверка тестируемого правила на одном сервере. Чем ближе по составу установленного ПО сервер приближен к "боевой" среде, тем лучше. На этом этапе необходимо во-первых смоделировать условия, для которых написано правило, а во-вторых протестировать все возможные варианты поведения сервиса/приложения/пользователя, которые могут вызвать ложные срабатывания.

  2. Проверка тестируемого правила в составе имеющихся других правил. На этом этапе проводим тесты и убеждаемся в том, что всё по-прежнему работает как задумано: другие правила могут перекрывать новое и наоборот.

  3. Проверка нового набора правил на группе серверов. Снова, чем ближе к будущей инфраструктуре будут сервера по составу ПО, тем лучше. При необходимости этот этап можно повторять, увеличивая количество серверов.

  4. Применение правил на всей инфраструктуре. Если по предыдущим пунктам вы убедились в "безопасности" нового набора, то можно применять его на всей инфраструктуре.

Если у вас большое количество серверов, то всегда стоит помнить о том, что какой-то участок вашей инфраструктуры может сработать не так как ожидалось и породить большое количество событий, поэтому пути решения возможных проблем лучше обдумать сразу.

Алгоритм тестирования правил

Для каждого правила в частности будем использовать следующий алгоритм:

  1. Пробуем определить события для отслеживания по формуле:

    AA - SA = IE

    где AA - attacker's actions - набор действий атакующего, SA - service actions - набор действий сервиса в ходе его обычной деятельности, IE - incident events - события инцидента. Положительный результат (события инцидента) в формуле и будет основной целью для нас. Каждый набор действий состоит из системных вызовов и обращений к файлам. Эта формула может быть особенно полезна в случае с обнаружением инцидентов. Если явно выявить события инцидента не получается, то можно определить события, которые помогут при расследовании инцидента: обращения к важным файлам, выполнение команд и пр. На мой взгляд - хорошее правило то, для которого не нужно писать много фильтров и порождает события, по которым с высокой вероятностью можно сказать, что произошёл инцидент.

  2. Пишем правило(а) для набора действий определенных в пункте 1.

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

  4. Пишем фильтры: если мы нашли такие события (п.3) то стоит подумать - можем ли мы от них избавиться. Писать фильтры желательно максимально точно, чтобы не "зацепить" лишних событий. В статье будет предложен вариант с написанием фильтров на хостах-источниках событий.

  5. Моделируем ситуацию: создаём ситуацию, для которой написали правило и убеждаемся, что создаются необходимые события.

Модель угроз

Модель угроз для определения отслеживаемых событий, на мой взгляд, стоит рассматривать аналогично классическому: для обнаружения инцидента определяем все возможные способы взлома (вся информация, которая попадает на сервер), для расследования - вся информация, за которой мы хотим наблюдать. На этом этапе будет полезно устроить мозговой штурм среди коллег с целью составления способов взлома и/или проникновения на сервер в случае с обнаружением инцидента, а также наблюдаемых ресурсов для расследования. Затем можно в каждой из подгрупп провести ранжирование по важности отслеживаемых событий, после чего приступать к написанию правил. Подробную моделирование угроз выполнять не будем, т.к. это отдельная большая тема. Рассмотрим подгруппы подробнее.

Обнаружение инцидентов
С точки зрения логирования будем считать инцидентом ситуацию, при которой у атакующего появилась возможность выполнения команд и/или чтения файлов операционной системы. Для написания правил по обнаружению инцидентов, необходимо понять, каким образом он может вообще возникнуть. Поскольку для взлома сервера на него должны каким-то образом попасть данные от атакующего по сети, то в первую очередь необходимо определить пути попадания такой информации. Это любые сервисы, которые устанавливают соединения наружу и/или принимают входящие соединения. Причем чем раньше мы сможем установить факт компрометации сервера, тем, очевидно, лучше. Основные способы выполнения команд на сервере:
- выполнение уже имеющихся исполняемых файлов (файлы директорий /bin/, /usr/bin/ и т.д.) — самый популярный способ. Например, атакующий получил доступ к командной оболочке напрямую или через имитацию шелла;
- выполнение команд через запись в файлы. Пример — планировщик задач cron. Если вы используете файлы, содержимое которых может быть выполнено как команды системой, то за ними необходим контроль;
- выполнение команд напрямую через системные вызовы — такой способ может применяться, например, в ходе "бинарных" атак: переполнения стека, кучи и т.д.

Что касается файлов, то наша задача определить те, что используется сервисом в обычной деятельности точно исключить такие события, поскольку в случае взлома сервиса, определить аномалию по отношению к таким файлам очень сложно.

Помимо вышеперечисленного, будем опираться на этапы проведения атаки:

  1. Сканирование сервера.
    Злоумышленник производит обнаружение открытых портов на сервере извне.

  2. Атака сервера, эксплуатация.
    На этом этапе злоумышленник каким-либо образом получает возможность чтения файлов, выполнению команд или системных вызовов на сервере. В этот условный этап будем относить все действия атакующего вплоть до момента выполнения любой первой команды и/или чтения первого файла, когда ему необходимо понять, что он смог добиться успеха в проведении атаки.

  3. Взаимодействие с сервером, постэксплуатация.
    Вслед за взломом злоумышленник может попытаться закрепиться на сервере (оставить файл с шеллом, получить ssh-ключ и т.д.), найти информацию для продвижения вглубь инфраструктуры (поиск паролей, токенов в файлах, базах данных и т.д.).

Вы можете воспользоваться как уже имеющимися вариантами, например, mitre, так и использовать свой подход.

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

Пример

Обнаружение инцидентов

Основное отличие при работе по обнаружению инцидентов от расследования - стремление к созданию таких правил, события которых будут означать возникновение инцидента. Кратко: если возникло событие по правилу инцидента, то возник и сам инцидент.

В качестве примера возьмём сервер на котором есть http-сервис и ssh. Для каждого сервиса каждый этап взлома проведем через наш алгоритм. Проведём каждый сервис по этапам атаки через алгоритм, для каждого этапа будем применять формулу. Правила для расследования инцидентов рассмотрим отдельно позже, поскольку они подходят практически для любых видов сервисов. Все примеры ниже приведены на виртуальной ОС ubuntu 18.04, веб-сервер apache.

Будет полезен скрипт для автоматизации наших действий:

#!/bin/bash

killall -9 /sbin/auditd 2>/dev/null; \
systemctl stop auditd; \
systemctl stop apache2; \
sleep 2; \
rm /var/log/audit/audit.log*; \
systemctl start auditd; \
systemctl start apache2; \
auditctl -R /home/ubuntu/auditd/apache.rules > /dev/null 2>&1; \
auditctl -l; \
wc -l /var/log/audit/audit.log

Для быстрого завершения сначала убиваем процессы auditd, останавливаем сервисы auditd и apache2 (иногда без перезапуска apache2 правила по какой-то причине не применяются), удаляем все журналы логов, чтобы в поиске не выдавались старые результаты, запускаем сервисы, читаем правила из файла /home/ubuntu/auditd/apache.rules, проверяем список примененных правил, чтобы убедиться в что они работают и проверяем количество записей в файле лога аудита.

Файл /home/ubuntu/auditd/apache.rules:

-D
<тестируемые правила>

В первой строке -D используется для очистки существующих правил, которые мы могли забыть, чтобы избежать неожиданного поведения.

HTTP-Сервис

HTTP. Сканирование сервиса

  1. Результат: в широком смысле мы можем отслеживать все входящие сетевые соединения, а логику для написания алертов необходимо дополнительно настраивать. В целом - это не лучшее правило для создания событий с целью обнаружения инцидентов, однако в определенных случаях такие правила могут быть полезны.

    HTTP. Атака сервиса

    1. На данном этапе злоумышленник каким-либо образом получил возможность читать файлы ОС или выполнять команды. Можем предположить, что действия атакующего будут затрагивать файлы в директориях /bin/, /usr/bin/, часто пытаются прочитать файл /etc/passwd как в ходе автоматизированной так и при ручной атаках. Действия веб-сервера в большинстве случаев находится в директории /var/www/. Таким образом, возникает идея логировать действия для пользователя www-data везде, кроме директории /var/www.

    2. Далее пишем правила для наших предположений:

      -a never,exit -F dir=/var/www/ -F uid=www-data 
      -w / -F uid=www-data -k apache_alert
    3. Затем переходим к тестированию. После выполнения скрипта check.sh, обратимся к одной из страниц веб-сервера. Сделаем файл /var/www/html/test.php с содержимым:

      <?php phpinfo(); >?

      После этого загружаем через браузер этот файл, останавливаем и запускаем службу:

      Логи
      ----
      time->Thu Aug 12 20:35:45 2021
      type=PROCTITLE msg=audit(1628789745.294:566): proctitle=2F7573722F7362696E2F61706163686532002D6B007374617274
      type=PATH msg=audit(1628789745.294:566): item=0 name="/usr/share/zoneinfo/Africa" inode=2359764 dev=08:01 mode=040755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
      type=CWD msg=audit(1628789745.294:566): cwd="/var/www/html"
      type=SYSCALL msg=audit(1628789745.294:566): arch=c000003e syscall=257 success=yes exit=12 a0=ffffff9c a1=5555bf2ae6a0 a2=90800 a3=0 items=1 ppid=6496 pid=6505 auid=4294967295 uid=33 gid=33 euid=33 suid=33 fsuid=33 egid=33 sgid=33 fsgid=33 tty=(none) ses=4294967295 comm="apache2" exe="/usr/sbin/apache2" key="apache_alert"
      ----
      time->Thu Aug 12 20:35:45 2021
      type=PROCTITLE msg=audit(1628789745.294:567): proctitle=2F7573722F7362696E2F61706163686532002D6B007374617274
      type=PATH msg=audit(1628789745.294:567): item=0 name="/usr/share/zoneinfo/America" inode=2359765 dev=08:01 mode=040755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
      type=CWD msg=audit(1628789745.294:567): cwd="/var/www/html"
      type=SYSCALL msg=audit(1628789745.294:567): arch=c000003e syscall=257 success=yes exit=12 a0=ffffff9c a1=5555bf2a5fa0 a2=90800 a3=0 items=1 ppid=6496 pid=6505 auid=4294967295 uid=33 gid=33 euid=33 suid=33 fsuid=33 egid=33 sgid=33 fsgid=33 tty=(none) ses=4294967295 comm="apache2" exe="/usr/sbin/apache2" key="apache_alert"
      ----
      time->Thu Aug 12 20:35:45 2021
      type=PROCTITLE msg=audit(1628789745.294:568): proctitle=2F7573722F7362696E2F61706163686532002D6B007374617274
      type=PATH msg=audit(1628789745.294:568): item=0 name="/usr/share/zoneinfo/America/Argentina" inode=2359837 dev=08:01 mode=040755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
      type=CWD msg=audit(1628789745.294:568): cwd="/var/www/html"
      type=SYSCALL msg=audit(1628789745.294:568): arch=c000003e syscall=257 success=yes exit=12 a0=ffffff9c a1=5555bf2a7b50 a2=90800 a3=0 items=1 ppid=6496 pid=6505 auid=4294967295 uid=33 gid=33 euid=33 suid=33 fsuid=33 egid=33 sgid=33 fsgid=33 tty=(none) ses=4294967295 comm="apache2" exe="/usr/sbin/apache2" key="apache_alert"
      ----
      time->Thu Aug 12 20:35:45 2021
      type=PROCTITLE msg=audit(1628789745.294:569): proctitle=2F7573722F7362696E2F61706163686532002D6B007374617274
      type=PATH msg=audit(1628789745.294:569): item=0 name="/usr/share/zoneinfo/America/Indiana" inode=2359838 dev=08:01 mode=040755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
      type=CWD msg=audit(1628789745.294:569): cwd="/var/www/html"
      type=SYSCALL msg=audit(1628789745.294:569): arch=c000003e syscall=257 success=yes exit=12 a0=ffffff9c a1=5555bf2a5790 a2=90800 a3=0 items=1 ppid=6496 pid=6505 auid=4294967295 uid=33 gid=33 euid=33 suid=33 fsuid=33 egid=33 sgid=33 fsgid=33 tty=(none) ses=4294967295 comm="apache2" exe="/usr/sbin/apache2" key="apache_alert"
      ----
      time->Thu Aug 12 20:35:45 2021
      type=PROCTITLE msg=audit(1628789745.294:570): proctitle=2F7573722F7362696E2F61706163686532002D6B007374617274
      type=PATH msg=audit(1628789745.294:570): item=0 name="/usr/share/zoneinfo/America/Kentucky" inode=2359839 dev=08:01 mode=040755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
      type=CWD msg=audit(1628789745.294:570): cwd="/var/www/html"
      type=SYSCALL msg=audit(1628789745.294:570): arch=c000003e syscall=257 success=yes exit=12 a0=ffffff9c a1=5555bf2adea0 a2=90800 a3=0 items=1 ppid=6496 pid=6505 auid=4294967295 uid=33 gid=33 euid=33 suid=33 fsuid=33 egid=33 sgid=33 fsgid=33 tty=(none) ses=4294967295 comm="apache2" exe="/usr/sbin/apache2" key="apache_alert"
      ----
      time->Thu Aug 12 20:35:45 2021
      type=PROCTITLE msg=audit(1628789745.294:571): proctitle=2F7573722F7362696E2F61706163686532002D6B007374617274
      type=PATH msg=audit(1628789745.294:571): item=0 name="/usr/share/zoneinfo/America/North_Dakota" inode=2359840 dev=08:01 mode=040755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
      type=CWD msg=audit(1628789745.294:571): cwd="/var/www/html"
      type=SYSCALL msg=audit(1628789745.294:571): arch=c000003e syscall=257 success=yes exit=12 a0=ffffff9c a1=5555bf2ade20 a2=90800 a3=0 items=1 ppid=6496 pid=6505 auid=4294967295 uid=33 gid=33 euid=33 suid=33 fsuid=33 egid=33 sgid=33 fsgid=33 tty=(none) ses=4294967295 comm="apache2" exe="/usr/sbin/apache2" key="apache_alert"
      ...

      Как видим, в логах присутствуют записи, которые мы не ожидали увидеть.

    4. Пишем фильтры. Из получившихся событий мы видим, что пользователь www-data обращается к файлам директории /usr/share/zoneinfo/. Поскольку никакой ценной информации с точки зрения безопасности в этой директории не содержится, мы можем написать фильтр, чтобы избавиться от этих событий:

      -a never,exit -F dir=/usr/share/zoneinfo/ -F uid=www-data

      Тестируем снова, убеждаемся, что эти события пропали из журналов и других "лишних" событий не присутствует. Можем переходить к моделированию поведения атакующего.

    5. Смоделируем условия, при которых атакующий смог воспользоваться уязвимостью LFI или загрузить веб-шелл и воспользоваться какой-то командой.

      В директории /var/www/html/ разместим файл read_passwd.php с содержимым:

      <?php
      $myfile = fopen("/etc/passwd", "r") or die("Unable to open file!");
      echo fread($myfile,filesize("/etc/passwd"));
      fclose($myfile);
      ?>

      И еще один shell.php который имитирует простейший веб-шелл:

      <?php if(isset($_REQUEST['cmd'])){ echo "<pre>"; $cmd = ($_REQUEST['cmd']); system($cmd); echo "</pre>"; die; }?>

      Получим через браузер сначала read_file.php и выполним поиск по логам:

      $ ausearch -k apache_alert -i
      ----
      type=PROCTITLE msg=audit(12.08.2021 23:12:08.373:688) : proctitle=/usr/sbin/apache2 -k start 
      type=PATH msg=audit(12.08.2021 23:12:08.373:688) : item=0 name=/etc/passwd inode=264156 dev=08:01 mode=file,644 ouid=root ogid=root rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0 
      type=CWD msg=audit(12.08.2021 23:12:08.373:688) : cwd=/var/www/html 
      type=SYSCALL msg=audit(12.08.2021 23:12:08.373:688) : arch=x86_64 syscall=openat success=yes exit=12 a0=0xffffff9c a1=0x7ffea2903630 a2=O_RDONLY a3=0x0 items=1 ppid=3410 pid=3419 auid=unset uid=www-data gid=www-data euid=www-data suid=www-data fsuid=www-data egid=www-data sgid=www-data fsgid=www-data tty=(none) ses=unset comm=apache2 exe=/usr/sbin/apache2 key=apache_alert 

      После этого в браузере выполним запрос:
      http://192.168.0.101/shell.php?cmd=ls

      И выполнив поиск по логам, увидим, что добавились события:

      ----
      type=PROCTITLE msg=audit(12.08.2021 23:14:57.566:707) : proctitle=sh -c ls 
      type=PATH msg=audit(12.08.2021 23:14:57.566:707) : item=0 name=/etc/ld.so.cache inode=265858 dev=08:01 mode=file,644 ouid=root ogid=root rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0 
      type=CWD msg=audit(12.08.2021 23:14:57.566:707) : cwd=/var/www/html 
      type=SYSCALL msg=audit(12.08.2021 23:14:57.566:707) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffff9c a1=0x7feec9ccbea8 a2=O_RDONLY|O_CLOEXEC a3=0x0 items=1 ppid=3422 pid=3433 auid=unset uid=www-data gid=www-data euid=www-data suid=www-data fsuid=www-data egid=www-data sgid=www-data fsgid=www-data tty=(none) ses=unset comm=sh exe=/bin/dash key=apache_alert 
      ----
      type=PROCTITLE msg=audit(12.08.2021 23:14:57.562:706) : proctitle=sh -c ls 
      type=PATH msg=audit(12.08.2021 23:14:57.562:706) : item=1 name=/lib64/ld-linux-x86-64.so.2 inode=3156086 dev=08:01 mode=file,755 ouid=root ogid=root rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0 
      type=PATH msg=audit(12.08.2021 23:14:57.562:706) : item=0 name=/bin/sh inode=1966114 dev=08:01 mode=file,755 ouid=root ogid=root rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0 
      type=CWD msg=audit(12.08.2021 23:14:57.562:706) : cwd=/var/www/html 
      type=EXECVE msg=audit(12.08.2021 23:14:57.562:706) : argc=3 a0=sh a1=-c a2=ls 
      type=SYSCALL msg=audit(12.08.2021 23:14:57.562:706) : arch=x86_64 syscall=execve success=yes exit=0 a0=0x7f5978e1de1a a1=0x7ffea29045e0 a2=0x7ffea29073d8 a3=0x1 items=2 ppid=3422 pid=3433 auid=unset uid=www-data gid=www-data euid=www-data suid=www-data fsuid=www-data egid=www-data sgid=www-data fsgid=www-data tty=(none) ses=unset comm=sh exe=/bin/dash key=apache_alert 
      ....

      Всё работает как было задумано.

    Результат: такими правилами мы обнаружим любое обращение к файлам, которые не используются веб-сервером в рамках привычной своей деятельности и могут являться целью злоумышленника. В приведенном примере использовался веб-сервер без каких-либо приложений, фильтров может быть больше, однако, если вам удастся подобным образом написать правила, то многие наиболее критичные виды веб-уязвимостей (RCE, LFI, SSTI, XXE и т.д.) при выполнении команд в системе или чтении файлов могут быть обнаружены в момент их реализации.
    В случае, если исключений слишком много. можно пойти другим путем и написать правила для наблюдения только за наиболее важными директориями в системе. Например:

    # dirs from PATH var
    -w /bin -F uid=www-data -k apache_alert
    -w /usr/local/sbin -F uid=www-data -k apache_alert
    -w /usr/local/bin -F uid=www-data -k apache_alert
    -w /usr/sbin -F uid=www-data -k apache_alert
    -w /usr/bin -F uid=www-data -k apache_alert
    -w /sbin -F uid=www-data -k apache_alert
    
    -w /etc -F uid=www-data -k apache_alert

    Таким образом при обращении пользователя веб-сервера к исполняемым файлам системы будут созданы соответствующие события.

    HTTP. Постэксплуатация

    Поскольку на предыдущем шаге мы установили наблюдение за почти всеми возможными ... непокрытое поле для злоумышленника остаётся только в директории /var/www/. Можем предположить, что он может попытаться записать новый файл с функционалом для веб-приложения или изменить существующий для реализации новой логики. Если у вас приложение не создаёт динамических страниц, то для обнаружения изменений в существующих файлах веб-приложения можно написать следующие правила:

    -w /var/www/ -p wa -F uid=www-data -k apache_file_change

    Тогда для всех случаев когда файлы открываются для записи или изменения прав веб-сервером будут записаны события. Это правило необходимо разместить над фильтрами. Итоговый набор правил может выглядеть так:

    -D
    -w /var/www/ -p wa -F uid=www-data -k apache_file_change
    -a never,exit -F dir=/usr/share/zoneinfo/ -F uid=www-data
    -a never,exit -F dir=/var/www/ -F uid=www-data
    -w / -F uid=www-data -k apache_alert

    SSH сервис

    Немного забегая вперёд, стоит отметить, что правила по обнаружению инцидентов возникающих через ssh-сервис очень схожи с правилами по расследованию инцидентов, поэтому многие правила из этого раздела можно использовать и при расследовании инцидентов. Это связано со спецификой самого ssh-сервиса.

    SSH. Сканирование сервиса

    Данный этап идентичен с этапом для HTTP-сервиса, поэтому его пропускаем.

    SSH. Атака сервиса

    Учитывая назначение сервиса, объеденим атаку и постэскплуатацию - поскольку взлом самого сервиса маловероятен, сфокусируемся на случае, когда злоумышленник получил доступ к сервису "популярным" способом - узнал пароль или ключ.

    1. Определим действия. Рассматривать атакую перебор учетных данных сервиса не будем, т.к. есть более удобные инструменты для отслеживания таких атак, однако стоит отметить, что по умолчанию в журналы аудиты попадают все события связанные с попытками логина и аутентификации. Пример неудачной попытки ввода учетных данных:

      time->Fri Aug 13 14:45:27 2021
      type=USER_LOGIN msg=audit(1628855127.918:860): pid=8622 uid=0 auid=4294967295 ses=4294967295 msg='op=login acct=28756E6B6E6F776E207573657229 exe="/usr/sbin/sshd" hostname=? addr=192.168.0.104 terminal=sshd res=failed'
      ----
      time->Fri Aug 13 14:45:27 2021
      type=USER_LOGIN msg=audit(1628855127.918:861): pid=8622 uid=0 auid=4294967295 ses=4294967295 msg='op=login acct=28696E76616C6964207573657229 exe="/usr/sbin/sshd" hostname=? addr=192.168.0.104 terminal=sshd res=failed'
      ----
      time->Fri Aug 13 14:45:30 2021
      type=USER_AUTH msg=audit(1628855130.974:862): pid=8622 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:authentication acct="testy" exe="/usr/sbin/sshd" hostname=192.168.0.104 addr=192.168.0.104 terminal=ssh res=failed'
      ----
      time->Fri Aug 13 14:45:30 2021
      type=USER_LOGIN msg=audit(1628855130.974:863): pid=8622 uid=0 auid=4294967295 ses=4294967295 msg='op=login acct=28696E76616C6964207573657229 exe="/usr/sbin/sshd" hostname=? addr=192.168.0.104 terminal=sshd res=failed'

      SSH изначально предполагает подключение пользователей и предоставление им возможности выполнять команды, поэтому обнаружение подозрительной активности становится весьма нетривиальной задачей.
      В зависимости от предназначения сервера, наборы подозрительных действий могут отличаться. Так если сервер предназначен, например, для веб-разработки, то маловероятно, что пользователям нужны утилиты связанные с дампом трафика. Можно предположить, что злоумышленника будет интересовать сбор сведений о системе, поиск ценных данных о проекте (компании), повышение привилегий в системе. Для начала можно пройтись по спискам Linux Privilege Escalation, ознакомиться с основными способами сбора информации там и настроить правила для них. Затем, исходя из специфики сервера, необходимо добавить дополнительные правила.

    2. Поскольку правил может быть очень много, рассмотрим основные. Много полезных примеров для этого раздела я нашёл здесь. Интересно, что auditd с собой несёт тоже несколько примеров наборов правил, есть даже для pci-dss-v31:

      $ ls /usr/share/doc/auditd/examples/rules
      10-base-config.rules  12-cont-fail.rules     21-no32bit.rules             30-nispom.rules.gz       31-privileged.rules   41-containers.rules   70-einval.rules      README-rules
      10-no-audit.rules     12-ignore-error.rules  22-ignore-chrony.rules       30-pci-dss-v31.rules.gz  32-power-abuse.rules  42-injection.rules    71-networking.rules
      11-loginuid.rules     20-dont-audit.rules    23-ignore-filesystems.rules  30-stig.rules.gz         40-local.rules        43-module-load.rules  99-finalize.rules

      Для каждого события будем добавлять строку "susp_", по этому ключу можно будет найти любые подозрительные действия в системе, а также удобно настраивать поиск в подсистеме анализа.
      Начнём с логирования действий над самим инструментом:

      -w /etc/audit/ -p wa -k susp_auditconfig
      -w /etc/audisp/ -p wa -k susp_audispconfig
      -w /sbin/auditctl -p x -k susp_audittools
      -w /sbin/auditd -p x -k susp_audittools
      -w /usr/sbin/augenrules -p x -k susp_audittools
      -w /var/log/audit/ -k susp_auditlog

      Запись или изменение прав файлов планировщика задач:

      -w /etc/cron -p wa -k cron_change
      -w /etc/crontab -p wa -k cron_change
      -w /etc/cron.allow -p wa -k cron_change
      -w /etc/cron.d  -p wa -k cron_change
      -w /etc/cron.deny -p wa -k cron_change
      -w /etc/cron.daily -p wa -k cron_change
      -w /etc/cron.hourly -p wa -k cron_change
      -w /etc/cron.monthly -p wa -k cron_change
      -w /etc/cron.weekly -p wa -k cron_change
      -w /etc/anacrontab -p wa -k cron_change
      -w /var/spool/cron -p wa -k cron_change
      -w /var/spool/cron/crontabs/root -p wa -k cron_change

      Интересным кажется вариант с логированием выполнения команды sudo всеми пользователями, кроме того (тех), кому такие права не выданы:

      -w /usr/bin/sudo -F auid!=<имя пользователя> -k susp_sudo

      Важно наблюдать за работой сетевых утилит:

      -w /sbin/iptables -p x -k susp_netutil
      -w /sbin/ip6tables -p x -k susp_netutil
      -w /sbin/ifconfig -p x -k susp_netutil
      -w /usr/sbin/arptables -p x -k susp_netutil
      -w /usr/sbin/ebtables -p x -k susp_netutil
      -w /sbin/xtables-nft-multi -p x -k susp_netutil
      -w /usr/sbin/nft -p x -k susp_netutil

      Особый интерес представляют события, связанные с различными нарушениями доступа пользователей: при чтении, записи, изменении файлов:

      ## File Access
      ### Unauthorized Access (unsuccessful)
      -a always,exit -F arch=b32 -S creat -S open -S openat -S open_by_handle_at -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=-1 -k file_access
      -a always,exit -F arch=b32 -S creat -S open -S openat -S open_by_handle_at -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=-1 -k file_access
      -a always,exit -F arch=b64 -S creat -S open -S openat -S open_by_handle_at -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=-1 -k file_access
      -a always,exit -F arch=b64 -S creat -S open -S openat -S open_by_handle_at -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=-1 -k file_access
      
      ### Unsuccessful Creation
      -a always,exit -F arch=b32 -S creat,link,mknod,mkdir,symlink,mknodat,linkat,symlinkat -F exit=-EACCES -k file_creation
      -a always,exit -F arch=b64 -S mkdir,creat,link,symlink,mknod,mknodat,linkat,symlinkat -F exit=-EACCES -k file_creation
      -a always,exit -F arch=b32 -S link,mkdir,symlink,mkdirat -F exit=-EPERM -k file_creation
      -a always,exit -F arch=b64 -S mkdir,link,symlink,mkdirat -F exit=-EPERM -k file_creation
      
      ### Unsuccessful Modification
      -a always,exit -F arch=b32 -S rename -S renameat -S truncate -S chmod -S setxattr -S lsetxattr -S removexattr -S lremovexattr -F exit=-EACCES -k file_modification
      -a always,exit -F arch=b64 -S rename -S renameat -S truncate -S chmod -S setxattr -S lsetxattr -S removexattr -S lremovexattr -F exit=-EACCES -k file_modification
      -a always,exit -F arch=b32 -S rename -S renameat -S truncate -S chmod -S setxattr -S lsetxattr -S removexattr -S lremovexattr -F exit=-EPERM -k file_modification
      -a always,exit -F arch=b64 -S rename -S renameat -S truncate -S chmod -S setxattr -S lsetxattr -S removexattr -S lremovexattr -F exit=-EPERM -k file_modification

      Обратите внимание, что правила написаны для системных вызовов разных архитектур отдельно.
      Как показала практика, у таких правил часто возникают ложные срабатывания, в таким случае их можно изменить, добавив срабатывание только на пользовательские действия. После опции -S <системный вызов> необходимо добавить:

      -F auid>=1000 -F auid!=-1

      Можно привести еще много примеров, общие принципы понятны.

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

    4. Написание фильтров как и в случае с HTTP-сервисом лучше проводить поэтапно, для каждого правила или набора правил.

    5. Завершающий этап - моделирование ситуации, при которой эти правила должны создать события в журнале аудита, чтобы убедиться, что всё работает как задумано.

    Результат: SSH-сервис, на мой взгляд, один из самых сложных сервисов для обнаружения инцидента при помощи auditd, поэтому для него должны быть использованы надежные средства защиты, которые не позволят злоумышленнику получить доступ к серверу, . Созданные на этом этапе правила во многом могут быть использованы для расследования инцидентов о чем будет сказано далее.

    Расследование инцидентов

    Подход при определении событий логирования схож с подходом при выявлении инцидента - определяем все возможные способы действий злоумышленника, ранжируем их по значимости, определяем для них события, после чего пишем правила. Помимо этого в качестве подспорья можно использовать условную классификацию по подсистемам ОС (для каждой подсистемы определять список важных файлов, системных вызовов, команд), группам пользователей и другим классификациям, которые облегчат понимание общей картины. Часть таких классификаций уже использовалась при написании правил в разделе про SSH:

    • группы пользователей ОС и их идентификаторы (uid, euid, auid и др.): можно разбить пользователей на сервисных (uid 1-999) и остальных;

    • результаты выполнения команд: можно создать правила, которые будут записывать события по нарушению доступа к файлам: записи, чтения, выполнения, создания или системных вызовов;

    При создании правил, используя условную классификацию по подсистемам, для каждой подсистемы необходимо определить файлы, за которыми необходимо наблюдение, системные вызовы и утилиты (исполняемые файлы). Для удобства составления правил ОС можно разбить на подсистемы по функциональному назначению, например:

    • работа с ядром ОС;

    • планировщик задач cron;

    • работа с сетью и сетевыми настройками;

    • операции с диском и файловой системой;

    • подсистема управления пользователями ОС;

    • подсистема установки/обновления ПО;

    • файлы конфигурации пользователей ОС;

    Рассмотрим несколько примеров.

    Подсистема логирования

    Специфичных системных вызовов я не нашёл для системы логирования, поэтому основная работа будет проходить по файлам и командам:

    ## Auditd configuration
    ### Modifications to audit configuration that occur while the audit collection functions are operating
    -w /etc/audit/ -p wa -k auditconfig
    -w /etc/libaudit.conf -p wa -k auditconfig
    -w /etc/audisp/ -p wa -k audispconfig
    
    ## Monitor for use of audit management tools
    -w /sbin/auditctl -p x -k audittools
    -w /sbin/auditd -p x -k audittools
    
    ## Read and changing permissions alert
    -w /var/log/ -p ra -k log_alert

    Устанавливаем наблюдение за файлами конфигурации auditd, его модулей, исполняемых файлов и логами.

    Подсистема управления пользователями

    ## User, group, password databases
    -w /etc/group -p wa -k etcgroup
    -w /etc/passwd -p wa -k etcpasswd
    -w /etc/gshadow -k etcgroup
    -w /etc/shadow -k etcpasswd
    -w /etc/security/opasswd -k opasswd
    -w /etc/adduser.conf -k adduserconf
    
    ## Sudoers file changes
    -w /etc/sudoers -p wa -k actions
    
    ## Passwd
    -w /usr/bin/passwd -p x -k passwd_modification
    -w /usr/bin/gpasswd -p x -k gpasswd_modification
    
    ## Tools to change group identifiers
    -w /usr/sbin/groupadd -p x -k group_modification
    -w /usr/sbin/groupmod -p x -k group_modification
    -w /usr/sbin/addgroup -p x -k group_modification
    -w /usr/sbin/useradd -p x -k user_modification
    -w /usr/sbin/usermod -p x -k user_modification
    -w /usr/sbin/adduser -p x -k user_modification
    
    ## Login configuration and information
    -w /etc/login.defs -p wa -k login
    -w /etc/securetty -p wa -k login
    -w /var/log/faillog -p wa -k login
    -w /var/log/lastlog -p wa -k login
    -w /var/log/tallylog -p wa -k login

    Выше перечислены основные команды, файлы логов и конфигурации по управлению пользователями ОС.

    Подобным образом можно создавать правила и для других подсистем, а тестирование проводить описанным выше способом.

    Заключение

    По итогу можно сделать выводы:
    1. Для ряда случаев можно настроить auditd, что позволит практически моментально выявить проникновение в систему - как в приведенном примере с apache;
    2. В остальном - работа требует глубокого погружения и проработки.

    На мой взгляд auditd - мощный инструмент, который, при грамотной настройке, может стать отличным дополнением в обеспечении информационной безопасности инфраструктуры.

    Если у вас есть вопросы, пожелания, замечания или вы готовы поделиться собственным опытом, то пишите в комментариях.

Источник: https://habr.com/ru/post/553036/


Интересные статьи

Интересные статьи

Где-то в компании “Рельсы-рельсы, шпалы-шпалы”. CISO: Игорь, кто-то получил доступ к нашим камерам на вокзалах. Игорь: @@@! CISO: Ступай, разберись. Проверь конфигурации каждой камер...
После выпуска первой публичной (третьей) версии платформы мы получили огромное количество фидбэка, большая часть работы над которым нашла отражение в недавно вышедшей четвертой версии...
Как работают платформы анализа информации об угрозах и какие функции предоставляет передовое ПО из этой сферы; сравнение продуктов на основе аналитической таблицы ROI4CIO. ...
Перевод статьи подготовлен специально для студентов курса «Безопасность Linux». Читать первую часть 5. Не оставляйте чувствительные данные в образах Docker Иногда при создании приложения в...
Автокэширование в 1с-Битрикс — хорошо развитая и довольно сложная система, позволяющая в разы уменьшить число обращений к базе данных и ускорить выполнение страниц.