Обнаружение угроз и аудит: CloudTrail, GuardDuty, Config, Security Hub
Урок 02 предотвращал; этот — обнаруживает и реагирует. CloudTrail — спина аудита, GuardDuty ловит активные угрозы, Config ловит дрейф конфигурации, Security Hub агрегирует — затем EventBridge маршрутизирует к автоответу. Нет CloudTrail — нет форензики после взлома.
Через три недели после утечки CI-ключа доступа финансы сигналят о сюрпризе на $40k: GPU-инстансы майнят крипту в двух регионах, куда вы никогда не деплоите. Вы ротируете ключ, гасите инстансы, и тут приходит вопрос, который реально важен, от вашего CISO: что ещё они трогали — читали ли бакет с данными клиентов, создали ли бэкдор-пользователя, меняли ли IAM-политику? Вы открываете консоль для расследования и находите, что ответ узнать невозможно. CloudTrail никогда не был включён на уровне организации; единственный существовавший трейл писал в S3-бакет в том же скомпрометированном аккаунте, и DeleteObjects злоумышленника стёр его на выходе. Event History хранит лишь 90 дней management-событий и ничего не показывает по S3-чтениям, которые вас волнуют. У вас нет форензик-таймлайна, вы не можете очертить периметр взлома и обязаны уведомить клиентов, исходя из худшего сценария. Атака удалась, потому что предотвращение один раз дало сбой; расследование провалилось, потому что обнаружение и аудит вообще не были настроены. Этот урок — вторая половина безопасности: обнаруживать и реагировать.
После этого урока ты поймёшь, почему трейл в том же аккаунте — это не трейл вовсе, что делает GuardDuty из трёхнедельного сюрприза пейджем того же часа и почему обнаружение без владельца — просто дорогие обои.
CloudTrail: спина аудита, которую нельзя пропустить
Урок 02 был о предотвращении — оценка IAM, KMS, ограничение радиуса поражения до того, как что-то пойдёт не так. Этот урок — другая половина: предполагая, что что-то пойдёт не так, как это увидеть и отреагировать. Фундамент всего — это CloudTrail, который записывает каждый вызов AWS API в вашем аккаунте — кто (принципал), что (действие), когда, откуда (исходный IP) и что произошло (ответ). Это неизменяемый ответ на вопрос «что они трогали?».
CloudTrail делит события на два вида, и различие — это решение о стоимости и покрытии. Management-события — это операции control-plane: RunInstances, CreateUser, AttachRolePolicy, PutBucketPolicy, AssumeRole. Они — спина любого форензик-таймлайна, и первая копия по сути бесплатна. Data-события — это высокообъёмные операции data-plane: объектные GetObject/PutObject в S3, Invoke у Lambda, операции с элементами DynamoDB. Они выключены по умолчанию, потому что льются как из брандспойта; вы платите примерно $0.10 за 100 000 доставленных data-событий, а загруженный S3-бакет может генерировать миллионы в день. Но именно data-события отвечают на вопрос «они читали бакет с данными клиентов?» — management-события показывают изменение политики бакета, и только data-события показывают, что объекты читали. Senior-решение избирательное: management-события всегда включены на уровне организации, data-события — только на тех бакетах и функциях, которые реально важны.
Безоговорочный фундамент — это один трейл организации, мультирегиональный, доставляемый в заблокированный S3-бакет в отдельном logging-аккаунте, с включённой валидацией целостности лог-файлов. Каждая клауза защищает от сценария из Hook. Org-wide и мультирегиональность означают, что новый член-аккаунт или злоумышленник, перепрыгнувший в eu-north-1, всё равно записывается. Отдельный заблокированный logging-аккаунт означает, что злоумышленник, владеющий скомпрометированным аккаунтом, не может удалить улики — это и был фатальный изъян в Hook. Валидация лог-файлов заставляет CloudTrail хеш-цепочкой связывать и подписывать каждый доставленный файл, так что позже можно доказать, что логи не подделывали.
# Один org-wide, мультирегиональный трейл в заблокированный бакет logging-аккаунта,
# с включённой валидацией целостности лог-файлов.
aws cloudtrail create-trail \
--name org-audit-trail \
--s3-bucket-name acme-central-cloudtrail-logs \
--is-organization-trail \
--is-multi-region-trail \
--enable-log-file-validation \
--kms-key-id arn:aws:kms:us-east-1:444455556666:key/trail-cmk
aws cloudtrail start-logging --name org-audit-trail
# Добавляем data-события S3 для ОДНОГО важного бакета (не для всех).
aws cloudtrail put-event-selectors \
--trail-name org-audit-trail \
--advanced-event-selectors '[{
"Name": "customer-data reads/writes",
"FieldSelectors": [
{ "Field": "eventCategory", "Equals": ["Data"] },
{ "Field": "resources.type", "Equals": ["AWS::S3::Object"] },
{ "Field": "resources.ARN", "StartsWith": ["arn:aws:s3:::acme-customer-data/"] }
]
}]'
# Позже доказываем, что логи не тронуты за период взлома.
aws cloudtrail validate-logs \
--trail-arn arn:aws:cloudtrail:us-east-1:444455556666:trail/org-audit-trail \
--start-time 2026-05-01T00:00:00ZРежим отказа — это само отсутствие: нет трейла (или он однорегиональный, или пишет в бакет, контролируемый злоумышленником) означает, что после взлома у вас нулевой форензик-таймлайн и вы не можете ответить на единственный значимый вопрос. 90-дневный Event History, который консоль показывает бесплатно, не замена — он покрывает только management-события, действует по регионам, не ищется кросс-аккаунтно и исчезает через 90 дней. Настоящий трейл долговечен, охватывает организацию и принадлежит вам.
▸Почему это работает
Почему отдельный logging-аккаунт, а не просто бакет в том же аккаунте с жёсткой политикой? Потому что граница доверия для форензики — сам аккаунт. Если бакет трейла живёт в аккаунте, который компрометируют, украденные креды злоумышленника могут нести s3:DeleteObject (или эскалироваться до него), а первое, что делает грамотный взломщик, — удаляет логи, которые его раскрыли бы, ровно как стирание DeleteObjects из Hook. Выделенный logging-аккаунт, в который не может писать ни один прикладной принципал, принадлежащий другой команде, с SCP, запрещающим удаление логов, и S3 Object Lock на бакете, означает, что улики переживут даже полную компрометацию каждого рабочего аккаунта. Форензика, которую можно удалить из радиуса поражения, — это не форензика.
GuardDuty: управляемое обнаружение угроз, просто включить
CloudTrail записывает; он не судит. Читать сырые трейлы, чтобы заметить атаку в реальном времени, безнадёжно на масштабе. GuardDuty — управляемый детектор: без агентов для установки вы его включаете, и он непрерывно анализирует три источника данных, которые вы уже производите — события CloudTrail, VPC Flow Logs (логи сетевых потоков внутри вашего виртуального облака) и DNS-логи запросов — применяя машинное обучение, детекцию аномалий и курируемую AWS разведку угроз, чтобы выдавать находки. Он ловит классику: EC2-инстанс, майнящий крипту (он знает домены майнинг-пулов и паттерны трафика), эксфильтрацию кред (IAM-ключ, внезапно используемый из новой страны, с выходного узла Tor или из другого AWS-аккаунта), аномальный доступ к S3 и разведку вроде сканирования портов или перечисления API.
Это ровно сценарий из Hook, проигранный с включённым обнаружением. Утёкший CI-ключ, использованный из необычной локации для запуска инстансов, поднимает UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration за минуты; инстансы, звонящие в майнинг-пул, поднимают CryptoCurrency:EC2/BitcoinTool.B!DNS. Вместо того чтобы финансы заметили счёт на $40k три недели спустя, дежурного пейджат в тот же час — потому что GuardDuty был включён.
Компромисс — усилия против шума. GuardDuty действительно малозатратен и высокосигнален — щёлкаешь его на уровне организации, и он просто работает. Но находка, лежащая в консоли, которую никто не смотрит, ничего не стоит. Находкам нужны триаж и автоответ, иначе они копятся, пока дашборд не станет обоями. Стандартная обвязка — EventBridge → Lambda/SNS: GuardDuty эмитит находки как события EventBridge, а правило маршрутизирует высокосерьёзные в remediation-Lambda или на пейджер. Фильтруй агрессивно — алертить на каждую низкосерьёзную находку — это путь, которым команды учатся игнорировать канал.
{
"source": ["aws.guardduty"],
"detail-type": ["GuardDuty Finding"],
"detail": {
"severity": [{ "numeric": [">=", 7] }]
}
}# Маршрутизируем только высокосерьёзные (7.0+) находки GuardDuty к цели реагирования.
aws events put-rule \
--name guardduty-high-sev \
--event-pattern file://gd-high-sev.json
aws events put-targets \
--rule guardduty-high-sev \
--targets 'Id=isolate,Arn=arn:aws:lambda:us-east-1:111122223333:function:gd-respond' \
'Id=page,Arn=arn:aws:sns:us-east-1:111122223333:secops-pager'Серьёзность GuardDuty — это шкала 1.0–8.9+, разбитая на Low (1.0–3.9), Medium (4.0–6.9) и High (7.0–8.9). Маршрутизация по >= 7 пейджит людей по тому, что важно, тогда как средние/низкие находки текут в дашборд на разбор, а не в пейдж в 3 ночи.
AWS Config: дрейф конфигурации и комплаенс-постура
GuardDuty отвечает на «кто-то атакует прямо сейчас?». AWS Config отвечает на другой вопрос: «настроена ли моя инфраструктура так, как должна, и когда это изменилось?». Он непрерывно записывает конфигурацию каждого ресурса во времени — версионированную историю состояния каждого ресурса — и оценивает это состояние против правил: «S3-бакеты не должны быть публичными», «EBS-тома должны быть зашифрованы», «ни одна security group не разрешает 0.0.0.0/0 на порту 22». Ресурс, нарушающий правило, помечается NONCOMPLIANT, и Config даёт комплаенс-таймлайн, показывающий ровно, когда ресурс отдрейфовал из политики и кто его менял (с перекрёстной ссылкой на CloudTrail). Он может авто-ремедиировать через SSM Automation документы — публичный бакет можно вернуть в приватность за секунды после того, как он стал публичным, без человека в цикле.
Отличие от GuardDuty — в этом весь смысл и частая путаница: Config — это мисконфигурация и комплаенс-постура (предотвратимое, структурное — оставленная незапертой дверь); GuardDuty — это активные угрозы (поведенческое — кто-то дёргает дверь). Config говорит, что SSH-порт открыт миру, до того как кто-то его проэксплуатирует; GuardDuty говорит, что кто-то брутфорсит этот открытый порт сейчас. Нужны оба — Config сжимает поверхность атаки, GuardDuty ловит то, что прорвалось.
# Управляемое правило: пометить любой S3-бакет с публичным чтением/записью
# и авто-ремедиировать через SSM-документ.
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "s3-no-public-access",
"Source": {
"Owner": "AWS",
"SourceIdentifier": "S3_BUCKET_PUBLIC_READ_PROHIBITED"
}
}'
aws configservice put-remediation-configurations --remediation-configurations '[{
"ConfigRuleName": "s3-no-public-access",
"TargetType": "SSM_DOCUMENT",
"TargetId": "AWS-DisableS3BucketPublicReadWrite",
"Automatic": true,
"MaximumAutomaticAttempts": 3
}]'Config тарифицирует по двум осям, которые удивляют команды: примерно $0.003 за конфигурационный элемент (каждое изменение ресурса пишет один) и $0.001 за оценку правила. Большой, активно меняющийся аккаунт с сотнями правил по тысячам ресурсов жжёт реальные деньги, поэтому ограничивай запись теми типами ресурсов, что важны, а не слепо записывай всё. Режим отказа тут тонкий — Config, работающий без правил, или правила без ремедиации — это пассивная история, на которую никто не реагирует, что является более дорогой версией проблемы GuardDuty «дашборд, который никто не смотрит».
Security Hub и петля реагирования
Теперь у вас три источника сигнала — находки GuardDuty, комплаенс Config и другие (Inspector для CVE, IAM Access Analyzer для внешнего доступа). Смотреть три консоли по дюжине аккаунтов — это как всё проскальзывает. Security Hub — это единое окно: он агрегирует находки из GuardDuty, Config, Inspector, Access Analyzer и Macie в один нормализованный формат (AWS Security Finding Format), дедуплицирует и приоритизирует их по каждому аккаунту организации и непрерывно оценивает вас против стандартов — CIS AWS Foundations Benchmark, AWS Foundational Security Best Practices (FSBP), PCI DSS. Вместо «комплаентен ли этот один бакет» вы получаете «ваша организация на 78% против FSBP, вот провальные контролы, ранжированные по серьёзности».
Senior-петля — это одно предложение: обнаружить (GuardDuty, Config) → агрегировать (Security Hub) → маршрутизировать (EventBridge) → реагировать (автоматическая ремедиация или пейдж). Сам Security Hub эмитит свои агрегированные находки в EventBridge, поэтому ты обвязываешь один пайплайн реагирования от Security Hub, а не N пайплайнов от каждого источника. Высокосерьёзные, высокоуверенные находки авто-ремедиируются (вернуть бакет в приватность, изолировать инстанс, отозвать ключ) или пейджат; всё остальное — ранжированный бэклог.
Режим отказа на этом слое — организационный, не технический: включить CloudTrail, GuardDuty, Config и Security Hub, а затем назначить вывод никому. Теперь у вас красивый, дорогой дашборд, который никто не смотрит и которым никто не владеет — а несмотримый алерт идентичен отсутствию алерта. Дисциплина — это инверсия «включи всё»: алертить людей только на высокосерьёзные находки, автоматизировать рутинные ремедиации (публичный бакет, открытый SSH, светящийся ключ), чтобы они чинились сами, и дать бэклогу владельца с SLA. Обнаружение без владения — это театр.
EC2-инстанс с утёкшим кредом роли майнит крипту и эксфильтрирует данные на внешний IP, тогда как отдельный S3-бакет только что сделали публичным плохим деплоем. Какой сервис — ОСНОВНОЙ детектор активной угрозы майнинга/эксфильтрации?
После взлома тебе нужно узнать, действительно ли злоумышленник читал объекты в твоём S3-бакете с данными клиентов. Твой org-трейл логирует только management-события. Что ты можешь определить и почему?
- 01Опиши безоговорочную настройку CloudTrail и противопоставь management-события data-событиям, включая режим отказа при ошибке.
- 02Различи GuardDuty, Config и Security Hub и сформулируй senior-петлю обнаружения и реагирования, включая её главный режим отказа.
Предотвращение (IAM, KMS) — лишь половина безопасности; этот урок — другая половина: обнаруживать и реагировать. CloudTrail — спина аудита: он записывает каждый вызов AWS API (кто, что, когда, откуда), деля их на management-события (control-plane, форензик-спина, первая копия по сути бесплатна) и data-события (чтения объектов S3, вызовы Lambda — высокообъёмные, выключены по умолчанию, ~$0.10/100k, и единственное, что доказывает, читал ли злоумышленник твои данные). Безоговорочная форма — один мультирегиональный трейл организации в заблокированный S3-бакет в отдельном logging-аккаунте с включённой валидацией лог-файлов, так что взломщик, владеющий скомпрометированным аккаунтом, всё равно не сможет удалить или подделать улики — ровно тот отказ, что оставил героя Hook без форензик-таймлайна. CloudTrail записывает, но не судит; GuardDuty судит. Без агентов он анализирует CloudTrail, VPC Flow Logs и DNS-логи через ML и разведку угроз, чтобы помечать активные угрозы — крипто-майнинг, эксфильтрацию кред, аномальный доступ, разведку — и тот же утёкший ключ, что стоил $40k молча, запейджил бы дежурного в тот же час с включённым обнаружением. Его компромисс в том, что малозатратные, высокосигнальные находки всё равно нуждаются в маршрутизации (EventBridge → Lambda/SNS) и триаже, иначе копятся; алертить только на высокую серьёзность. AWS Config отвечает на ортогональный вопрос — настроена ли инфраструктура верно и когда она отдрейфовала — записывая конфигурацию ресурсов во времени, оценивая правила (нет публичного S3, шифрованный EBS, нет открытого SSH) и авто-ремедиируя через SSM; Config — это постура мисконфигурации (незапертая дверь), GuardDuty — активная угроза (кто-то её дёргает), и нужны оба. Security Hub — единое окно, агрегирующее находки GuardDuty, Config, Inspector и Access Analyzer в один нормализованный, приоритизированный вид по организации и оценивающее тебя против CIS и FSBP. Вся senior-петля — обнаружить → агрегировать → маршрутизировать → реагировать, и её доминирующий отказ организационный: включить всё, но не владеть ничем, превращает это в дашборд, который никто не смотрит, что идентично отсутствию обнаружения вовсе. Автоматизируй рутинные ремедиации, пейджи людей только на высокую серьёзность и дай остальному владельца с SLA. Теперь, когда принимаешь аккаунт впервые, первый вопрос: есть ли заблокированный мультирегиональный org-трейл — и пишет ли он в бакет, который никто в этом аккаунте не может удалить?
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.