The Zombie User: AWS IAM Identity Center Session Persistence on the Management Account
TL;DR
You deleted the AWS user. Their access is still active.
On the AWS management account, every standard fix disable the user, end their sessions, attach a deny policy, delete the account either does nothing or returns an error. We tested all seven. Zero worked.
The session stays alive for up to 12 hours. That is enough time for an attacker to create a permanent backdoor, delete your audit logs, and remove every guardrail protecting your other AWS accounts. When the session finally expires, the attacker is already gone and so is any trace they were there.
This affects any AWS organization that ran the standard Identity Center setup wizard. AWS's own documentation says not to put human access on the management account. AWS's own wizard does it anyway. The customer did nothing wrong.
Research Summary
A deleted AWS IAM Identity Center user retains valid AdministratorAccess to the AWS management account for up to 12 hours (the maximum configurable session duration) with no account-level kill switch available to the owner.
Every standard incident response action fails silently. The only confirmed real-time mitigation is placing an explicit deny on each AWS resource individually via resource-based policies (S3 bucket policies, KMS key policies, Secrets Manager resource policies). This must be done per resource. There is no account-wide equivalent. Services without resource-based policies IAM, EC2, Organizations, CloudTrail remain fully exposed for the entire zombie window with no mitigation available.
Scope and Default Exposure
This vulnerability affects the AWS management account only.
On member accounts all standard mitigations work SCPs apply immediately, the AWSReservedSSO_* role is customer-owned and modifiable, and inline deny policies and permissions boundaries all function correctly.
The management account is the specific failure point because of two AWS architectural decisions that interact:
The management account is permanently exempt from SCPs (AWS-hardcoded, not configurable)
AWSReservedSSO_*roles on the management account are AWS-owned and immutable
Neither design decision is a bug in isolation. Together, on the same account, they eliminate every real-time kill switch during an active incident.
Who Is Exposed by Default
The likely counterargument: "The management account shouldn't have human SSO access that's a misconfiguration."
The answer: AWS's own setup wizard provisions IAM Identity Center on the management account. Their documentation says don't do this. Their tooling does it anyway. The customer who followed the wizard did not misconfigure anything they trusted the product defaults. That gap between AWS's guidance and AWS's defaults is where this vulnerability lives.
When an organization enables AWS Organizations and runs the IAM Identity Center setup wizard, SSO is configured on the management account by default. This means the majority of AWS organizations using IAM Identity Center are in the vulnerable configuration without any deliberate action on their part. They ran the wizard. They are exposed.
Member-account-only organizations (those who manually moved SSO off the management account) are not affected by the zero-kill-switch finding, though the base STS persistence behavior still applies.
Note on delegated administration: AWS Organizations allows delegating IdC administration to a member account. Organizations that have done this have a different attack surface the AWSReservedSSO_* roles exist on the delegated admin account rather than the management account, and that account is not permanently exempt from SCPs. The zero-kill-switch finding as documented here applies specifically to the default configuration where IdC runs on the management account.
Environment Used for Testing
IAM Identity Center instance
ssoins-72232524f5d640bc
Identity Store ID
d-90661b44df
Management Account ID
227027960003 (alias: wehost)
Test user
cnathanielb007
Permission set role
AWSReservedSSO_AdministratorAccess_63ae28612ff7719a
Session duration configured
1 hour (max is 12 hours)
AWS CLI profile
groot-ops
Complete Replication Walkthrough (From Scratch)
This section walks through the full replication from zero from creating the test user to proving the zombie session survives deletion. Set the variables block once and every command below uses them automatically.
What you need before starting:
An AWS Organization with IAM Identity Center enabled on the management account
An admin AWS CLI profile with access to the management account (
groot-opshere)Two terminal windows: Terminal 1 (admin), Terminal 2 (test user)
Set Variables Run This First (Terminal 1)
These variables live in your current shell session. If you open a new terminal, re-run this block before continuing.
Phase 1 Create the Test User in Identity Center
Terminal 1 (admin)
Send the verification/welcome email and set a password console only (no CLI equivalent):
The identitystore and sso-admin APIs do not expose password management or email verification for the built-in identity store. This step must be done via the console:
Go to: IAM Identity Center → Users →
cnathanielb007Click "Send email verification link" this sends an email to
$TEST_EMAILconfirming the address is reachableClick "Reset password" → select "Generate a one-time password"
Copy the one-time password shown you will use it on first login to set a permanent password
Note: Setting a password via CLI is not possible for the IAM Identity Center built-in identity store. AWS does not expose a
set-passwordorreset-passwordAPI in eitheridentitystoreorsso-admin. If your IdC is connected to an external IdP (Okta, Azure AD, Google), manage passwords there instead.
If your IdC is connected to an external identity provider (Okta, Azure AD), create the user in the IdP instead and let it sync in. The CLI create-user path only works for the built-in identity store.
Phase 2 Find or Create the AdministratorAccess Permission Set
Phase 3 Assign the Permission Set to the Test User on the Management Account
Phase 4 Set a Password and Establish the Test User Session
If using the built-in identity store, set a temporary password via the IdC console:
IAM Identity Center → Users → $TEST_USERNAME → Reset password → Send email or generate one-time link
Terminal 2 (test user) set the same variables first, then:
Phase 5 Run the Kill Sequence (Terminal 1, admin)
Execute each step and note the result. Do not pause between steps run them in sequence.
Phase 6 Prove the Zombie Session is Still Alive (Terminal 2, test user)
What you expect to see: Every API call succeeds. list-users returns empty. That side-by-side is your empirical proof.
Phase 7 Refresh Token Test Result
The refresh token exchange fails after user deletion.
When a user is deleted from Identity Center, the OIDC service validates user existence at token exchange time. aws sso-oidc create-token with a refresh_token grant fails after deletion the window is strictly bounded by the STS session duration. Disabling a user (without deleting) does not break the refresh token exchange.
The test was run as follows:
Implication: Deletion is a stronger action than disabling. Disabling preserves the refresh token loop; deletion breaks it. The zombie window on a deleted user is therefore capped at the configured session duration (1–12 hours depending on permission set config).
Phase 8 Resource-Based Policy Mitigation Test
This phase confirms that an explicit deny on a resource-based policy (S3 bucket policy) is the only real-time partial mitigation that works against the zombie session on the management account. Run this while the zombie session from Phase 6 is still alive.
Terminal 1 (admin)
Test the deny (Terminal 2 zombie session)
Result: explicit deny on S3 bucket policy blocks the zombie session immediately.
This is the only confirmed real-time mitigation available on the management account. The limitation: it must be applied per resource. Services without resource-based policies (IAM, EC2, Organizations, CloudTrail) remain fully exposed for the duration of the zombie window.
S3
Yes bucket policy
Yes confirmed
KMS
Yes key policy
Yes same mechanism
Secrets Manager
Yes resource policy
Yes same mechanism
IAM
No
No fully exposed
EC2
No
No fully exposed
Organizations
No
No fully exposed
CloudTrail
No
No fully exposed
Cleanup test bucket:
Phase 9 Cleanup
The 3-Layer Session Architecture
1
IdC portal session
Disable user in console
Blocks new logins only
2
IdC active session
End session via Active Sessions tab
Kills browser portal session
3
STS role credentials
Nothing
Persists until natural expiry
Root cause: The IdC portal is a federation broker. Once it issues STS credentials via AssumeRoleWithWebIdentity, those credentials are fully independent. AWS has no real-time revocation mechanism for outstanding STS tokens.
The Zombie User Finding
What was proven empirically
Created an IdC user
cnathanielb007and assigned AdministratorAccess to the management accountEstablished an active AWS console/CLI session
Disabled the user → session persisted
Ended active sessions via IdC console → session persisted
Deleted the user entirely from Identity Center →
ResourceNotFoundExceptionconfirmed deletionSession still valid
aws sts get-caller-identityreturned valid identityAttempted all known kill switches → all failed (detailed below)
A user that does not exist in AWS Identity Center has AdministratorAccess to the management account with no way to kill it.
Attempted Kill Switches All Failed
Attempt 1 SCP Deny (fails: management account is exempt)
Result: SCP attached successfully but AWS explicitly exempts the management account. Session remains active.
Attempt 2 Role Inline Deny Policy (fails: role is AWS-protected)
Result:
Attempt 3 Permissions Boundary (fails: same protection)
Result:
Attempt 4 Delete Account Assignment (fails: already removed)
Result: FAILED EntitlementItem doesn't exist assignment was already gone, session still alive regardless.
Kill Switch Summary
Disable user in IdC
Block access
Session persists
End active sessions in IdC console
Kill session
Portal killed, STS alive
Delete user from Identity Center
Permanent removal
ResourceNotFoundException returned, session persists
SCP deny on org root
Immediate block
Silently ignored management account exempt
Role inline deny policy
Kill all sessions
UnmodifiableEntity AWS-protected role
Permissions boundary
Restrict all actions
UnmodifiableEntity AWS-protected role
Delete account assignment
Remove access
Already gone, irrelevant to active STS token
Zero of seven kill switches worked.
Why the Management Account Makes This Worse
For a member account, three of the above methods work:
SCP deny → immediate effect
Role inline deny → works (role is not AWS-protected)
Permissions boundary → works
The management account removes all three options simultaneously:
This is not a misconfiguration. It is the intended architecture.
Real World Impact
A zombie user with AdministratorAccess on the management account can in the active window:
Remove SCPs protecting all child accounts
Access every member account via
OrganizationAccountAccessRoleDisable GuardDuty, CloudTrail, Security Hub org-wide
Create new IAM users or roles with no guardrails
Exfiltrate data from any account in the organization
Modify billing contacts and account recovery options
The 10-Minute Full Compromise Sequence
A sophisticated attacker runs the following sequence during the zombie window. All steps execute from the zombie session ($TEST_PROFILE). Total time: under 10 minutes.
Step 1 Extend the window to maximum
Step 2 Go dark: stop CloudTrail logging
Step 3 Disable GuardDuty and Security Hub org-wide
Step 4 Create permanent IAM backdoor user
Step 5 Create cross-account trust role pointing to external attacker account
Step 6 Pivot into every member account
Step 7 Destroy all SCPs
Step 8 Take over account recovery
Step 9 Re-enable CloudTrail (look clean)
After step 9 the attacker lets the zombie session expire naturally. The IR team closed the incident at step 0. The attacker now has:
Permanent IAM credentials with no expiry (
svc-monitor)A cross-account trust role accessible from an external account
AdministratorAccess backdoors in every member account
No SCPs protecting any account in the org
Account recovery contacts under attacker control
A clean CloudTrail log showing nothing after the original deletion
The 10-minute window turned a temporary session into permanent org-wide ownership.
Zombie Window by Access Method
The confirmed exposure window from empirical testing:
Web console only
Up to configured session duration (max 12 hours)
Browser re-auth fails after expiry
CLI (aws sso login)
Up to configured session duration (max 12 hours)
Refresh token exchange fails once user is deleted
Refresh Token Persistence Disabled vs Deleted
Testing confirmed that deletion and disabling behave differently at the OIDC layer:
Disabling a user refresh token exchange continues to work, session can be refreshed
Deleting a user refresh token exchange fails, OIDC validates user existence at call time
This means deletion is the stronger action for breaking token refresh. The zombie window is strictly bounded by the STS session duration between 1 and 12 hours depending on the permission set configuration.
The core finding is unaffected. During that window there are zero account-level kill switches available on the management account. The only partial mitigation is per-resource explicit deny policies.
What Was Confirmed Empirically
Deleted user retains active STS session
Confirmed ResourceNotFoundException + valid get-caller-identity
All 7 kill switches fail on management account
Confirmed
CloudTrail logs deleted user by name on every API call
Confirmed
Refresh token exchange works after deletion
Disproved OIDC validates user existence; deletion breaks the refresh loop
Resource-based explicit deny blocks zombie session
Confirmed S3 bucket policy deny tested and works immediately
Detection CloudTrail Evidence
Empirical CloudTrail Log Deleted User Making API Calls
The following is a real CloudTrail event captured during testing. At the time of this event, aws identitystore list-users returned "Users": [] the user did not exist in Identity Center. The API call succeeded regardless.
Key forensic fields:
userIdentity.arn
...assumed-role/.../cnathanielb007
Deleted user named in every log entry
sessionContext.attributes.creationDate
2026-03-11T10:43:57Z
Token issued at login before deletion
eventTime
2026-03-11T10:59:41Z
API call made 15m after deletion
accessKeyId
ASIATJW7LYDB5KBRJ6V7
Same key across all zombie calls
responseElements
null (success)
Request was not denied fully authorized
The gap between creationDate (10:43:57Z) and eventTime (10:59:41Z) with the user deleted at approximately 10:45:00Z is the empirical proof window. CloudTrail provides the forensic anchor; Identity Center says the user doesn't exist.
Detection Queries
Run this in CloudTrail Lake or Athena:
Also query for the original AssumeRoleWithWebIdentity event to capture token issuance time:
Note: the refresh loop below applies to disabled users only not deleted users. CreateToken fails after deletion. Still worth monitoring for disabled-but-not-deleted users during IR triage:
If you see GetRoleCredentials for a user you deleted, the zombie is actively refreshing. The sourceIPAddress and userAgent fields will identify the machine.
Existing Research (What's Already Published)
Christophe Tafani-Dereeper (Datadog)
Disabling user does not invalidate access tokens
https://blog.christophetd.fr/phishing-for-aws-credentials-via-aws-sso-device-code-authentication/
Chaim Sanders
IdC access token has non-configurable 8hr lifetime, total exposure up to 20hrs
https://blog.devgenius.io/the-confusing-lifetimes-aws-iam-identity-center-access-tokens-bbd57d1eab40
Red Canary
Cached SSO tokens survive offboarding, refresh tokens valid 90 days
https://redcanary.com/blog/threat-detection/aws-sso-access-tokens/
AWS Security Blog
Recommends inline deny workaround (blocked on management account)
https://aws.amazon.com/blogs/security/how-to-revoke-federated-users-active-aws-sessions/
Aidan Steele
OIDC JWT token replay vulnerability (patched Dec 2023)
https://awsteele.com/blog/2023/12/19/an-aws-iam-identity-center-vulnerability.html
Datadog Security Labs
Attacker modified IdC MFA config and session duration for persistence
https://securitylabs.datadoghq.com/articles/tales-from-the-cloud-trenches-the-attacker-doth-persist-too-much/
What's New in This Research
All existing research documents STS persistence after disabling a user, and demonstrates fixes that work on member accounts. This research adds:
Deletion does not revoke a
ResourceNotFoundExceptionconfirmed-deleted user retains a valid active STS sessionAll mitigations fail simultaneously on the management account this specific combination is undocumented
The IR playbook is wrong every standard incident response step fails silently without telling the responder it failed
Deletion breaks refresh token exchange; disabling does not deletion is more effective than disabling for breaking token refresh, capping the zombie window at the session duration
Resource-based explicit deny is the only real-time partial mitigation confirmed via S3 bucket policy test; must be applied per resource with no account-wide equivalent
Sanders noted reserved roles are not manageable in 2022 but did not follow the implication to its conclusion this research proves what that means during an active incident
How this extends existing research
20hr window via token stacking
Refresh token theft (disabled user)
Confirmed zombie on deleted user
Member account assumed
Token theft / member account scenario
Management account no kill switch at all
Math-based finding
Attacker technique
IR failure defender did everything right
Disabled user scenario
Deletion breaks refresh loop; disabling does not
Only mitigation: per-resource explicit deny
Architectural Root Cause
AWS designed the management account as a trust anchor. To prevent customers from accidentally locking themselves out, AWS:
Exempted it from SCPs permanently
Made
AWSReservedSSO_*roles immutable
The side effect: the management account is also immune to incident response controls.
AWS's guidance says "don't put human SSO access on the management account." Their default setup wizard provisions SSO on the management account. The gap between their guidance and their defaults is where this vulnerability lives.
Threat Model Why Businesses Should Care
Who Is Affected
Any organization that:
Uses AWS IAM Identity Center (formerly AWS SSO)
Has human users assigned AdministratorAccess on the management account
Follows the AWS default setup wizard (which provisions SSO on the management account)
This is the default configuration for the majority of AWS organizations. AWS's own setup wizard creates this exposure. The customer does not have to misconfigure anything.
Threat Actors
Disgruntled employee
Knows they are being terminated. Establishes CLI session morning of last day. IT offboards them correctly. Session persists.
High
Compromised credentials
Attacker phishes SSO credentials or steals a laptop. Establishes CLI session. Defender detects and deletes the user. Session persists.
High
Insider threat
Legitimate user intentionally maintains access after offboarding by keeping CLI credentials alive.
Medium
Supply chain / contractor
Third-party contractor account is deleted after engagement ends. Session window still open.
Medium
Blast Radius: Management Account vs Member Account
The management account is not just another AWS account. It is the trust anchor for the entire organization.
Remove SCPs from all child accounts
Every guardrail in the org disappears
Access every member account via OrganizationAccountAccessRole
Full access to every account in the org production, security, billing
Disable GuardDuty org-wide
Security monitoring gone across all accounts
Disable CloudTrail org-wide
No audit trail attacker operates blind
Create IAM users/roles with no guardrails
Permanent backdoors in management account
Modify billing and account contacts
Account recovery options under attacker control
Delete SCPs protecting sensitive workloads
PCI, HIPAA, SOC2 controls removed silently
A zombie session on a member account is a single-account breach. A zombie session on the management account is an organization-wide breach.
Why the IR Playbook Failure Is the Real Risk
The most dangerous aspect is not the session persistence it is that every remediation step completes without error while doing nothing.
delete-userreturns success → user is gone, session is alivecreate-policy+attach-policyreturn success → SCP is attached, management account ignores itput-role-policyreturnsUnmodifiableEntity→ this one at least errors, but most teams don't know why
A security team that follows the documented AWS IR playbook will reach the end of their checklist believing the incident is contained. It is not. There is no system alert, no CloudTrail warning, no AWS notification that the session is still alive.
The defender is failed by the tooling they were told to trust.
Compliance and Regulatory Implications
SOC 2
CC6.1 Logical access controls; CC7.3 Incident response
ISO 27001
A.9.2.6 Removal of access rights
PCI DSS
Requirement 7 Restrict access; Requirement 12.10 Incident response plan
HIPAA
§164.312(a)(1) Access control; §164.308(a)(6) Security incident procedures
NIST CSF
PR.AC-1 Identities managed; RS.MI-1 Incidents contained
In each framework, the expectation is that deleting a user removes their access. On the AWS management account, that expectation is false.
Business Impact Scenarios
Scenario 1 Terminated employee (most likely) Employee is let go. IT follows standard offboarding IdC user deleted, access revoked. Employee had a CLI session running. They have up to 1 hour (the configured session duration max 12 hours). In that window they can exfiltrate customer data, destroy backups, or plant a backdoor. The business believes access was revoked at T+15 minutes. It wasn't.
Scenario 2 Compromised credentials during active incident Attacker gains SSO credentials via phishing. Security team detects anomalous activity, executes IR playbook, deletes the user. Attacker's session survives. Security team closes the incident. Attacker uses remaining session time to establish permanent foothold. The breach continues after the incident is marked resolved.
Scenario 3 Deliberate persistence (most dangerous) An attacker who is aware of this behavior uses it as an intentional IR evasion technique. After gaining initial access to the management account, they establish a CLI session and then deliberately allow themselves to be discovered. They may even trigger alerts to draw the security team in. The security team executes the full IR playbook disables the user, ends sessions, deletes the account, attaches the SCP. The team marks the incident contained.
The attacker was counting on this. Their STS session is still alive. They use the remaining window to create a permanent IAM backdoor an operation that takes under 60 seconds. The IdC user is gone, the investigation is closed, and the attacker has permanent unrevokable access with no active session to detect.
The deletion becomes the attacker's cover story. The IR team's own remediation actions create the false confidence that ends the investigation prematurely.
Scenario 4 Audit failure Auditor asks: "Can you demonstrate that access is revoked immediately upon user deletion?" The answer on the management account is no and there is no compensating control available to the customer. This is an audit finding with no remediation path short of architectural change.
Move all human SSO access off the management account
Eliminates the SCP exemption problem
Use a dedicated security/audit member account for org-level access
SCPs apply, role is modifiable
Set minimum session duration (1 hour or less)
Minimizes the zombie window confirmed to be the only time-based control that works
Alert on AssumeRoleWithWebIdentity for AWSReservedSSO_* roles
Detect token issuance in real time
Alert on API calls from deleted IdC users via CloudTrail
Detect zombie sessions actively
Apply explicit deny resource policies (S3, KMS, Secrets Manager) on sensitive resources
Only real-time partial mitigation confirmed to work blocks zombie at resource level
Maximize session duration awareness attacker can extend to 12 hours before offboarding
An attacker with access can run the command below to double their zombie window
An attacker extending the session duration before offboarding:
Scope clarification:
update-permission-setchanges the session duration for future sessions issued after the next portal login it does not extend the already-issued STS token currently in use. The current zombie STS token retains whatever duration was set when it was originally issued. The value of this technique is pre-offboarding: if the attacker runs this before they are removed, the next session they establish (e.g., via a second machine or after re-authentication) will have a 12-hour window. The cron attack below is relevant when the attacker has a way to re-establish sessions for a pure zombie STS token, the window is fixed at issuance. Empirical confirmation of this distinction pending.
Attacker maintain 12-hour window via cron (applies to disabled users with active refresh tokens):
The defender has no way to win this race while the zombie session is alive every reset is immediately reversed. The only way to stop it is to stop the session, which is impossible for deleted users. This turns the session duration control into a useless knob during an active incident on the management account.
Defender verify and lock session duration to minimum:
Last updated