Compromised cloud credentials give an attacker the same API access as the workload or administrator they belong to, and deactivating a key is only the first of several steps, because sessions, tokens and backdoor credentials created with it keep working. This cloud credential compromise playbook is a step-by-step cloud credential incident response procedure for the three credential types most often leaked or stolen: AWS IAM user access keys and the role sessions derived from them, Microsoft Entra service principal secrets and certificates, and Google Cloud service account keys. It covers activation, containment, scoping with CloudTrail, Entra sign-in and audit logs and Cloud Audit Logs, eradication, recovery and lessons learned, with [Organisation] placeholders so it can be adopted as written. It is for cloud security, incident response and platform teams. For the wider picture of logging, forensics and provider engagement, see the Cloud Incident Response Guide.
How to use this template
- Replace text in square brackets, such as [Organisation], [Cloud security on-call] and [15 minutes], with your own teams, tools and targets. Bracketed timings are suggestions.
- Steps are numbered in the order to perform them. "Must" steps are not skipped without the incident lead's recorded decision.
- Pre-fill section 2 and the pre-requisites in section 1 before you need them. A playbook whose contacts and roles are blank on the day is not usable.
- Run the AWS, Azure and Google Cloud subsections that apply; a single incident often touches more than one, because leaked files tend to contain several credentials.
- For the leaked access key response outside your accounts (a secret in a public repository or package), also follow the triage and rotation steps in the Leaked Credential Response Playbook; this page covers what happens inside the cloud account.
1. Purpose, activation and pre-requisites
This playbook is activated when any of the following indicates that a cloud credential belonging to [Organisation] may be in unauthorised hands:
- An AWS Support case or notification that a key is exposed, or the AWS managed policy AWSCompromisedKeyQuarantineV3 appearing on an IAM user (some AWS guidance still names the earlier AWSCompromisedKeyQuarantineV2).
- A threat detection finding on a credential, for example GuardDuty
UnauthorizedAccess:IAMUser/ConsoleLoginSuccess.B,Recon:IAMUser/TorIPCaller,Stealth:IAMUser/CloudTrailLoggingDisabledor anAnomalousBehaviorfinding; a Microsoft Entra ID Protection risk detection on a workload identity; or a Security Command Center finding. - A Google Cloud service account key disabled with
SERVICE_ACCOUNT_KEY_DISABLE_REASON_EXPOSEDby the Service Account Key Exposure Response constraint. - A cloud credential leak reported by secret scanning or a third party, an unexplained billing spike, or resources launched in Regions [Organisation] does not use.
Pre-requisites, checked [quarterly]: incident response roles exist in every AWS account, Azure subscription and Google Cloud project; responders can reach them without the identity provider under investigation; CloudTrail, Entra and Cloud Audit Logs are exported to [log archive] outside the workload accounts; and every non-human credential in the inventory has an owner. See the NHI Ownership Guide.
2. Roles and contacts
| Role | Responsibility | Contact |
|---|---|---|
| Incident lead | Declares the incident, owns decisions on disruptive containment and the timeline | [Cloud security on-call] |
| Cloud platform engineer | Runs containment and log queries in each provider | [Platform on-call] |
| Credential owner | Knows what depends on the credential; rotates and restores service | [From NHI inventory] |
| Identity team | Entra, IAM Identity Center and federation changes | [Identity on-call] |
| Legal and privacy | Notification decisions if data was accessed | [Contact] |
| Provider support | AWS Support case (Account and Billing, category Security); Microsoft support or incident response retainer; Google Cloud Customer Care | [Support plan and case links] |
3. Triage: identify the credential
Complete these steps within [15 minutes] of activation.
- Record the credential identifier exactly: AWS access key ID (long-term IAM user keys begin AKIA, temporary session keys begin ASIA), Entra application (client) ID and credential key ID, or Google Cloud service account email and key ID.
- Resolve it to an identity and owner: the IAM user or role, the app registration and its service principal, or the service account and project. If there is no owner on record, the cloud platform team acts as owner for containment.
- Size the blast radius from permissions, not from what has been seen so far: attached and inline policies, Azure role assignments and Graph application permissions, Google Cloud IAM bindings at project, folder and organisation level. Note whether the identity can create other credentials (
iam:CreateAccessKey,iam:CreateUser, application owner rights, Service Account Key Admin or Service Account Token Creator). - Set severity: [Critical] if the credential is administrative, can create identities, or was exposed publicly; [High] if it reaches production data; [Medium] otherwise.
- Tell the credential owner that containment will break dependent workloads, and agree the order; do not wait for agreement on a Critical incident.
4. Containment: compromised AWS access keys and role sessions
Contain an AWS access key compromise in this order, even if the compromised access key appears to have low privileges: attackers use one key to create others.
- Deactivate the key: set the IAM user access key to Inactive (UpdateAccessKey). Do not delete it yet: an inactive key can be re-enabled if containment breaks a critical service, and its ID stays visible for the investigation. AWS's own guidance for rotation is "Don't delete the original access key during this step."
- Block the IAM user: attach an explicit deny-all inline policy to the user and remove its console password. If AWS has attached AWSCompromisedKeyQuarantineV3, leave it in place: its description says "Do NOT remove this policy. Instead, please follow the instructions specified in the support case created for you regarding this event." It is not a blanket deny; it blocks a list of actions attackers use for fraud and persistence, such as
iam:CreateAccessKey,iam:CreateUser,iam:PassRole,ec2:RunInstances,lambda:CreateFunction,bedrock:InvokeModel,s3:DeleteBucketandsts:GetSessionToken, which is why your own deny is still needed. - Kill sessions derived from the key: an attacker may already have used the key to obtain temporary credentials with GetSessionToken or GetFederationToken, and those can stay valid until they expire. Because they draw on the user's permissions, the deny-all in step 2 blocks them. If the user must keep working, use a deny with the condition
aws:TokenIssueTimeearlier than the containment time instead; AWS notes this condition is only present on requests signed with temporary credentials, so it never replaces step 1. - Revoke AWS sessions on roles the key could assume: use Revoke active sessions on each role in scope. IAM attaches an inline policy named AWSRevokeOlderSessions that denies everything to sessions issued before about 30 seconds after you act. It affects every user of the role, cannot be used on service-linked roles, and needs
iam:PutRolePolicy. Roles created from IAM Identity Center permission sets must be revoked in IAM Identity Center instead. - Apply an organisation guardrail if the scope is unclear: a service control policy denying the suspect principal, or all actions in Regions [Organisation] does not use, stops activity in every account at once. SCPs do not apply to the management account, so contain there directly.
- Open the AWS Support case with the IAM user or role ARNs, the timeline and the business impact, and record the case number.
With compromised AWS access keys, speed decides the cost of cloud credential compromise. In the Codefinger S3 ransomware stolen keys were used to encrypt buckets with AWS's own encryption, and in the AWS crypto-mining campaign miners ran within minutes of compromised IAM credentials being used.
5. Containment: compromised service principal credentials in Microsoft Entra ID
- Disable the service principal by setting
accountEnabledto false (in the portal, "Enabled for users to sign in" set to No). Microsoft's compromised application playbook recommends disabling first "to give your incident response team or the affected business unit time to evaluate the impact of deletion or key rolling". Do not delete the application during the incident. - Coordinate with any admin compromise: if administrator credentials may also be compromised, Microsoft advises coordinating this "with an eviction event to ensure that all routes to accessing the tenant are cut off simultaneously". Plan the cut so that the attacker loses every path at the same time.
- Replace and remove credentials: list all
passwordCredentialsandkeyCredentialson the application object and on every service principal of the app, record their key IDs, add a new certificate if the workload must keep running, then remove every old secret and key from both objects (removePassword and removeKey). - Block risky workload identities: a Conditional Access policy for workload identities can block service principals that Identity Protection marks as risky; Microsoft notes enforcement is limited to single-tenant applications.
- Rotate secrets the service principal could read, in Microsoft's priority order: Key Vault secrets it read directly, then the rest of the secrets in those vaults, then secrets across exposed subscriptions.
- Alert on re-enablement: monitor the audit log for "Update service principal" with the modified property "account enabled" set to true.
Hijacked app identities are a known route to compute abuse: see the Storm-1283 OAuth apps abuse, and for the design side the Azure RBAC and Service Principals Guide.
6. Containment: compromised GCP service account key
- Disable the key, then delete it once scoping in section 7 has recorded its ID and activity. Google's sequence for rotation is to deploy a replacement, "Disable the old key to verify that the new key works as expected," then delete it. If a key was committed to a repository, Google says "you must delete the key in IAM as quickly as possible".
- Cut active tokens: Google states that "Service account access tokens are bearer tokens and remain valid until their expiration time" and cannot be revoked directly. Disable the service account or apply an IAM deny policy on it, and "wait at least 60 minutes after disabling the service account so that the compromised token can expire". If the organisation allows extended token lifetimes (
constraints/iam.allowServiceAccountCredentialLifetimeExtension), wait for that lifetime instead. - Remove impersonation paths: list who holds Service Account Token Creator or Service Account User on the account and revoke grants that are not needed; the attacker may have added one.
- Federated workloads: if the compromised credential was an external identity used through workload identity federation, disable the pool provider (or the pool) to stop new token exchanges, and apply a temporary deny policy to block tokens already issued.
- Human gcloud credentials: if a user's gcloud or Application Default Credentials were stolen, revoke the refresh token; Google notes that suspending the user or resetting the password does not "invalidate compromised access tokens that an attacker already controls".
Applying a deny policy at organisation level needs the Deny Admin role; grant it to the incident response role in advance. See the Google Cloud IAM and Service Accounts Guide.
7. Investigation and scoping
Search from the earliest possible exposure date, not the alert time, and across every Region, subscription and project the identity could reach. The question is not only what the credential did, but what new credentials, identities and resources it created.
| Question | AWS (CloudTrail) | Azure and Entra ID | Google Cloud (Cloud Audit Logs) |
|---|---|---|---|
| Which calls used this credential? | Look up events by access key ID; check userIdentity.type (IAMUser, AssumedRole, FederatedUser), sourceIPAddress and userAgent | Service principal sign-ins: location, failures, timestamps, frequency and the Resource accessed | Filter on the principal email; the serviceAccountKeyName field, which many services add to audit records, identifies the key |
| Which sessions came from it? | sessionContext.sessionIssuer and sourceIdentity link role sessions to the original identity | Microsoft Graph and Azure Resource Manager activity by the app ID | serviceAccountDelegationInfo shows impersonation chains |
| New credentials and identities? | CreateAccessKey, CreateUser, CreateLoginProfile, UpdateLoginProfile, CreateRole, UpdateAssumeRolePolicy, CreateSAMLProvider, CreateOpenIDConnectProvider | Audit log, category Application Management: "Update application" for Certificates and secrets management; "Add app role assignment to service principal"; "Consent to application"; redirect URI changes | New service account keys, new user accounts, new IAM bindings, project-level SSH keys |
| Privilege changes? | AttachUserPolicy, AttachRolePolicy, PutUserPolicy, CreatePolicyVersion | Azure role assignments; Entra role assignments | SetIamPolicy at project, folder or organisation |
| Defence impairment? | StopLogging, DeleteTrail, DeleteDetector, StopConfigurationRecorder, DeleteAnalyzer | Diagnostic setting deletions; Conditional Access changes | Log sink and audit configuration changes |
| Data and resource abuse? | RunInstances in any Region, CreateFunction, InvokeModel, PutBucketPolicy, DeleteBucketPublicAccessBlock, ScheduleKeyDeletion | VM and GPU deployments, storage key listing, Key Vault reads | New VMs, buckets and service accounts |
- Empty fields: CloudTrail notes
accessKeyId"might not be present, or might be displayed as an empty string", so pivot on the user or role ARN and source IP as well. - Billing as evidence: cost and usage data shows Regions and services you would not think to search. Model invocations are a common target; see the LLMjacking campaign.
- Key testing at scale: attackers validate stolen keys with cheap identity calls before acting; the TruffleNet campaign did this across hundreds of hosts, so a burst of failed or low-value calls from new IPs is worth an alert on its own.
- Preserve: export the relevant log records to write-once storage in [forensics account] before retention windows close. Logging prerequisites and retention defaults are in the Cloud Logging and Audit Trail Guide.
8. Eradication
- Delete or deactivate every credential and identity created by the attacker found in section 7: access keys, IAM users, login profiles, roles and trust policy changes, identity providers, service principal secrets and certificates, app role assignments and consents, service account keys and IAM bindings.
- Remove attacker resources in all Regions and projects, including stopped instances, images, snapshots, functions and layers. Snapshot anything needed as evidence first.
- Rotate every secret the identity could read: Secrets Manager and Parameter Store values, Key Vault secrets, Secret Manager secrets, and credentials stored in instance user data or environment variables.
- Replace the compromised credential type rather than re-issuing it: roles for AWS workloads, managed identities or workload identity federation for Azure, attached service accounts or workload identity federation for Google Cloud. See the Cloud Workload Identity Guide.
- Delete the deactivated original key only when the credential owner confirms nothing legitimate still depends on it and the investigation has recorded its activity.
9. Recovery
- Restore damaged data from the last known clean state: EBS and RDS snapshots, S3 object versions, managed disk snapshots, Cloud Storage object versions.
- Bring dependent workloads back on the new credentials and watch for authentication failures from anything missed for [72 hours].
- Re-enable logging and detection that was impaired, and confirm with a test event.
- Verify account contacts, root user email and MFA (AWS recommends multiple MFA devices for the root user), and Entra and Google Cloud super administrator recovery settings.
- Respond to the AWS Support case; remove AWSCompromisedKeyQuarantineV3 only as the case instructs.
- Keep the containment deny policies and enhanced alerting on the affected identities for [30 days].
10. Lessons learned
- Timeline: record exposure, first malicious use, detection, containment, eradication and recovery times. NIST SP 800-61 Rev. 3 treats lessons learned as continuous improvement across the CSF 2.0 Functions, not a one-off report.
- Root cause: where the credential leaked (code, CI logs, an endpoint, a supplier), why it was long-lived, and why it had the permissions it did. The Sumo Logic breach is a reminder that one compromised AWS credential can force a customer-wide rotation.
- Prevention actions: block new long-lived keys where policy allows (SCPs denying
iam:CreateAccessKey, Google Cloud's "Disable service account key creation" constraint, which organisations created on or after 3 May 2024 enforce by default), set Service Account Key Exposure Response toDISABLE_KEY, and add the detections that would have caught this sooner. - Playbook update: amend this document with anything that slowed the team down, and re-test it.
11. Framework mapping
| Playbook stage | ATT&CK v20 techniques addressed | NIST CSF 2.0 |
|---|---|---|
| Triage and investigation (3, 7) | T1078.004 Valid Accounts: Cloud Accounts; T1552.001 Credentials In Files; T1552.005 Cloud Instance Metadata API | RS.MA Incident Management; RS.AN Incident Analysis |
| Containment (4 to 6) | T1078.004 | RS.MI Incident Mitigation |
| Eradication of persistence (8) | T1098.001 Additional Cloud Credentials; T1098.003 Additional Cloud Roles | RS.MI Incident Mitigation |
| Resource abuse (7, 8) | T1496.001 Compute Hijacking; T1496.004 Cloud Service Hijacking | RS.AN Incident Analysis |
| Defence impairment checks (7) | T1685 Disable or Modify Tools | DE.CM Continuous Monitoring |
| Recovery and lessons (9, 10) | None | RC.RP Incident Recovery Plan Execution; ID.IM Improvement |
In NIST SP 800-53 Rev. 5 terms, the playbook is an IR-8 incident response plan component, exercised under IR-3 and executed under IR-4 Incident Handling, with IA-5 Authenticator Management covering the credential replacement.
Implementation guidance
- Pre-build the access: create the incident response roles, the deny policies and SCP templates, and grant Deny Admin and PIM-eligible Entra roles before an incident. Test that responders can assume them from a clean device.
- Script the first ten minutes: key deactivation, user deny policy, role session revocation, service principal disable and service account disable should each be one reviewed script or automation, with dry-run output.
- Exercise with a canary: create a credential in a sandbox account, subscription and project with no permissions, "leak" it internally, and time detection to containment. Rollback is simply re-enabling the canary.
- Agree disruption rules: decide in advance which production credentials the incident lead may disable without the owner, and record that decision in this template.
- Feed the inventory: every incident should update the credential's owner, purpose and replacement plan in the NHI inventory.
A small organisation with one account per cloud can run this playbook manually if the roles in section 2 are named and the containment steps have been rehearsed once. Large estates need organisation-level guardrails, automation and a central log archive, because the attacker will spread across accounts faster than people can click. Common failure patterns: deleting the key immediately and losing the trail; deactivating the key but leaving role sessions and GetSessionToken credentials alive; disabling a service principal while the attacker's added certificate remains; forgetting that Google Cloud access tokens outlive key deletion; searching only the home Region; and re-issuing the same long-lived credential type. Track these measures:
- Time to contain: detection to credential disabled and sessions revoked (target [under 1 hour] for Critical).
- Exposure to detection: time from first exposure to first alert.
- Persistence found: attacker-created credentials or identities per incident, and how many were found after recovery.
- Long-lived credential count: IAM user access keys, service principal secrets and service account keys outstanding, trending down.
- Exercise currency: days since each provider's section was last tested.
Standards and references
- NIST: SP 800-61 Rev. 3, Incident Response Recommendations and Considerations for Cybersecurity Risk Management
- AWS: AWSCompromisedKeyQuarantineV3 managed policy reference
- AWS: Revoke IAM role temporary security credentials
- AWS re:Post: What do I do if I notice unauthorized activity in my AWS account?
- AWS Samples: Customer Playbook Framework, Compromised IAM Credentials
- Microsoft Learn: Compromised and malicious applications investigation
- Google Cloud: Respond to compromised Google Cloud credentials
- MITRE ATT&CK: T1078.004 Valid Accounts: Cloud Accounts
This template is provided for guidance and must be adapted to your organisation. Related NHI Mgmt Group resources: Cloud Incident Response Guide · Leaked Credential Response Playbook · Identity Incident Response Playbook · AWS Security Guide · Secrets Management Guide