Skip to main content

API7:2023 Server-Side Request Forgery

The server fetches a URL the user controls. The attacker steers requests at internal hosts (cloud metadata services, RFC 1918 ranges) and bypasses perimeter firewalls.

What Vulkro detects​

Taint from the request body, query or path into HTTP client calls (requests.get, axios, fetch, http.Client.Get and similar) with no URL validation or allowlist check in between.

Non-compliant code​

// Express: user-supplied URL fetched directly
app.post('/webhook/probe', async (req, res) => {
const r = await fetch(req.body.url); // attacker hits 169.254.169.254
res.send(await r.text());
});

Compliant code​

// Express: allowlisted host, private IPs rejected
const ALLOWED_HOSTS = new Set(['api.partner.com']);
app.post('/webhook/probe', async (req, res) => {
const url = new URL(req.body.url);
if (!ALLOWED_HOSTS.has(url.hostname)) return res.status(400).end();
// also verify the resolved IP is not in 10/8, 172.16/12, 192.168/16, 169.254/16, 127/8
const r = await fetch(url.href, { redirect: 'error' });
res.send(await r.text());
});

References​

See also: Confidence model.


This page is generated by vulkro rules export <out-dir> from Vulkro's built-in detector catalogue. Edits made by hand are overwritten on the next regeneration.