Running untrusted code in cloud environments has always been a difficult problem. With the introduction and larger adoption of containers, it is becoming more feasible to do this in a secure way. However, I have noticed that many environments that have otherwise well-secured containers focus too heavily on local security, and fail to secure their network environment properly.
Unfortunately, many cloud providers have made it easy to exploit their default environment through the use of instance metadata APIs. These APIs have become fairly standard. Google, Amazon, and Azure all have some form of internal API. They are accessible by default, and can be difficult and counter-intuitive to disable or block.
Old Tricks, New Dogs
Attacking instance metadata APIs has been a tactic used to demonstrate and exploit same-site request forgery (SSRF) vulnerabilities for quite some time. This is by no means a novel technique, and is incredibly easy to exploit in most cases. Instance metadata APIs can provide access to anything from private buckets to kubernetes control, even if nothing else is running in that environment. These APIs also often provide information about authorized users, which could be bad for applications like honeypots, where anonymity is important.
Show me the money!
I was amazed at how many of the applications I tested for this were vulnerable to it. Almost none of the systems I tested had blocked access or properly limited the scope of these APIs. Most notably, I was able to access these APIs through GitLab’s CI, several online development environments, and many example configurations of Cowrie (a popular SSH honeypot). Exploiting instance metadata from within these environments is as simple as making a few web requests
The most effective approach for securing instance metadata (outside of blocking network access) is to limit access to the role assigned to devices running untrusted code. Here’s how to do that:
If you are unable to do this due to your use case or simply want an extra line of defense, you can also block access to 169.254.169.254 (and other reserved IP addresses?) from devices running untrusted code.
Impacted Services and Disclosure Timelines
- 06/20/18 - Reported via Hackerone: https://hackerone.com/reports/369451
- 06/28/18 - Was asked to demonstrate risk
- 06/28/18 - Demonstrated access to internal resources and sensitive info
- 01/31/19 - Bug fixed
- 02/26/19 - Awarded $3,000 bounty
- 04/12/19 - Public disclosure
- 6/25/18 - Reported via github issue
- 06/25/18 - Maintainer response
Online IDEs/Code Editor (only one of multiple vulnerable services responded)
- 6/20/18 - Reported via email contact
- 6/20/18 - Received response
- 6/25/18 - Requested update
- 6/28/18 - Received confirmation that the bug was fixed