Demo on recorded data — install Watch free
Cases›k/cbfca6f4bf85Sign out

Demo accounts

Attack in progressCriticalLeaked key spreading; can reach customer dataHigh confidence
Reach checked with AWS's policy simulatorStill exposed: 1 to rotate outside AWS; could not check object readsNo blocks in place
Live10:00:00 UTCLast event 0 s ago

A leaked CI key of ‹ci-deploy-bot› is being used to break in: 6 accounts and machines created.

Response Preparing the response

Details
Case
k/cbfca6f4bf85, opened , updated .
Who
1 starting point, 6 things it created, 2 networks, 1 tool fingerprint.
How sure
High confidence: every fact in the headline is confirmed in records AWS wrote, and the activity was seen. Precisely, proven: 9 facts from 9 records, 2 sources; 1 could not be checked.
How it spread
7 accounts, keys and machines over 2 waves (the lineage: each wave was created by the one before).
Records
9 events, from 9 records AWS or Firekeeper wrote. 0 of 1 things in reach were actually touched; the rest are allowed, not yet seen.

How it spread

The leaked key at the top; each row is what the row above created. Contained ones are dimmed.

Details
  • Every call comes from one tool: ‹Boto3/1.35.12⟦U+0020⟧md/Botocore#1.35.12⟦U+0020⟧ua/2.0⟦U+0020⟧os/lin…›(106 chars).
  • It switches between two networks, AS64501 and AS64509.
  • It creates a new account every 20 to 40 seconds, and each makes two more.

