Skip to content

Instantly share code, notes, and snippets.

@RajChowdhury240
Created March 5, 2026 17:51
Show Gist options
  • Select an option

  • Save RajChowdhury240/8a33df04d53ed3bfdfc046a7617c3f32 to your computer and use it in GitHub Desktop.

Select an option

Save RajChowdhury240/8a33df04d53ed3bfdfc046a7617c3f32 to your computer and use it in GitHub Desktop.

AWS Centralized Root Account Management — Security Deep Dive

What It Is

AWS Centralized Root Access Management (released re:Invent 2024) allows the management account (or a delegated admin) in AWS Organizations to:

  1. Perform privileged root-only actions on member accounts via sts:AssumeRoot — without needing root credentials for those accounts.
  2. 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.


How It Works Under the Hood

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.


Risks

1. Management Account Is Now the Ultimate Single Point of Failure

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.

2. SCPs Do NOT Apply to the Management Account

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:AssumeRoot from 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

3. IAMCreateRootUserPassword Enables Persistent Backdoors

An attacker with access to sts:AssumeRoot + IAMCreateRootUserPassword can:

  1. Assume root on a target member account
  2. Create a root password for that account
  3. Log in to that member account as root via the console
  4. Add their own MFA device
  5. 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.

4. Delegated Admin Expands the Blast Radius

You can delegate root access management to a member account. If that delegated admin account is compromised:

  • Attacker gets the same sts:AssumeRoot capability
  • SCPs DO apply to delegated admin accounts (better than management account)
  • But if SCPs are misconfigured, the delegated admin has org-wide root

5. CloudTrail Dependency for Detection

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 AssumeRoot call is logged as the source
  • The target account sees a root session but not necessarily who initiated it from the management account

6. Root Credential Deletion Can Be Weaponized

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

Privilege Escalation Paths

Path 1: Management Account IAM User → Org-Wide Root

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

Path 2: Delegated Admin Role → Lateral Movement to All Member Accounts

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

Path 3: IAM Policy Manipulation → Escalate to AssumeRoot

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.

Path 4: Confused Deputy via Automation

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

Path 5: Cross-Account Role Chain → Management Account → AssumeRoot

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.


Lockdown Guide — Least Privilege

1. Restrict sts:AssumeRoot to the Absolute Minimum

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

2. Deny IAMCreateRootUserPassword Unless Break-Glass

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)

3. Zero Workloads in the Management Account

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.

4. Minimize IAM Principals in the Management Account

  • 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* and iam:Get* quarterly

5. Use a Delegated Admin (with Caution)

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.

6. SCP to Block All Member Accounts from Calling AssumeRoot

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.

7. Enforce MFA on All AssumeRoot Callers

{
  "Sid": "DenyAssumeRootWithoutMFA",
  "Effect": "Deny",
  "Action": "sts:AssumeRoot",
  "Resource": "*",
  "Condition": {
    "BoolIfExists": {
      "aws:MultiFactorAuthPresent": "false"
    }
  }
}

8. CloudTrail and Alerting

  • 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:AssumeRoot events:
EventName = "AssumeRoot"

Alert on:

  • Any AssumeRoot call outside of a change window
  • Any AssumeRoot with IAMCreateRootUserPassword task policy
  • Any AssumeRoot from an unexpected source IP
  • Any AssumeRoot failure (could indicate reconnaissance)
  • Any IAMDeleteRootUserCredentials call

9. Lock Down IAM Write Permissions in the Management Account

These actions in the management account are root-equivalent because they can lead to sts:AssumeRoot access:

  • iam:CreateRole
  • iam:PutRolePolicy / iam:AttachRolePolicy
  • iam:CreateUser
  • iam:PutUserPolicy / iam:AttachUserPolicy
  • iam:CreatePolicyVersion
  • iam:SetDefaultPolicyVersion
  • iam:PassRole
  • iam:UpdateAssumeRolePolicy

Deny all of these except for a break-glass admin role.

10. Remove Root Credentials from Member Accounts

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 900

This eliminates the risk of member account root credential compromise entirely.


Detection and Monitoring Checklist

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

Summary — Security Posture Priorities

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

The Attacker's Perspective

If I'm targeting an org with centralized root enabled, my kill chain is:

  1. Find any foothold in the management account — SSO misconfiguration, leaked credentials, cross-account role chain, compromised CI/CD
  2. Escalate to sts:AssumeRoot — via IAM policy manipulation or finding an existing role with the permission
  3. Use IAMCreateRootUserPassword on a target account — now I have persistent root outside the management account
  4. 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment