Asterrr's Handbook

Compromised credentials

Responding to exposed access keys, stolen role and instance credentials, compromised Identity Center users and root credentials, tracing activity in CloudTrail, and handling AWS abuse reports.

Exam tasks: 2.2.2 (search and correlate logs across services), 2.2.3 (validate findings to assess scope), 2.2.4 (contain, eradicate and recover), 2.2.5 (root cause)

The decision: which kind of credential leaked (long-term key, role session, instance credentials, federated user, root), what is the fastest control that invalidates that credential without breaking everything else, and what did the attacker create while they had it?

Pick the containment for the credential type

CredentialLooks likeFastest invalidationWatch out for
IAM user access keyAKIA...UpdateAccessKey to InactiveTemporary credentials the attacker minted with GetSessionToken or GetFederationToken keep working until you deny the user
Role sessionASIA...Revoke active sessions on the roleLegitimate callers must re-assume the role
EC2 instance profile credentialsASIA..., session name is the instance IDRevoke sessions on the roleLegitimate instances fail until IMDS hands them fresh credentials
Identity Center userRole named AWSReservedSSO_...Disable the user, remove assignments, revoke sessions in Identity CenterYou can't edit those roles in IAM
Rootarn:aws:iam::111122223333:rootReset password, replace MFA, delete root keysAlso check the account email and contact details weren't changed

Where the alert comes from

  • GuardDuty findings such as UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS (instance credentials used from outside AWS), .InsideAWS (used from another AWS account), anomalous API behaviour findings, and attack sequence findings such as AttackSequence:IAM/CompromisedCredentials, which chain several signals into one critical finding.
  • AWS Health event AWS_RISK_CREDENTIALS_EXPOSED when AWS finds your key in a public place, such as a public code repository. AWS also opens a support case and may attach the AWSCompromisedKeyQuarantineV3 managed policy to the user.
  • Trusted Advisor has an Exposed Access Keys check that surfaces the same kind of event.
  • An abuse report from AWS (see below).

Removing the quarantine policy

AWSCompromisedKeyQuarantineV3 denies actions that attackers typically abuse (launching instances, creating users and keys, changing policies, invoking Bedrock models, deleting S3 objects). Detaching it to "get the app working again" is wrong. Rotate the key, clean up, and follow the instructions in the support case AWS opened for you.

Exposed IAM user access keys

  1. Deactivate the exposed key. Don't delete it yet: an inactive key can be re-enabled if you picked the wrong one, and its ID stays useful for searching logs.
  2. Attach an inline deny-all policy to the user. Temporary credentials minted from that user are evaluated against the user's own policies, so this also shuts down GetSessionToken and GetFederationToken sessions the attacker created. The AWS managed policy AWSDenyAll does this.
  3. Create a replacement key, update the application (better: move it to a role and delete keys entirely), then delete the old key.
  4. Hunt for persistence (next section), and review the IAM credential report and last accessed data for the user.
  5. Review charges and Regions you don't use. Attackers like launching expensive instances in forgotten Regions.

Detaching policies instead of denying

Removing a principal's permission policies isn't enough: a bucket policy, key policy or queue policy that names the principal still grants access. An explicit deny in the identity policy beats any allow, including allows in resource-based policies.

Exam signal

"The key was pushed to a public repository and must stop working immediately, with the least impact" means deactivate that key, not delete the user, not rotate every key in the account. "The attacker also used the key to get temporary credentials" adds deny all on the IAM user.

Stolen role and instance credentials

  • Revoke active sessions in the IAM console attaches an inline policy named AWSRevokeOlderSessions to the role. It denies everything when aws:TokenIssueTime is earlier than the revoke time (plus about 30 seconds for propagation).
  • Anyone who assumes the role afterwards is unaffected. If the attacker can still assume the role (for example because they hold a user key that is allowed to), fix that path too.
  • You need iam:PutRolePolicy on the role to do it. Service-linked roles can't be revoked this way.
  • For EC2 instance credentials used from outside the instance:
    • Revoke sessions on the instance role. Healthy instances pick up new credentials from IMDS on their next refresh.
    • Treat the instance as compromised: the credentials came from somewhere. Isolate it (see Compromised workloads).
    • Prevent a repeat with IMDSv2 required and policies that use aws:EC2InstanceSourceVPC and aws:EC2InstanceSourcePrivateIPv4 so instance credentials only work from where they were issued.

Deleting the role

Deleting and recreating a role changes its unique ID and breaks every trust policy, resource policy and key policy that referenced it. Revoking sessions invalidates the stolen credentials without that collateral damage.

Identity Center and federated users

  • Roles created from permission sets (AWSReservedSSO_...) can't be edited in IAM, so the IAM Revoke sessions button isn't available for them.
  • Disable or delete the user in the identity source (the external IdP, or the Identity Center directory), remove their account assignments, and revoke active sessions in Identity Center. Existing role sessions end when their session duration expires, so keep permission set session durations short.
  • For SAML or OIDC federation straight into IAM roles, disable the user at the IdP and revoke sessions on the roles.

Root credential compromise

  • Standalone account: sign in with the root recovery flow, reset the password, replace the MFA device, delete any root access keys, confirm the account email and alternate contacts, then contact AWS Support.
  • Member accounts in Organizations: turn on centralized root access. The management account or a delegated admin can then delete a member account's root credentials entirely and perform the few root-only tasks through short-lived privileged sessions (sts:AssumeRoot), such as unlocking an S3 bucket policy that denies everyone.
  • SCPs apply to the root user of member accounts, so a deny-by-default SCP limits what a stolen member root credential can do. They never apply to the management account.

Exam signal

"Ensure no one can sign in as root in the 200 member accounts, with the least operational effort" is centralized root access with root credentials deleted, not a password vault with 200 MFA tokens.

Tracing what the attacker did

Search by the credential, then follow every credential it created.

ToolBest forLimits
CloudTrail Event historyQuick look-up by access key ID, user name or event name in one account and Region90 days, management events only
CloudTrail LakeSQL across accounts and Regions, including data eventsOnly what you sent to the event data store
Athena over the org trail in S3Cheap SQL over years of logsYou manage the table and partitions
DetectiveVisual timeline of a user or role, new geolocations, API volume, related findingsNeeds Detective enabled before the incident
  • Filter on userIdentity.accessKeyId, then pivot on sourceIPAddress and userAgent to find other credentials used from the same place.
  • When the key called AssumeRole, the responseElements hold the new session's access key ID. Search for that too, or you'll miss everything done in other accounts.
  • Look for persistence: CreateUser, CreateAccessKey, CreateLoginProfile, UpdateAssumeRolePolicy, AttachRolePolicy, new SAML or OIDC providers, CreateFunction, RunInstances in unusual Regions, PutBucketPolicy, ScheduleKeyDeletion, and StopLogging or DeleteTrail.
  • errorCode: AccessDenied bursts are the attacker enumerating permissions. They tell you what they tried as well as what they got.

More log-query technique lives in Log analysis.

AWS abuse reports

  • AWS Trust and Safety emails the account's contacts when your resources are reported for spam, port scanning, DoS, intrusion attempts, malware distribution or hosting prohibited content.
  • An abuse report is often the first sign of compromise: a leaked key used to launch scanning instances, or a vulnerable server turned into a spam relay.
  • Reply to the report with what you found and did. If you don't respond, AWS may restrict or suspend the offending resources.
  • To report abuse coming from AWS resources you don't own, use the AWS abuse reporting form.
  • Keep the security alternate contact current on every account (you can set it centrally through Organizations) so these notices reach the security team.
90 days
CloudTrail Event history retention (management events).
~30 seconds
Future buffer AWSRevokeOlderSessions adds past the revoke time for propagation.
AKIA / ASIA
Prefixes of long-term user keys and temporary STS keys.
AWS_RISK_CREDENTIALS_EXPOSED
AWS Health event for keys found in public.

Scenarios

Scenario
A developer at Quillmark Analytics accidentally committed an IAM user access key to a public repository. Within minutes, CloudTrail shows the key calling sts:GetFederationToken from an unfamiliar IP address. The security engineer deactivates the access key, but the unfamiliar IP address continues making successful API calls. What should the engineer do next to stop this activity?
Scenario
GuardDuty raises UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS for the role attached to a fleet of 40 web servers behind an ALB. The company must stop the stolen credentials from working immediately while keeping the website online. What is the best first action?
Scenario
Brightwell Retail has 150 member accounts in AWS Organizations. An audit found that 12 member accounts still have root access keys and nobody knows who holds the root passwords. The CISO wants root sign-in to be impossible in member accounts while keeping the ability to perform the rare root-only task. Which approach meets this with the least operational overhead?

Further reading

On this page