Compromised IAM Credentials
How to respond to compromised IAM Credentials
Overview
At some point, you'll likely be dealing with compromised AWS IAM credentials. It's important to know how to appropriately respond to this while also understanding both the potential limitations of the response and ways in which threat actors can circumvent it.
The response process is going to be different depending on the type of identity that was compromised.
IAM Users
IAM Users can have a username and password for accessing the AWS console and also have access keys. Regardless of which set of credentials were compromised, the response process is the same.
Revoking the Session — Quarantine Policy (Not Recommended)
AWS offers a managed IAM Policy called AWSCompromisedKeyQuarantine
. The aim of the policy is to restrict a threat actor from escalating their privileges and maintaining access while allowing legitimate users to carry on with minimal to no impact.
Let's first discuss how this response process works and then we'll dive into the limitations, bypasses, and better response process.
After we discover IAM User credentials have been compromised, we can attach the IAM Policy AWSCompromisedKeyQuarantine
to the user. As you can see from the screenshot, this policy denies certain actions that a threat actor might take to escalate or maintain their privileges. You can view the whole policy here. Remember that a Denied permission always takes precedence over an Allowed permission.

aws iam create-access-key --user-name admin
An error occurred (AccessDenied) when calling the CreateAccessKey operation: User: arn:aws:iam::111111111111:user/bob is not authorized to perform: iam:CreateAccessKey on resource: user admin with an explicit deny in an identity-based policy
Limitations of the Quarantine Policy
Over the years this policy has been updated by AWS and now, as of the time of this writing, comes in three different versions — version1, version2, and version3. While version 2 and version 3 are the same for some reason, version 2 added more denied permissions vs the version 1 policy e.g., version 1 didn't deny S3 actions or Bedrock actions.
However, if a threat actor has legitimate access to access keys, why do you want them having any access to your resources? You shouldn't.
Revoking the Session — Deny All (Recommended)
The best approach to take would be adding the AWSDenyAll
IAM Policy to the IAM User, effectively denying all AWS permissions!
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyAll",
"Effect": "Deny",
"Action": [
"*"
],
"Resource": "*"
}
]
}
Additionally, you should deactivate and delete the compromised access keys. You can create new ones if they're still needed.
IAM Roles
Unlike IAM Users, IAM Roles do not have long-term access keys. Instead, they have short-term credentials which expire anywhere from 15 minutes to 12 hours depending on the configuration. When IAM Roles are assumed, it's called a session.
While IAM Roles can be assumed by human users, they are also commonly assumed by AWS Services like EC2 or Lambda to perform legitimate workloads. Thus attaching an IAM Policy that denies everything will very likely cause disruption, potentially taking down Production!
So what do we do here?
Revoking the Session
We can revoke the session. This will cause current sessions to be revoked and the identity (user/role/service) will need to re-authenticate to obtain valid credentials again. AWS Services will automatically re-authenticate (applications that leverage a role should be programmed to do this too) but human users will need to re-authenticate themselves. So, there shouldn't be any impact to workloads but there will be some minor annoyance to users.
We can revoke the session by either updating the role's IAM Policy with this Condition,
"Condition": {
"DateLessThan": {"aws:TokenIssueTime": "2025-08-24T02:00:00Z"}
}
or we can simply attach an additional IAM Policy to the role,
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"DateLessThan": {"aws:TokenIssueTime": "2025-08-24T02:00:00Z"}
}
}
}
Either approach will work fine! All we're doing here is saying that if the token (the session credentials) is older than this date/time (make sure this is a date/time after you discovered the compromised credentials) then no AWS actions can be performed.
And now identities will need to re-authenticate to get new credentials.
This approach assumes the threat actor doesn't have the ability to assume the role (re-authenticate) and get new credentials. If they do, then this approach will not work!
It's important to understand how the threat actor obtained the credentials in the first place!
Identity Center (SSO) Users
Identity Center Users are a bit more complex to revoke credentials for.
Revoking the Session
AWS recommends the following actions,
Find the user id
# get the identity store id
aws sso-admin list-instances --region <where-identity-center-is-setup>
{
"Instances": [
{
"InstanceArn": "arn:aws:sso:::instance/ssoins-74542342df6jfdfdf",
"IdentityStoreId": "d-90664837e4",
"OwnerAccountId": "111111111111",
"CreatedDate": "2025-08-24T16:32:49.311000-06:00",
"Status": "ACTIVE"
}
]
}
# get the user id
aws --region <where-identity-center-is-setup> identitystore list-users --identity-store-id d-90664837e4 | jq -r '.Users[] | select(.UserName == "tyler") | .UserId'
81r8b4f8-e0d1-54lb-90c6-d08b7398d66a2
Add an SCP denying all actions for the Identity Center User and keep this in place for as long as as your session duration is configured for Identity Center authentication (between 1 hour to 90 days). Otherwise, the threat actor will have regained their access
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"*"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"identitystore:userId": [
"81r8b4f8-e0d1-54lb-90c6-d08b7398d66a2"
]
}
}
}
]
}
Remove all permission set assignments from the Identity Center User — including those the threat actor is not using because if they still have access to the AWS session, they can use other roles

(If using an Identity Provider like Okta, Active Directory or something else) you must disable the user in the identity source or else the threat actor may establish another AWS session
Delete the active session in Identity Center for the compromised user

Disable the user in Identity Center

After the SCP has remained in place for the length of the Identity Center authentication configuration,
Remove the user from the SCP
Update the user's credentials (if those were compromised)
Restore their AWS account/permission set assignments
Additional Considerations
You may be tempted to simply remove the IAM Permissions from the compromised identity. While this would effectively stop the threat actor from doing anything with the credentials, the credentials are still active. If permissions are later re-applied, the threat actor would now have permissions again — assuming the credentials are still active.
After a threat actor obtains legitimate IAM access keys, they may perform the call
aws sts get-federation-token
. This enables the threat actor to obfuscate their actions further e.g.,
aws sts get-federation-token --name sally --policy-arns arn=arn:aws:iam::aws:policy/AdministratorAccess --duration-seconds 129,600
In this case, the threat actor now gains temporary credentials (valid from 15 min - 36 hours). The important things to know here:
The
name
can be anything — this is simply what shows up in the logs, it doesn't need to be a real identityAt least one (up to 10) managed or inline policy needs to be passed or else the session credentials will have no permissions
The ultimate permissions of this session is the intersection of the user (who runs this command) and the permission policies passed in the command. So, if the administrator policy is used but the user running the command can only list S3 buckets, then the session credentials can only list S3 buckets
If the user's permissions are later updated e.g., now they can create IAM users, then the session credentials can now create IAM users — you do not need to re-generate credentials!
Additionally, if you apply the quarantine or deny all policy, this federated user will also be denied those actions — again because "the ultimate permissions of this session is the intersection of the user and the permission policies passed in the command"
Last updated
Was this helpful?