AWS Centralized Root Access Management (released re:Invent 2024) allows the management account (or a delegated admin) in AWS Organizations to:
- Perform privileged root-only actions on member accounts via
sts:AssumeRoot— without needing root credentials for those accounts. - Remove root credentials (password, MFA, signing certs, access keys) from member accounts entirely.
Once enabled, root sessions are obtained programmatically through STS, scoped to specific task policies, and are short-lived.
Management Account (or Delegated Admin)
│
▼
sts:AssumeRoot (with TaskPolicyArn)
│
▼
Short-lived root session on target member account
│
▼
Perform scoped privileged action (e.g., delete S3 bucket policy, unlock SQS, fix account)
The API call:
{
"Action": "sts:AssumeRoot",
"TargetPrincipal": "arn:aws:iam::123456789012:root",
"TaskPolicyArn": {
"arn": "arn:aws:iam::aws:policy/root-task/IAMAuditRootUserCredentials"
},
"DurationSeconds": 900
}AWS provides a fixed set of task policies that scope what the root session can do:
| Task Policy ARN | What It Allows |
|---|---|
IAMAuditRootUserCredentials |
Audit root user credential status |
IAMCreateRootUserPassword |
Create root user password |
IAMDeleteRootUserCredentials |
Delete root credentials (password, MFA, keys, certs) |
S3UnlockBucketPolicy |
Delete a misconfigured S3 bucket policy that locked everyone out |
SQSUnlockQueuePolicy |
Delete a misconfigured SQS queue policy |
These are AWS-managed — you cannot create custom task policies.
Before this feature, compromising the management account gave you:
- SCP control, OU management, billing, organizational changes
After enabling this feature, compromising the management account additionally gives:
- Root-level access to every member account in the organization
- Ability to create root passwords on member accounts
- Ability to delete root credentials on member accounts (denial of service)
- Ability to unlock and modify locked-down S3 buckets and SQS queues
This is the single biggest risk. The management account becomes a god-mode key for your entire AWS estate.
Service Control Policies (SCPs) only apply to member accounts. The management account is exempt from all SCPs. This means:
- You cannot use SCPs to restrict who calls
sts:AssumeRootfrom the management account - You cannot use SCPs to block root session creation from the management account
- The only controls are IAM policies on the management account itself
An attacker with access to sts:AssumeRoot + IAMCreateRootUserPassword can:
- Assume root on a target member account
- Create a root password for that account
- Log in to that member account as root via the console
- Add their own MFA device
- Now they have persistent root access to that member account, independent of the management account
This survives:
- Removal of their management account access
- Rotation of all IAM user/role credentials
- SCP changes
This is the highest-impact privilege escalation path.
You can delegate root access management to a member account. If that delegated admin account is compromised:
- Attacker gets the same
sts:AssumeRootcapability - SCPs DO apply to delegated admin accounts (better than management account)
- But if SCPs are misconfigured, the delegated admin has org-wide root
All sts:AssumeRoot calls are logged in CloudTrail, but:
- If CloudTrail is misconfigured, disabled, or logs are tampered with in the management account, you lose visibility
- CloudTrail in the management account is the only place where the
AssumeRootcall is logged as the source - The target account sees a root session but not necessarily who initiated it from the management account
An attacker (or misconfigured automation) calling IAMDeleteRootUserCredentials on member accounts can:
- Delete root MFA devices across all accounts
- Delete root passwords, locking legitimate admins out of root recovery
- Delete root signing certificates
- This is a denial-of-service vector against your own organization's break-glass procedures
Compromised IAM user in management account
→ Has sts:AssumeRoot (overly broad)
→ AssumeRoot on any member account with IAMCreateRootUserPassword
→ Create root password on target account
→ Console login as root
→ Full persistent access to member account
Severity: Critical
Compromised role in delegated admin account
→ sts:AssumeRoot scoped to S3UnlockBucketPolicy
→ Unlock a bucket with sensitive data
→ Exfiltrate data, or modify bucket policy to grant external access
→ Pivot to other accounts if AssumeRoot is broadly scoped
Severity: High
Attacker has iam:PutUserPolicy or iam:AttachUserPolicy in management account
→ Attach policy granting sts:AssumeRoot
→ Now has root access to all member accounts
Severity: Critical — This is why IAM write permissions in the management account must be treated as org-wide root-equivalent.
CI/CD pipeline or Lambda in management account
→ Has sts:AssumeRoot for a legitimate automation task
→ Attacker compromises the pipeline (code injection, dependency hijack)
→ Pipeline now calls AssumeRoot with IAMCreateRootUserPassword
→ Persistent backdoor created
Severity: High
Attacker compromises a member account
→ Member account has a role that can assume a role in the management account
→ That management account role has sts:AssumeRoot
→ Attacker now has org-wide root
Severity: Critical — Audit ALL cross-account trust policies pointing into the management account.
Never grant sts:AssumeRoot with * resource. Always scope by target account AND task policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAssumeRootScopedToAuditOnly",
"Effect": "Allow",
"Action": "sts:AssumeRoot",
"Resource": "arn:aws:iam::111122223333:root",
"Condition": {
"StringEquals": {
"sts:TaskPolicyArn": "arn:aws:iam::aws:policy/root-task/IAMAuditRootUserCredentials"
}
}
}
]
}Key conditions to enforce:
| Condition Key | Purpose |
|---|---|
sts:TaskPolicyArn |
Restrict which task policy can be used (MOST IMPORTANT) |
aws:PrincipalOrgID |
Ensure the caller is from your org |
aws:ResourceAccount |
Restrict which target accounts can be assumed into |
aws:SourceIp |
Restrict to known IP ranges |
aws:MultiFactorAuthPresent |
Require MFA for the calling principal |
aws:MultiFactorAuthAge |
Require recent MFA authentication |
This is the most dangerous task policy. Deny it by default.
{
"Sid": "DenyCreateRootPasswordByDefault",
"Effect": "Deny",
"Action": "sts:AssumeRoot",
"Resource": "*",
"Condition": {
"StringEquals": {
"sts:TaskPolicyArn": "arn:aws:iam::aws:policy/root-task/IAMCreateRootUserPassword"
}
}
}Only allow it via a separate break-glass role with:
- MFA required
- IP restriction
- Session duration of 900 seconds (minimum)
- Approval workflow (e.g., require a PIM/JIT elevation)
The management account should contain:
- No applications
- No CI/CD pipelines
- No Lambda functions
- No EC2 instances
- No developer access
Every workload is an attack surface. The management account should be a near-empty control plane.
- Maximum 2-3 human IAM roles (break-glass only)
- No IAM users — use SSO/Identity Center with session policies
- No long-lived access keys
- No service-linked roles beyond what AWS requires
- Audit all roles with
iam:List*andiam:Get*quarterly
Delegating to a member account means SCPs apply to it, giving you an extra layer of control.
{
"Sid": "DenyAssumeRootExceptApprovedAdmin",
"Effect": "Deny",
"Action": "sts:AssumeRoot",
"Resource": "*",
"NotPrincipal": {
"AWS": "arn:aws:iam::DELEGATED_ADMIN_ACCOUNT:role/RootAccessAdmin"
}
}Then apply SCPs to the delegated admin account restricting which task policies it can use.
Member accounts should never call sts:AssumeRoot. Block it org-wide:
{
"Sid": "DenyAssumeRootFromMemberAccounts",
"Effect": "Deny",
"Action": "sts:AssumeRoot",
"Resource": "*"
}Apply this SCP to the root OU. It won't affect the management account (SCPs don't apply there), but it prevents any member account (including a compromised one) from using this API.
{
"Sid": "DenyAssumeRootWithoutMFA",
"Effect": "Deny",
"Action": "sts:AssumeRoot",
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
}
}- Organization trail enabled, logging to a secured S3 bucket in a log archive account
- Management account CloudTrail logs must be immutable (S3 Object Lock, Glacier Vault Lock)
- Real-time alerting on
sts:AssumeRootevents:
EventName = "AssumeRoot"
Alert on:
- Any
AssumeRootcall outside of a change window - Any
AssumeRootwithIAMCreateRootUserPasswordtask policy - Any
AssumeRootfrom an unexpected source IP - Any
AssumeRootfailure (could indicate reconnaissance) - Any
IAMDeleteRootUserCredentialscall
These actions in the management account are root-equivalent because they can lead to sts:AssumeRoot access:
iam:CreateRoleiam:PutRolePolicy/iam:AttachRolePolicyiam:CreateUseriam:PutUserPolicy/iam:AttachUserPolicyiam:CreatePolicyVersioniam:SetDefaultPolicyVersioniam:PassRoleiam:UpdateAssumeRolePolicy
Deny all of these except for a break-glass admin role.
Once centralized root is enabled, remove root credentials from all member accounts:
# Audit first
aws sts assume-root \
--target-principal arn:aws:iam::MEMBER_ACCOUNT:root \
--task-policy-arn arn:aws:iam::aws:policy/root-task/IAMAuditRootUserCredentials \
--duration-seconds 900
# Then delete credentials
aws sts assume-root \
--target-principal arn:aws:iam::MEMBER_ACCOUNT:root \
--task-policy-arn arn:aws:iam::aws:policy/root-task/IAMDeleteRootUserCredentials \
--duration-seconds 900This eliminates the risk of member account root credential compromise entirely.
| What to Monitor | CloudTrail Event | Severity |
|---|---|---|
Any AssumeRoot call |
sts:AssumeRoot |
High |
| Root password creation | AssumeRoot with IAMCreateRootUserPassword |
Critical |
| Root credential deletion | AssumeRoot with IAMDeleteRootUserCredentials |
High |
| Bucket policy unlock | AssumeRoot with S3UnlockBucketPolicy |
Medium |
| Queue policy unlock | AssumeRoot with SQSUnlockQueuePolicy |
Medium |
Failed AssumeRoot attempts |
sts:AssumeRoot with errorCode |
High |
| IAM policy changes in mgmt account | iam:Put*Policy, iam:Attach*Policy, iam:Create* |
Critical |
| New cross-account roles into mgmt account | iam:UpdateAssumeRolePolicy |
Critical |
| CloudTrail modifications in mgmt account | cloudtrail:StopLogging, DeleteTrail, UpdateTrail |
Critical |
| Priority | Action |
|---|---|
| P0 | Zero workloads in the management account |
| P0 | Deny IAMCreateRootUserPassword except break-glass |
| P0 | Scope sts:AssumeRoot by target account + task policy in all IAM policies |
| P0 | Real-time alerting on all AssumeRoot CloudTrail events |
| P0 | Immutable CloudTrail logs in a separate log archive account |
| P1 | SCP denying sts:AssumeRoot from all member accounts |
| P1 | MFA required for all AssumeRoot callers |
| P1 | Remove root credentials from all member accounts |
| P1 | Deny all IAM write actions in management account except break-glass |
| P2 | Use delegated admin instead of management account for day-to-day |
| P2 | IP-restrict AssumeRoot to known admin networks |
| P2 | Quarterly audit of all IAM principals and trust policies in management account |
If I'm targeting an org with centralized root enabled, my kill chain is:
- Find any foothold in the management account — SSO misconfiguration, leaked credentials, cross-account role chain, compromised CI/CD
- Escalate to
sts:AssumeRoot— via IAM policy manipulation or finding an existing role with the permission - Use
IAMCreateRootUserPasswordon a target account — now I have persistent root outside the management account - Cover tracks — disable CloudTrail in the management account if possible, or operate from the newly backdoored member account
The defense must break this chain at every link.