DEV Community

Rocky
Rocky

Posted on

Your Detection Rules Have Ten Years of Windows Logic and Zero Lines for a Stolen IAM Key

Your team has a mature detection stack. Years of rules tuned against real incidents: suspicious parent-child process trees, LSASS access patterns, lateral movement over SMB. Then someone spins up a project in AWS, an access key gets phished out of a CI config file, and the actual attack unfolds entirely inside CloudTrail: a sequence of IAM API calls with no process, no host, no EDR agent anywhere near it. Every detection rule your team has ever written assumes a process tree exists. This attack doesn't have one. It has an audit log, and nobody wrote a rule against it.

This isn't a hypothetical gap, it's the default state of most detection programs, because cloud-native attacks are a genuinely different signal type than the one host and network detection engineering was built around, and the switch from reading process trees to reading API call sequences doesn't happen automatically just because you already know how to write a good detection rule.

Here's the shape of the attack that actually gets missed. A compromised IAM credential, on its own, is not loud. The first thing an attacker with a stolen access key typically does is sts:GetCallerIdentity, to confirm what they've got, followed by a burst of iam:List* and iam:Get* calls: listing roles, listing attached policies, listing users. None of that touches data. None of it deletes anything. On a host, that reconnaissance pattern would look like whoami and a directory listing, mundane enough to ignore. In CloudTrail it's exactly as mundane, and exactly as worth flagging, if you know a normal developer credential doesn't enumerate the entire IAM structure of the account in a two-minute burst right after a login from a new IP.

The actual escalation, when it lands, often isn't a stolen root key. It's a chain: a permission the account holder was actually supposed to have, like iam:PassRole combined with lambda:CreateFunction and lambda:InvokeFunction, used together to pass an over-permissioned role to a new function and invoke it, which is functionally privilege escalation without ever touching a credential the account wasn't allowed to use. This is a well documented category of AWS privilege escalation path, and it does not trip any alert built for Windows or Linux, because there's no process spawning to catch. There's only a specific, unusual combination of IAM API calls, in a specific order, from an identity that doesn't normally make them.

Detecting this takes the same discipline as any good detection rule, just pointed at a different data source: know what normal looks like for a given identity and role, flag reconnaissance-shaped API bursts the same way you'd flag reconnaissance-shaped process activity, and write the rule for the combination of permissions that enables escalation, not just the individual calls, since each one in isolation is something a legitimate deploy script does constantly. The same logic applies across Azure's activity logs, GCP's audit logs, and Kubernetes' own API server audit trail, each with its own version of "the recon call that looks like nothing" and "the permission combination that becomes something."

Codelivly's Cloud Detection and Response Book: AWS, Azure, GCP is built around exactly this translation, turning the detection engineering instincts you already have for hosts and networks into working detection logic against IAM, activity, and audit logs across all three major providers and Kubernetes, instead of leaving that translation for you to reverse-engineer during your first real cloud incident.

Top comments (0)