Skip to content

Module 15 — Cloud Logging & Detection

Type 5 · Detonate & Detect (+ Type 13 · Eval Harness) — take module 14's telemetry, predict which actions the default log captured, and write a Sigma rule for the one worth detecting. (Secondary: Eval Harness — tune against benign noise until it fires on the attack and not the noise, with an explicit false-positive analysis.) Go to the hands-on lab →

Last reviewed: 2026-06

Cloud & Container Securitydetection is not a logging problem; it's an attention problem. The log was always there.

Difficulty: Intermediate  ·  Estimated time: ~4.5–6.5 hrs (study + lab)  ·  Prerequisites: Foundations · Module 14 — Cloud Attack Techniques

In 60 seconds

In both Capital One and LastPass, the log existed the whole time — nobody was watching the stream it landed in. Cloud is comprehensively logged by default, and that abundance breeds a false sense of safety: a detection is a hypothesis scored against a stream that is 99.99% benign, so the hard part is never the true positive — it's making the rule quiet enough that a human still reads its alerts a month from now. You'll take module 14's telemetry, find the data-plane blind spot, write one Sigma rule, and tune it against benign noise. Precision, not recall, is the product — and a rule muted by week two is no coverage at all.

The case

In both of the breaches that bookend this track, the log existed the whole time. Capital One's attacker assumed a role and listed every bucket — and it was in CloudTrail; an outsider, not the company, reported the breach. In the LastPass 2022 incidents, an attacker used keys stolen from a senior engineer to reach S3 and a DynamoDB store and walk out with encrypted customer vaults plus configuration — and the activity ran against logged AWS APIs. Neither breach was a logging failure. The telemetry was generated, signed, and retained. Nobody was watching the stream it landed in.

That is the uncomfortable truth this module turns on: cloud is comprehensively logged by default in a way on-prem never was, and that abundance creates a false sense of safety. A detection is a hypothesis about attacker behaviour scored against a stream that is 99.99% benign — and the hard part is never the true positive. It's making the rule quiet enough that a human will still read its alerts a month from now. So before you read on:

Of the techniques you detonated in module 14, which one shows up loud and clear in CloudTrail by default — and which is nearly invisible?

Your job

By the end of this module you'll take the telemetry from module 14, predict which attacker actions the default log even captured, then write a Sigma rule for the one worth detecting and tune it against benign activity until it fires on the attack and not on the noise. You'll reproduce the same finding in a native detector's event model (GuardDuty / Defender / SCC) and rule on where native coverage is enough and where you must fill the gap. The deliverable is detection-as-code with an explicit false-positive analysis — the artifact a cloud detection engineer is actually paid for.

Call it before you read on

Don't scroll. Commit to these — being wrong is the teaching event, and you'll grade yourself in the lab.

Q1. In module 14 the attacker assumed a role (T1078.004), created an admin user (T1098), and bulk-downloaded objects from S3 (T1530 — the LastPass exfil move). By default, which of those is NOT in CloudTrail at all?

Q2. You write a rule: alert on any CreateUser. It fires perfectly on the attack. Why is it a bad detection — what happens to it in week two?

Q3. A single GetObject is benign a thousand times a day. So is AssumeRole. How do you turn "individually-benign events" into a high-fidelity detection without drowning in false positives?

What fires, revealed

Hold your answers against these.

Q1 — the data plane is dark by default. CloudTrail splits into two planes, and the split is the single most important gotcha in cloud detection. Management eventsAssumeRole, CreateUser, AttachUserPolicy, PutBucketPolicy, RunInstances — are the control plane in log form, and they are logged for free, by default. Data eventss3:GetObject, s3:PutObject, dynamodb:GetItem, lambda:Invoke — are the actual reads and writes against your data, and they are off by default, cost money, and generate enormous volume, so most orgs log them only on a few sensitive buckets. So the answer to Q1 is T1530, the bulk download — the exact move that exfiltrated LastPass's vaults is, in a default account, invisible. The first question in any cloud incident is "were S3 data events enabled for this bucket?" — and the honest, common answer is no, so we cannot tell which objects left. The attacker's loudest action (the one that did the damage) is the one your default log is silent on.

The gotcha

"We have GuardDuty enabled" is not "we detect," and "the log exists" is not "we'd see it." Bulk S3 exfil — the move that did the LastPass damage — leaves no record in a default account because data events are off. The first question in any cloud incident is "were S3 data events enabled for this bucket?", and the common, honest answer is no, so we can't tell which objects left.

Q2 — the false-positive economics is the whole craft. A rule that fires on every CreateUser is correct on the attack and useless in production, because legitimate automation creates users all day. By week two it's muted, ignored, or routed to a folder no one opens — and a muted rule is a non-existent rule that feels like coverage. A detection isn't scored on whether it catches the attack; it's scored on its signal-to-noise on a 99.99%-benign stream. Precision is the product. This is why "we have GuardDuty enabled" is not the same as "we detect": coverage you don't tune is alert fatigue with a dashboard.

