Поиск угроз и криминалистическая экспертиза
Поиск угроз и криминалистика
Руководство
При поиске угроз время и точность имеют решающее значение. Вам нужно действовать максимально быстро и точно, чтобы найти информацию и отреагировать на неё. Как аналитик по безопасности, расследующий инциденты безопасности или занимающийся поиском угроз, вы часто сталкиваетесь с необходимостью:
- Перемещаться между несколькими выполненными запросами и их результатами.
- Управлять доказательствами, собранными в ходе расследований, и повторно использовать их при построении дополнительных запросов.
- Обеспечивать, чтобы:
- Расследование сохранялось в контексте.
- Инструменты для таких действий поддерживали быстрое создание запросов и детальный обзор результатов.
Далее мы покажем, как достичь этих целей с помощью Расследований.
Целевая аудитория
Эта страница предназначена для команд безопасности, занимающихся поиском угроз или анализом инцидентов безопасности, например, для команды реагирования на инциденты или аналитиков по безопасности.
Сценарий
Далее мы рассматриваем сценарий, в котором вы получаете уведомление из внешнего источника о подозрительно большом количестве несанкционированных запросов к вашей плоскости управления Kubernetes в период с 2024-02-13 16:00:00 по 2024-02-13 18:59:59. Ваш кластер Kubernetes настроен как кластер AWS EKS, а логи пересылаются в Ключ-АСТРОМ.
Как аналитик по безопасности, вы хотите понять, связано ли это с вредоносной деятельностью или может указывать на инцидент кибербезопасности. В ходе этого расследования вы будете следовать по цепочке своих находок, чтобы проиллюстрировать природу поиска угроз и решения инцидентов.
Предварительные требования
- Настройте наблюдаемость Kubernetes с помощью Ключ-АСТРОМ Operator.
- Настройте логирование в облаке:
- Настройте логирование кластера EKS.
- Настройте логирование потоков VPC.
- Настройте логирование DNS в K8S.
- Потоковая передача логов через Amazon Data Firehose.
- Базовые знания:
- Ключ-АСТРОМ Query Language (DQL)
- Ключ-АСТРОМ Pattern Language (DPL)
- Как работает разрешение имён DNS в кластерах Kubernetes
Путь расследования 1. Анализ логов аудита Kubernetes
Сначала вы хотите понять, какие действия вызвали уведомление о большом количестве несанкционированных запросов в логах аудита Kubernetes. Откройте Расследования и создайте новое расследование.
Шаг 1. Задайте временной диапазон
В разделе временного диапазона задайте период с 2024-02-13 16:00:00 по 2024-02-13 18:59:59, когда произошли несанкционированные запросы.
Шаг 2. Получите логи аудита кластера Kubernetes
Логи аудита Kubernetes пересылаются в Ключ-АСТРОМ со значениями aws.log_group и log_stream. Чтобы получить все уникальные группы логов AWS CloudWatch, загруженные в Ключ-АСТРОМ, скопируйте и вставьте следующий запрос DQL в поле ввода запроса:
fetch logs | summarize count(), by: aws.log_group
Выберите Запустить, чтобы выполнить запрос.
На этом этапе вы заметите, что в разделе «Дерево запросов» в правом верхнем углу появился круг. Это называется корневым узлом и отмечает начальную точку вашего расследования. С этого момента каждый раз, когда вы изменяете и выполняете запрос, в дереве запросов добавляется новый узел, позволяя вам перемещаться между запросами, сохраняя историю расследования. Подробности см. в разделе «Дерево запросов».
Шаг 3. Фильтрация по имени группы логов
В результатах запроса найдите запись с группой логов, собирающей логи плоскости управления EKS (в нашем примере /aws/eks/unguard-secla-demo/cluster), и добавьте её как фильтр в ваш запрос DQL.
Чтобы просмотреть только события аудита плоскости управления, измените команду фильтрации в поле ввода запроса, добавив оператор and и строковую функцию contains следующим образом:
| filter aws.log_group == "/aws/eks/unguard-secla-demo/cluster" and contains(aws.log_stream, "audit")
В поле ввода запроса удалите команду summarize и выберите Запустить, чтобы выполнить запрос.
Шаг 4. Изучите содержимое
В таблице результатов запроса щёлкните правой кнопкой мыши по любой ячейке в поле content и выберите Просмотреть сведения о поле, чтобы увидеть необработанное содержимое поля. Подробности см. в разделе «Изучение данных в исходном формате».
Шаг 5. Извлеките поля из JSON
В таблице результатов запроса щёлкните правой кнопкой мыши по любой ячейке в поле Content и выберите Извлечь поля, чтобы перейти в DPL Architect.
- Выберите Сохранённые шаблоны.
- В разделе «Шаблоны Ключ-АСТРОМ» выберите
k8s > audit.
При извлечении полей из структуры JSON вы можете определить только частичную схему для полей, relevant для вашего сценария. Чтобы продолжить расследование, вам нужно выбрать только relevant поля.
В поле ввода запроса DPL Architect замените шаблон следующим образом:
JSON{
STRING:verb,
JSON{string:username}(flat=true):user,
JSON_ARRAY{ipaddr}(typed=true):sourceIPs,
JSON{string+:resource}(flat=true):objectRef,
JSON{int:code}(flat=true):responseStatus
}(flat=true)
Выберите Результаты, чтобы увидеть обзор полей, которые будут извлечены из набора данных предварительного просмотра соответствия.
Выберите Вставить шаблон, чтобы добавить шаблон в ваш запрос DQL.
Выберите Запустить, чтобы выполнить запрос.
Шаг 6. Фильтрация событий
Чтобы выяснить, с каких IP-адресов исходит несанкционированная активность, вам нужно:
- Развернуть массив исходных IP-адресов.
- Суммировать результаты с relevant полями, извлечёнными ранее.
- Отфильтровать результаты, чтобы просмотреть только несанкционированные запросы (401) и запрещённые запросы (403).
В поле ввода запроса добавьте следующий фрагмент DQL, затем выберите Запустить, чтобы выполнить запрос:
| expand sourceIPs
| summarize count(), by: {sourceIPs, username, verb, resource=objectRef, responseStatus}
| filter in(responseStatus, {401, 403})
В меню таблицы результатов отсортируйте результаты по количеству, чтобы увидеть, какие IP-адреса имели наибольшее количество подключений.
Похоже, вы нашли источник вашего уведомления безопасности:
- Несанкционированный внешний IP-адрес пытается получить секреты из вашей плоскости управления (в нашем примере
198.51.100.2, с кодом ответа 401 и 122 подключениями). Это неудивительно, поскольку сканеры безопасности пытаются делать это ежедневно из интернета. - Частный IP-адрес пытается многократно перечислить поды (в нашем примере
172.31.29.138, с кодом ответа 403 и 2090 подключениями). Похоже, это один из подов в вашем кластере Kubernetes, и такое поведение может указывать на скомпрометированный под!
Шаг 7. Добавьте IP-адреса как доказательства
Оба IP-адреса нуждаются в дальнейшем анализе, но тот, у которого код ответа 403 и 2090 попыток, более критичен и требует особого внимания.
Чтобы сохранить IP-адреса как доказательства, вы можете добавить первый IP-адрес (198.51.100.2) в предустановленный список доказательств, а второй (172.31.29.138) — в новый настроенный список доказательств:
- Щёлкните правой кнопкой мыши по
198.51.100.2, затем выберите Добавить в список доказательств > Подозрительные IP-адреса. - Щёлкните правой кнопкой мыши по
172.31.29.138, выберите Добавить в список доказательств > Новый список доказательств и введите имя, например «Подозрительный под».
Путь расследования 2. Изучите потенциальную цель
Чтобы понять, что делал под и какие логи других сервисов вам нужны для расследования, вы можете начать с сетевых логов. Для облачных сервисов лучше всего начать с логов потоков сети VPC.
Шаг 1. Получите логи потоков VPC
Шаг 2. Извлеките поля
Шаг 3. Отфильтруйте результаты
Путь расследования 3. Определите, какие данные под отправил наружу
Чтобы найти имена DNS, разрешённые подом, вам нужно проверить логи CoreDNS. При правильной настройке логи запросов видны в логах контейнера CoreDNS.
Шаг 1. Получите логи CoreDNS
Чтобы получить логи контейнера CoreDNS, перейдите к шагу «Получение логов аудита кластера Kubernetes» и измените запрос в поле ввода запроса следующим образом:
fetch logs | filter k8s.container.name == "coredns"
Выберите Запустить, чтобы выполнить запрос. Это создаст третью ветвь в дереве запросов.
Шаг 2. Извлеките поля
- В таблице результатов запроса щёлкните правой кнопкой мыши по любой ячейке в поле
contentи выберите Извлечь поля. - В DPL Architect выберите Сохранённые шаблоны.
- В разделе «Шаблоны Ключ-АСТРОМ» выберите
k8s > coredns-query. - Выберите Вставить шаблон.
- Выберите Запустить, чтобы выполнить запрос.
Шаг 3. Отфильтруйте результаты
Чтобы просмотреть только записи, содержащие DNS-запросы, исходящие от вашего подозрительного пода, выберите заголовок столбца source_ip, затем выберите Фильтровать по > Подозрительный под.
Шаг 4. Извлеките доменное имя
В таблице результатов может быть довольно много DNS-запросов. Для лучшего понимания разрешённых имён хостов вам нужно извлечь часть доменного имени из поля name и суммировать результаты на его основе.
В поле ввода запроса добавьте следующий фрагмент в запрос DQL:
| parse name, "ld* '.'? ( (ld '.' ld):domain '.' eos)"
| summarize count = count(), by: {domain}
Выберите Запустить, чтобы выполнить запрос.
Вы заметите, что помимо внутренних или локальных доменов довольно часто разрешается один подозрительный домен (tiitha-maliciousdomain.com)!
Шаг 5. Добавьте домен как доказательство
В таблице результатов запроса щёлкните правой кнопкой мыши по подозрительному доменному имени, затем выберите Добавить в список доказательств > Новый список доказательств.
Введите имя для нового списка доказательств, например «Домен атакующего».
Шаг 6. Фильтрация по домену атакующего
В таблице результатов запроса выберите ячейку с подозрительным доменом, затем выберите Фильтровать по, чтобы добавить в запрос фильтр, который получает только запросы, включающие домен атакующего.
В поле ввода запроса удалите команду summarize и выберите Запустить, чтобы выполнить запрос.
Похоже, между подозрительным подом и доменом атакующего происходит какой-то обмен данными. Судя по именам запросов и учитывая количество запросов, данные, по-видимому, извлекаются через DNS-туннелирование.
Шаг 7. Проанализируйте DNS-запросы
Поскольку в сторону этого конкретного домена поступают тысячи DNS-запросов, вы можете захотеть агрегировать данные, чтобы определить, как действовать дальше.
В результатах запроса выберите заголовок столбца type, затем выберите Суммировать.
Выберите Запустить, чтобы выполнить запрос.
Вы заметите много запросов A, AAAA и TXT от пода. Вы начинаете исследовать запросы A.
В таблице результатов запроса щёлкните правой кнопкой мыши по ячейке A и выберите Фильтровать по, чтобы добавить фильтр в запрос DQL.
В поле ввода запроса удалите команду summarize и выберите Запустить, чтобы выполнить запрос.
Чтобы определить, что отправляется наружу, вам нужно извлечь часть поддомена из домена. Для этого вам нужно проанализировать один из DNS-запросов, разрешающих домен атакующего.
- Дважды щёлкните по любой ячейке в таблице результатов запроса.
- В окне Сведения (…) проверьте данные в поле
name.
Похоже, что DNS-имя структурировано как идентификатор, за которым следует часть полезной нагрузки, закодированная в шестнадцатеричном формате, и эти части разделены точками.
Чтобы разобрать и декодировать полезную нагрузку, добавьте следующий фрагмент DQL в запрос DQL:
| parse name, """ld:id '.' ld:payload '.tiitha-maliciousdomain'""" | fieldsAdd payload=replaceString(payload,".","") | fields timestamp, id, payload=decodeBase16ToString(payload) | sort timestamp, id
Результат доказывает, что данные из вашего пода определённо извлекаются и отправляются наружу!
Путь расследования 4. Выясните, как команды отправлялись на под
Вы точно знаете, что под отправляет информацию на внешний DNS-сервер, но ещё не выяснили, как он получает команды. Поскольку DNS-запросы типа TXT позволяют получать более крупные ответы и иногда также используются для вредоносных транзакций, вам нужно взглянуть на эти запросы. Поскольку записи CoreDNS не содержат полезную нагрузку ответа, вы обращаетесь к логам Route53.
Шаг 1. Проанализируйте записи TXT
Используя дерево запросов, перейдите к шагу «Получение логов аудита кластера Kubernetes».
В результатах запроса найдите запись с вашей группой логов Route53 (в нашем примере /aws/route53/unguard-secla-demo/resolver-logs) и добавьте её как фильтр в ваш запрос DQL.
В поле ввода запроса удалите команду summarize и выберите Запустить, чтобы выполнить запрос. Это создаст четвёртую ветвь в дереве запросов.
Шаг 2. Извлеките поля из записей логов
- В таблице результатов запроса щёлкните правой кнопкой мыши по любой ячейке в поле
contentи выберите Извлечь поля. - В DPL Architect выберите Сохранённые шаблоны.
- В разделе «Шаблоны Ключ-АСТРОМ» выберите
aws > route53-query.
Вам нужно извлечь значения query_name, query_type, srcaddr и answers из записи лога. В поле ввода запроса вы можете заменить шаблон следующим образом:
json{
string:query_name,
string:query_type,
json_array:answers,
ipaddr:srcaddr
}(flat=true)
Выберите Вставить шаблон.
Выберите Запустить, чтобы выполнить запрос.
Шаг 3. Отфильтруйте данные
В результатах запроса выберите заголовок столбца query_name, затем выберите Фильтровать по > Домен атакующего.
Выберите Запустить, чтобы выполнить запрос.
Вас интересуют только запросы типа TXT, поэтому вы можете дополнить фильтр соответствующим выражением. Поскольку часть answers является массивом, разверните поле так, чтобы каждое значение в массиве было отдельной записью. Вам нужны только поля srcaddr, query_name и элемент Rdata из объекта ответа.
В поле ввода запроса измените команду фильтрации, добавив следующий фрагмент:
| filter endsWith(query_name, "tiitha-maliciousdomain.com.") and query_type == "TXT" | expand answers | fields srcaddr, query_name, answer=answers[Rdata]
Выберите Запустить, чтобы выполнить запрос.
Ваша гипотеза подтвердилась: DNS-запросы TXT использовались для получения команд. Выполненные команды (включая запросы к плоскости управления Kubernetes в виде команд curl) отображаются как ответы в ваших DNS-логах!
Заключение
Вы выяснили, что произошло, но ещё не поняли, что ещё делал под, какой процесс или активность вызывает DNS-запросы, кто контролирует извлечение данных, как и когда под был инфицирован, и другие relevant аспекты инцидента безопасности.
С этого момента сложность расследования будет только расти, и возможность перемещаться между различными этапами расследования становится ещё более важной. Все эти вопросы могут вызвать новую ветвь в дереве запросов, если не отдельное расследование. Наше расследование порождает множество дополнительных вопросов, требующих ответов.