The Fetch That Reached the Metadata Service — JavaScript Bug Hunt
Modelled on the Capital One breach (July 2019): a misconfigured proxy let an attacker make the server fetch a URL of their choosing.
- Language: JavaScript
- Layer: Backend
- Difficulty: Hard
- Concepts: Security, SSRF
- Modelled on: Capital One · 2019
- Visible tests: an allow-listed host is permitted; the metadata endpoint is refused; loopback and private ranges are refused
- Reward: 50 XP for a complete fix
Briefing
Modelled on the Capital One breach (July 2019): a misconfigured proxy let an attacker make the server fetch a URL of their choosing. They pointed it at the cloud metadata endpoint 169.254.169.254, retrieved the instance's credentials, and used them to read 100 million customer records.
fetcher.js fetches whatever URL it is given.
Fix checkUrl so internal and link-local addresses are refused.
Bug report
BUG-CAPONE · Priority: Critical (SSRF) · Reported by: security
checkUrl(url) must return { allowed, reason } for a URL of the form "http://<host>/<path>":
- reject anything whose host is not in the public allow-list — reason "blocked"
- specifically reject the metadata address 169.254.169.254, localhost, 127.0.0.1, and the private ranges 10.x and 192.168.x
- an allowed host returns { allowed: true, reason: "ok" }
Observed: every URL is fetched, including the instance metadata endpoint.
Logs
[proxy] fetched http://169.254.169.254/latest/meta-data/iam/security-credentials/
[proxy] response contained an access key and session tokenThe code as shipped
src/proxy/fetcher.js (editable)
var ALLOWED_HOSTS = ["images.example.com", "cdn.example.com", "assets.example.org"];
exports.ALLOWED_HOSTS = ALLOWED_HOSTS;
function hostOf(url) {
var withoutScheme = url.replace("http://", "").replace("https://", "");
var slash = withoutScheme.indexOf("/");
return slash === -1 ? withoutScheme : withoutScheme.substring(0, slash);
}
exports.hostOf = hostOf;
exports.checkUrl = function (url) {
return { allowed: true, reason: "ok" };
};
Read-only context: src/proxy/SSRF.js.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.