This is an anonymized field note from a web application penetration test. The client is not identifiable. The flaw is reported as found, because the shape of it is common enough that it is worth recognizing.
The finding started with a feature nobody considered security-relevant: the ability to add a profile image by pasting a URL.
The Setup
The client operated a customer-facing web application hosted in a major cloud provider. The application had been tested before, the team was security-conscious, and the obvious injection and authentication issues had been addressed in previous rounds.
The image upload feature accepted either a file or a URL. Supplying a URL caused the server to fetch it, which is a convenience most users appreciate and a capability that hands an attacker the ability to make requests from inside the environment.
The Attack
Initial testing confirmed the server fetched arbitrary URLs. Requests to a listener under our control arrived from the application's infrastructure, which established server-side request forgery immediately.
The first attempts at the cloud metadata endpoint failed, which was encouraging: the team had thought about this. A basic blocklist rejected the standard metadata address.
Blocklists are hard to write and easy to defeat. The filter matched a literal string, and it did not account for alternate representations of the same address, nor for redirects. A URL on a domain we controlled, returning a redirect to the metadata address, was followed by the server without further validation. The filter checked the URL that was submitted, not the one that was eventually requested.
The metadata service returned instance details and, at the credentials path, a set of temporary credentials for the role attached to the instance.
What We Reached
The role attached to that web server had accumulated permissions over time, in the way instance roles usually do: each new feature needed one more grant, and no grant was ever removed.
With those credentials, operators could:
- Read several storage buckets, including one holding customer document uploads and one holding database backups.
- Enumerate the account's compute, database and networking resources, producing a complete map of an environment the client believed was internal.
- Read secrets from the parameter store, which included database credentials and a third-party API key with billing implications.
- Assume a second role intended for a data processing pipeline, which held broader read access again.
From a single URL field in an image upload, the assessment reached effective read access across the account.
Impact
The client's most sensitive data was reachable without ever touching the application's authentication. No user account was compromised, no password was cracked, and none of the controls the team had invested in were engaged, because the attack never went through the front door.
Detection produced nothing. The requests came from the application server, which is the system that legitimately talks to those services all day.
How to Break the Chain
This finding had four points at which it could have been stopped, and the client implemented all four.
- Use an allowlist, not a blocklist. The upload feature needed to fetch images from a small number of known sources. Restricting it to those closed the flaw completely. Blocklists fail against encoding, alternate address formats and redirects, and the redirect is what defeated this one.
- Validate after redirects. Resolve the destination and check the resulting IP address before connecting, and repeat that check on every redirect rather than only on the submitted URL.
- Enforce IMDSv2. Requiring a session token for metadata access defeats simple GET-based SSRF. It was available in the client's environment and was not enforced.
- Cut the instance role down. This was the change with the widest effect. The web server's role needed read access to one bucket, not to backups, secrets and a second role. Least privilege on instance roles is what determines whether an SSRF is a serious finding or a contained one.
The general lesson is that features which fetch a user-supplied URL deserve the scrutiny given to features that run user-supplied input, because in a cloud environment the server's network position is itself a privilege. For the wider pattern, see cloud misconfigurations that lead to breach.
To have your application and cloud environment tested together, get in touch.
Frequently asked questions
What is server-side request forgery?
SSRF is a flaw where an application can be induced to make an HTTP request to a destination the attacker chooses. Because the request originates from the server, it reaches places the attacker cannot reach directly, including internal services and the cloud metadata endpoint. It is dangerous precisely because the server is trusted by everything around it.
Why is the cloud metadata service such a common SSRF target?
Every major cloud provider exposes a metadata service at a fixed internal address that returns information about the instance, including temporary credentials for the role attached to it. Any process on the instance can query it, so an SSRF flaw that reaches it returns working cloud credentials. It is the highest-value destination an SSRF can reach.
What is IMDSv2 and does it fix this?
IMDSv2 requires a session token obtained through a PUT request with a specific header before metadata can be read, which defeats the simple GET-based SSRF that most flaws produce. It is a substantial improvement and should be enforced rather than merely available. It is not a complete fix, because a more capable SSRF that controls the request method and headers can still work, so it belongs alongside other controls rather than instead of them.
How do you prevent SSRF in an application?
Validate destinations against an allowlist rather than trying to block bad ones, because blocklists lose to encoding tricks, redirects and alternate address formats. Resolve the hostname and check the resulting address before connecting, then check again after any redirect. Where a feature only needs to fetch from known partners, an allowlist is straightforward and effective.
What limits the damage if SSRF succeeds anyway?
Least privilege on the instance role, principally. If the role attached to the web server can only read one storage location, credentials stolen through SSRF are worth very little. Egress filtering, network segmentation and alerting on unusual metadata access all narrow the outcome further. Defense in depth is what turns a critical finding into a contained one.