The mental model

A detection isn't scored on whether it catches the attack — it's scored on its signal-to-noise on a 99.99%-benign stream. Recall is easy and cheap; precision is the craft. The product you ship is not "a rule that fires," it's "a rule a tired analyst still trusts at 3am."

Q3 — sequence and qualifying context turn benign atoms into a signal. The fix for Q2 is to stop detecting single events and start detecting behaviour. CreateUser alone is noise; CreateUser followed by AttachUserPolicy attaching AdministratorAccess within five minutes from an IP that isn't your CI range is almost never legitimate — and that compound is precise. This is Sigma's job: a YAML detection that names the logsource, the field matches (the interesting fields are nested, in requestParameters and userIdentity — not top-level), the temporal condition, and — the part beginners skip — the falsepositives you've reasoned through. Native detectors (GuardDuty, Defender for Cloud, GCP SCC) ship pre-built versions of exactly this logic over the same control-plane logs; their strength is one-click coverage of common patterns, their weakness is opacity and lag behind the ATT&CK Cloud matrix. The practitioner posture is not "native or open" — it's native as the baseline, Sigma for the gap, and every rule tuned against benign traffic before it's trusted.

AI caveat

A model drafts a passable Sigma rule in seconds — it knows the syntax and the common field names. That's the cheap 80%. The owned 20% it can't do: it doesn't know your benign baseline, so its falsepositives block is generic and its rule is almost always too broad. Run the draft against the lab's benign events, watch it false-fire, then tighten it — the tuned rule plus the explicit "what this must NOT fire on" is yours to own, not the model's to guess.

In the lab you'll do exactly this against the module-14 telemetry: confirm the data-plane blind spot, write and tune one Sigma rule, and reproduce the finding in a native detector's model.

Learn (~3.5 hrs)

Richer than a foundations module — detection engineering is a craft. Read the case first, then the mechanism.

The logging surface and its blind spot (~1 hr) - AWS — CloudTrail concepts: management vs. data events (~30 min) — the primary source. Read "Management events vs. data events"; this is why T1530 is dark by default. The cost/volume model is the reason, not an accident. - AWS — CloudTrail record contents reference (~20 min, bookmark) — every rule references eventName, eventSource, userIdentity.type, sourceIPAddress, requestParameters. Learn where the interesting fields are nested.

Native detectors as the baseline (~1 hr) - AWS — GuardDuty finding types (~30 min, skim) — read the IAM and S3 sections: which techniques native coverage catches and at what confidence. Note what it doesn't cover. - Microsoft — Defender for Cloud security alerts (~20 min) — the Azure equivalent; note the structural parity (finding type, severity, evidence) so the model transfers across clouds.

Sigma — detection-as-code for the gap (~1.5 hrs) - Sigma — rule structure & detection logic (~30 min) — read the Detection section and condition/temporal correlation. This is the format your judgment ships in. - SigmaHQ — CloudTrail rule collection (~1 hr) — read 8–10 real rules. For each, mentally run it against a CloudTrail event: what must match to fire, and what benign thing might also match? Study how the good rules document falsepositives.

Key concepts

  • Management events (default, free) vs. data events (off by default, costly) — and that T1530/S3 exfil is invisible without data events on
  • A detection is a hypothesis scored on a 99.99%-benign stream; precision, not recall, is the product
  • A rule that fires correctly but noisily is muted by week two — a muted rule is no coverage at all
  • Sequence + qualifying context (CreateUserAttachUserPolicy(AdministratorAccess) in 5 min from a non-CI IP) turns benign atoms into a signal
  • Sigma structure: logsource, nested-field detection, temporal condition, and a reasoned falsepositives block
  • Native detector as baseline, Sigma for the gap — and every rule tuned against benign traffic before trust

AI acceleration

Hand a model a plain-English detection ("alert when a role is assumed from an unexpected region, then a bucket policy is changed") and it will draft a passable Sigma rule in seconds — it knows the syntax and the common field names. That's the cheap 80%. The expensive, owned 20% is the part the model can't do for you: it doesn't know your benign baseline, so its falsepositives block is generic and its rule is almost always too broad. Run its draft against the lab's benign events; watch it false-fire; then tighten it and write the FP analysis from what you saw. The judgment-as-code here is the tuned rule plus the explicit "what this must NOT fire on" — that's yours to own, not the model's to guess.

Check yourself

  • Which module-14 technique is not in CloudTrail at all by default, and what setting would have captured it?
  • A rule that alerts on every CreateUser fires perfectly on the attack. Why is it a bad detection by week two?
  • How do you turn individually-benign events (AssumeRole, GetObject) into a high-fidelity detection?

Comments

Sign in with GitHub to comment. Choose the type: Feedback (errors or suggestions on this page) · Hints (help for fellow learners — no spoilers) · General (anything else).