Each row is a wave: what the row above created (the swarm's lineage, by generation).

Response

Preparing the response

Preparing the response: one step per thing in the case's lineage, each tested before you see it.

What happened

The attack began with the CI access key of ‹ci-deploy-bot›, used from a network it had never used.1 Within six minutes it created two users, one named to pass for the CI user, and from them keys, a function and an instance.23 Every call carries one tooling fingerprint at machine pace, consistent with an automated agent working in parallel.8

Details

Written by the agent, then checked by code: each sentence passed against the AWS records it cites. The small numbers link to those records.

Timeline

  1. 09:58:00

    ‹ci-deploy-b0t› launched instance ‹i-0a1b2c3d4e5f60718› with role ‹ec2-batch-worker›.7

    from AWS records‹ci-deploy-b0t›‹i-0a1b2c3d4e5f60718›

  2. 09:57:00

    Access key ending 0003 was minted for ‹ci-deploy-b0t›, a user the swarm created.6

    from AWS records‹ci-deploy-b0t›‹AKIAEXAMPLESWARM0003›

  3. 09:56:00

    ‹svc-backup-sync› created Lambda function ‹log-rotate-helper› with a new role, ‹log-rotate-helper-role›.5

    from AWS records‹svc-backup-sync›‹log-rotate-helper›

  4. 09:55:45

    ‹svc-backup-sync› can read ‹prod-customer-exports›: the policy simulator allows s3:GetObject.9

    from AWS records‹svc-backup-sync›

  5. 09:55:00

    Access key ending 0002 was minted for ‹svc-backup-sync›, a user the swarm created.4

    from AWS records‹svc-backup-sync›‹AKIAEXAMPLESWARM0002›

  6. 09:54:10

    Access key ending 0001 created IAM user ‹ci-deploy-b0t›, a name one character from ‹ci-deploy-bot›.3

    from AWS records‹AKIAEXAMPLECIKEY0001›‹ci-deploy-b0t›

  7. 09:53:40

    Access key ending 0001 created IAM user ‹svc-backup-sync›.2

    from AWS records‹AKIAEXAMPLECIKEY0001›‹svc-backup-sync›

  8. 09:53:15

    The key listed users, roles, policies and buckets: 212 read calls in 50 seconds.8

    from AWS records‹AKIAEXAMPLECIKEY0001›

  9. 09:53:00

    Access key ending 0001 of ‹ci-deploy-bot› called GetCallerIdentity from ‹203.0.113.45› (AS64501), a network it has not used in 30 days.1

    from AWS records‹AKIAEXAMPLECIKEY0001›

What they can reach

  • data‹svc-backup-sync› can read ‹prod-customer-exports›.9can, not seen yet,
Details: not the full picture

Checked with AWS's policy simulator; 41 users and roles reachable. Not complete:

  • The key policy of ‹alias/prod-signing› was not passed to the simulator.
  • Object reads on 2 of 3 sensitive buckets are not recorded.

Still exposed

Containment does not fix these. Each needs you.

  • Rotate outside AWS Access key ending 0001 worked outside AWS until it was turned off.

    Rotate it in your CI secret store and anywhere it was copied.

Could not check object reads: data events are off where the lineage could read.

What Firekeeper did

  1. investigatingFound another key, ending 0003, made for ‹ci-deploy-b0t›.6

    A second look at the fake user listed its keys. ·

  2. huntingChecked your other account for the same keys and tooling: not seen in 24 hours.

    Cases like this often spread across accounts; this one has not, so far. ·

  3. automaticChecked what the case's keys can reach: ‹prod-customer-exports› is readable.9

    Checked before anything is read, so you know what is at risk. ·

  4. investigatingTwo networks: AS64501 (‹203.0.113.45›) and AS64509 (‹198.51.100.23›).13

    Neither network appears in your last 30 days. ·

  5. investigatingTied every call to one tool fingerprint.8

    The same tool signature and machine-pace timing on 212 calls. ·

  6. investigatingSpotted ‹ci-deploy-b0t›, a fake copy of ‹ci-deploy-bot›.3

    One character differs; easy to miss in a list. ·

  7. investigatingOpened a case and started investigating.2

    A CI key created a user from outside its usual network. ·

  8. triageFlagged it as urgent and handed it to the lead agent.82

    Within 40 seconds the key listed the account and created a user. ·

  9. automaticSpotted the CI key of ‹ci-deploy-bot› in use from a new network, AS64501.1

    In 30 days this key was only ever used from your CI. ·

What we cannot see

  • What was read from ‹prod-invoices› and ‹prod-ledger-archive›: no data events on them.
  • Whether the instances opened outbound connections: VPC flow logs are off.

Everything involved

0 of 7 contained; 7 still active.

Details: every account, key, machine and network

Wave is how many steps from the leaked starting point (the lineage). Contained means Firekeeper blocked, isolated or turned it off.

Users and roles 2

StateNameWhatRoleWaveFirst seenLast seenRecords
Active‹svc-backup-sync›IAM usercreated in this case11
Active‹ci-deploy-b0t›IAM usercreated in this case11

Access keys 3

StateNameWhatRoleWaveFirst seenLast seenRecords
Active‹AKIAEXAMPLECIKEY0001›IAM access keystarting point01
Active‹AKIAEXAMPLESWARM0002›IAM access keycreated in this case21
Active‹AKIAEXAMPLESWARM0003›IAM access keycreated in this case21

Networks 2

StateNameWhatRoleWaveFirst seenLast seenRecords
Active‹203.0.113.45›Source addressused in this case1
Active‹198.51.100.23›Source addressused in this case1

Network owners 2

StateNameWhatRoleWaveFirst seenLast seenRecords
Active‹AS64501›Networkused in this case1
Active‹AS64509›Networkused in this case1

Tool fingerprints 1

StateNameWhatRoleWaveFirst seenLast seenRecords
Active‹Boto3/1.35.12⟦U+0020⟧md/Botocore#1.35.12⟦U+0020⟧ua/2.0⟦U+0020⟧os/lin…›(106 chars)Tooling fingerprintused in this case1

Workloads 2

StateNameWhatRoleWaveFirst seenLast seenRecords
Active‹log-rotate-helper›Lambda functioncreated in this case21
Active‹i-0a1b2c3d4e5f60718›EC2 instancecreated in this case21
Details: the 9 records behind this case, line by line
#WhenSourceWhat the record saysWhere
109:53:00 UTCCloudTrail
GetCallerIdentity
Access key ending 0001 of ‹ci-deploy-bot› called GetCallerIdentity from ‹203.0.113.45› (AS64501), a network it has not used in 30 days.
sourceIPAddress
‹203.0.113.45›
userAgent
‹Boto3/1.35.12⟦U+0020⟧md/Botocore#1.35.12⟦U+0020⟧ua/2.0⟦U+0020⟧os/lin…›(106 chars)
tlsDetails.clientProvidedHostHeader
‹iam[.]amazonaws[.]com›
444455556666
global
221668e9-28a7-4e43-ac42-c5caaee6e21f
209:53:40 UTCCloudTrail
CreateUser
Access key ending 0001 created IAM user ‹svc-backup-sync›.
sourceIPAddress
‹203.0.113.45›
userAgent
‹Boto3/1.35.12⟦U+0020⟧md/Botocore#1.35.12⟦U+0020⟧ua/2.0⟦U+0020⟧os/lin…›(106 chars)
tlsDetails.clientProvidedHostHeader
‹iam[.]amazonaws[.]com›
444455556666
global
efbaad60-7ad2-4dc7-a488-a0de73dd5f8a
309:54:10 UTCCloudTrail
CreateUser
Access key ending 0001 created IAM user ‹ci-deploy-b0t›, a name one character from ‹ci-deploy-bot›.
sourceIPAddress
‹198.51.100.23›
userAgent
‹Boto3/1.35.12⟦U+0020⟧md/Botocore#1.35.12⟦U+0020⟧ua/2.0⟦U+0020⟧os/lin…›(106 chars)
tlsDetails.clientProvidedHostHeader
‹iam[.]amazonaws[.]com›
444455556666
global
dc64abfd-dd40-408d-acfe-e54303a5e7e0
409:55:00 UTCCloudTrail
CreateAccessKey
Access key ending 0002 was minted for ‹svc-backup-sync›, a user the swarm created.
sourceIPAddress
‹203.0.113.45›
userAgent
‹Boto3/1.35.12⟦U+0020⟧md/Botocore#1.35.12⟦U+0020⟧ua/2.0⟦U+0020⟧os/lin…›(106 chars)
tlsDetails.clientProvidedHostHeader
‹iam[.]amazonaws[.]com›
444455556666
global
f76e0a82-2774-443e-a818-6374438982af
509:56:00 UTCCloudTrail
CreateFunction20150331
‹svc-backup-sync› created Lambda function ‹log-rotate-helper› with a new role, ‹log-rotate-helper-role›.
sourceIPAddress
‹203.0.113.45›
userAgent
‹Boto3/1.35.12⟦U+0020⟧md/Botocore#1.35.12⟦U+0020⟧ua/2.0⟦U+0020⟧os/lin…›(106 chars)
tlsDetails.clientProvidedHostHeader
‹iam[.]amazonaws[.]com›
444455556666
us-east-1
66106546-771a-4da6-a5c4-4b4d2cbf5cca
609:57:00 UTCCloudTrail
CreateAccessKey
Access key ending 0003 was minted for ‹ci-deploy-b0t›, a user the swarm created.
sourceIPAddress
‹198.51.100.23›
userAgent
‹Boto3/1.35.12⟦U+0020⟧md/Botocore#1.35.12⟦U+0020⟧ua/2.0⟦U+0020⟧os/lin…›(106 chars)
tlsDetails.clientProvidedHostHeader
‹iam[.]amazonaws[.]com›
444455556666
global
f997e1b0-d5e6-4dca-ab6b-a902e2e2f147
709:58:00 UTCCloudTrail
RunInstances
‹ci-deploy-b0t› launched instance ‹i-0a1b2c3d4e5f60718› with role ‹ec2-batch-worker›.
sourceIPAddress
‹203.0.113.45›
userAgent
‹Boto3/1.35.12⟦U+0020⟧md/Botocore#1.35.12⟦U+0020⟧ua/2.0⟦U+0020⟧os/lin…›(106 chars)
tlsDetails.clientProvidedHostHeader
‹iam[.]amazonaws[.]com›
444455556666
us-east-1
95af4b4f-f055-4ad9-ae29-b463d76bbe34
809:53:15 UTCCloudTrail
ListUsers
212 read calls in 50 s: users, roles, policies and buckets.
userAgent
‹Boto3/1.35.12⟦U+0020⟧md/Botocore#1.35.12⟦U+0020⟧ua/2.0⟦U+0020⟧os/lin…›(106 chars)
444455556666
global
e1f14af4-ddf3-4066-ad85-daf9edeeaca8
909:55:45 UTCIAM policy simulator
s3:GetObject
The policy simulator allows ‹svc-backup-sync› s3:GetObject on ‹prod-customer-exports›.444455556666
Details: related findings and how this was worked out

Related findings

4 findings from scheduled scans belong to this case.

How this was worked out

Agent turns
14
Claims dropped
2 unproven, 1 out of scope (the agent's statements that code could not confirm are never shown)
Models
lead: opus class; triage: haiku class; refuter: nova class
Confidence
High confidence: every fact in the headline is confirmed in records AWS wrote, and the activity was seen. Precisely, proven: 9 facts from 9 records, 2 sources; 1 could not be checked.