Lesson 4 of 4 in The Bug Between Two Features
The Fix That Introduces Two Worse Bugs
Proxy the image server-side and the leak stops. Now your server fetches attacker-supplied URLs, which is a different and larger problem.
3 min read
Not yet reviewed
The fix is correct: fetch the avatar on the server, cache it, and serve it from your own domain. The visitor's browser only ever talks to the forum, and the leak is closed. This is what mature forum software does.
It also means your server now makes HTTP requests to addresses chosen by whoever set the avatar, which is a vulnerability class of its own.
One — server-side request forgery
What the attacker sets
http://169.254.169.254/latest/meta-data/iam/security-credentials/What your server does
Fetches it. From inside your network, with your
network position, and stores the response as an image.That address is the cloud metadata service, reachable only from inside the instance, and on a badly configured host it hands out credentials. The avatar proxy is a request-making machine that an anonymous user aims.
The same trick reaches anything your server can and the internet cannot: an internal admin panel on a private address, a database's HTTP interface, a service that trusts requests because they came from inside.
Two — it leaks the thing proxies exist to hide
The fetch comes from your origin server's real address. Anybody who sets an avatar pointing at a host they control now knows the IP behind your CDN — which is exactly what a CDN is there to conceal, and it turns a protected site into a directly attackable one.
Note
Both of these are live, documented problems in shipped forum software rather than hypotheticals. The pattern is worth naming: a fix that moves a capability from the client to the server moves the attack surface with it, and server-side is usually the more privileged place to be.
Fixing the fix
Resolve the hostname first, and refuse private and link-local ranges
Re-check after every redirect, not only the first URL
Fetch from a network position with no internal access
Cap the size, the time, and the content types you will store
- Line 1Refuse 10/8, 172.16/12, 192.168/16, 127/8, 169.254/16 and the IPv6 equivalents. Checking the *string* is not enough — a hostname can resolve to any of them.
- Line 2The classic bypass. A public URL that 302s to the metadata service passes a check performed only on what the user typed.
- Line 3The control that survives a mistake in the other three. If the fetcher cannot route to anything internal, an SSRF reaches nothing.
- Line 4An avatar fetcher that will download ten gigabytes is a denial of service with extra steps.
This is a lot of work for avatars. Is there not a simpler answer?
There is, and it is the honest one: do not accept remote avatars at all. Take an upload. Then there is no fetch, no proxy, and no SSRF — and you have lost a convenience that was never worth this much.
Which is why I prefer the sites that kept the feature. Every one of those bullet points is somewhere an implementation can be almost-right.
And then the harder question
With the avatar leak closed, go back to the other half. Should the recent-visitors panel exist? It is not a bug and it never was. But it publishes, to anybody, the fact that a named person read a particular page at a particular time — and this whole chapter happened because that fact was available to be joined against something else.
Take care
The honest answer is often that the feature *is* the vulnerability. A feature that publishes who-looked-at-what is a correlation surface for every other leak you have not found yet, and removing it is cheaper than defending it forever.
Your avatar proxy blocks any URL whose hostname resolves to a private address. Is it safe from SSRF?