Attack in progressA leaked CI key of ‹ci-deploy-bot› is being used to break in: 6 accounts and machines created.Open the case
Demo accounts
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 responsePreparing 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
- 09:58:00
‹ci-deploy-b0t› launched instance ‹i-0a1b2c3d4e5f60718› with role ‹ec2-batch-worker›.7
- 09:57:00
Access key ending 0003 was minted for ‹ci-deploy-b0t›, a user the swarm created.6
- 09:56:00
‹svc-backup-sync› created Lambda function ‹log-rotate-helper› with a new role, ‹log-rotate-helper-role›.5
- 09:55:45
‹svc-backup-sync› can read ‹prod-customer-exports›: the policy simulator allows s3:GetObject.9
- 09:55:00
Access key ending 0002 was minted for ‹svc-backup-sync›, a user the swarm created.4
- 09:54:10
Access key ending 0001 created IAM user ‹ci-deploy-b0t›, a name one character from ‹ci-deploy-bot›.3
- 09:53:40
Access key ending 0001 created IAM user ‹svc-backup-sync›.2
- 09:53:15
The key listed users, roles, policies and buckets: 212 read calls in 50 seconds.8
- 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
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
investigatingFound another key, ending 0003, made for ‹ci-deploy-b0t›.6
A second look at the fake user listed its keys. ·
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. ·
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. ·
investigatingTwo networks: AS64501 (‹203.0.113.45›) and AS64509 (‹198.51.100.23›).13
Neither network appears in your last 30 days. ·
investigatingTied every call to one tool fingerprint.8
The same tool signature and machine-pace timing on 212 calls. ·
investigatingSpotted ‹ci-deploy-b0t›, a fake copy of ‹ci-deploy-bot›.3
One character differs; easy to miss in a list. ·
investigatingOpened a case and started investigating.2
A CI key created a user from outside its usual network. ·
triageFlagged it as urgent and handed it to the lead agent.82
Within 40 seconds the key listed the account and created a user. ·
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
| State | Name | What | Role | Wave | First seen | Last seen | Records |
|---|---|---|---|---|---|---|---|
| Active | ‹svc-backup-sync› | IAM user | created in this case | 1 | 1 | ||
| Active | ‹ci-deploy-b0t› | IAM user | created in this case | 1 | 1 |
Access keys 3
| State | Name | What | Role | Wave | First seen | Last seen | Records |
|---|---|---|---|---|---|---|---|
| Active | ‹AKIAEXAMPLECIKEY0001› | IAM access key | starting point | 0 | 1 | ||
| Active | ‹AKIAEXAMPLESWARM0002› | IAM access key | created in this case | 2 | 1 | ||
| Active | ‹AKIAEXAMPLESWARM0003› | IAM access key | created in this case | 2 | 1 |
Networks 2
| State | Name | What | Role | Wave | First seen | Last seen | Records |
|---|---|---|---|---|---|---|---|
| Active | ‹203.0.113.45› | Source address | used in this case | 1 | |||
| Active | ‹198.51.100.23› | Source address | used in this case | 1 |
Network owners 2
| State | Name | What | Role | Wave | First seen | Last seen | Records |
|---|---|---|---|---|---|---|---|
| Active | ‹AS64501› | Network | used in this case | 1 | |||
| Active | ‹AS64509› | Network | used in this case | 1 |
Tool fingerprints 1
| State | Name | What | Role | Wave | First seen | Last seen | Records |
|---|---|---|---|---|---|---|---|
| Active | ‹Boto3/1.35.12⟦U+0020⟧md/Botocore#1.35.12⟦U+0020⟧ua/2.0⟦U+0020⟧os/lin…›(106 chars) | Tooling fingerprint | used in this case | 1 |
Workloads 2
Details: the 9 records behind this case, line by line
| # | When | Source | What the record says | Where |
|---|---|---|---|---|
| 1 | 09:53:00 UTC | CloudTrail 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.
| 444455556666 global 221668e9-28a7-4e43-ac42-c5caaee6e21f |
| 2 | 09:53:40 UTC | CloudTrail CreateUser | Access key ending 0001 created IAM user ‹svc-backup-sync›.
| 444455556666 global efbaad60-7ad2-4dc7-a488-a0de73dd5f8a |
| 3 | 09:54:10 UTC | CloudTrail CreateUser | Access key ending 0001 created IAM user ‹ci-deploy-b0t›, a name one character from ‹ci-deploy-bot›.
| 444455556666 global dc64abfd-dd40-408d-acfe-e54303a5e7e0 |
| 4 | 09:55:00 UTC | CloudTrail CreateAccessKey | Access key ending 0002 was minted for ‹svc-backup-sync›, a user the swarm created.
| 444455556666 global f76e0a82-2774-443e-a818-6374438982af |
| 5 | 09:56:00 UTC | CloudTrail CreateFunction20150331 | ‹svc-backup-sync› created Lambda function ‹log-rotate-helper› with a new role, ‹log-rotate-helper-role›.
| 444455556666 us-east-1 66106546-771a-4da6-a5c4-4b4d2cbf5cca |
| 6 | 09:57:00 UTC | CloudTrail CreateAccessKey | Access key ending 0003 was minted for ‹ci-deploy-b0t›, a user the swarm created.
| 444455556666 global f997e1b0-d5e6-4dca-ab6b-a902e2e2f147 |
| 7 | 09:58:00 UTC | CloudTrail RunInstances | ‹ci-deploy-b0t› launched instance ‹i-0a1b2c3d4e5f60718› with role ‹ec2-batch-worker›.
| 444455556666 us-east-1 95af4b4f-f055-4ad9-ae29-b463d76bbe34 |
| 8 | 09:53:15 UTC | CloudTrail ListUsers | 212 read calls in 50 s: users, roles, policies and buckets.
| 444455556666 global e1f14af4-ddf3-4066-ad85-daf9edeeaca8 |
| 9 | 09:55:45 UTC | IAM 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.