← All field notes
awscloudformationfor responders

One StackSet operation, a backdoor in every AWS account

Service-managed StackSets fan out automatically, so one CreateStackInstances call can plant a backdoor role in every account in an AWS Organization. Here is how to contain it.

Persistence does not have to be planted account by account. With service-managed StackSets, an attacker plants it everywhere in a single operation.

How the attack works

The attacker reaches the management account or a delegated StackSets administrator and creates a service-managed StackSet whose template provisions a backdoor IAM role. A single CreateStackInstances call targets all organizational units, and the StackSet fans the stack out automatically to every member account. Within minutes the same trust role is live everywhere, and the attacker begins assuming it across accounts for broad, uniform, persistent control. CloudTrail in the admin account records the StackSet operations and exactly which instance targets they hit, while member-account CloudTrail confirms the planted resources and any AssumeRole use. This maps to T1078.004, Valid Accounts: Cloud Accounts, and T1098, Account Manipulation.

Why it works

StackSets exist to deploy a baseline to every account at once, so whoever controls the StackSet administration path holds org-wide deployment power. There is usually no guardrail distinguishing an approved baseline from a template that creates new trust roles.

How to fix it

Cleaning the one account where you first spotted the role is a trap: the backdoor remains org-wide and the StackSet simply redeploys it. The non-obvious containment is to delete the rogue stack instances across every targeted account and delete the StackSet itself so it cannot redeploy, then revoke the StackSet admin role’s session. Durably, restrict that admin role to a tightly controlled set, require change-controlled templates, add service control policy guardrails on the StackSet actions, and alert on every StackSet create and update.

Practice it

We built this as a GraphLattice Range scenario so responders can rehearse scoping the org-wide blast radius and removing instances everywhere before the backdoor is used.