Lion Cipher Lab
Build an SSRF-safe URL fetcher that survives the bypass zoo (from scratch)
- AppSec / DevSecOps
- Advanced
- ~90 min
- Free · no account required
Why it matters
Server-Side Request Forgery (SSRF) is the bug behind some of the largest cloud breaches, and it hides in the most innocent-looking feature: anything that 'fetches a URL for the user' — a link-preview generator, a webhook, an image proxy, a PDF renderer, an import-from-URL button. That feature quietly hands an attacker your server's network position, letting them reach internal admin panels, databases, and — the crown jewel — the cloud metadata endpoint (169.254.169.254) that on many instances hands out temporary IAM credentials to anything that asks. The Capital One 2019 breach was exactly…
What you'll learn
- explaining SSRF (Server-Side Request Forgery): a feature that fetches an attacker-chosen URL, turning your server into the attacker's proxy into internal networks and cloud metadata
- standing up a disposable local lab: an internal 'secret' service and a LOCAL stand-in for the cloud metadata endpoint (a fake 169.254.169.254), both on 127.0.0.1
- writing a deliberately naive URL fetcher and watching it leak internal secrets and fake metadata credentials
- walking the full bypass zoo: direct loopback/localhost, alternate IP encodings (decimal 2130706433, hex 0x7f000001, octal, 127.1, 0.0.0.0, IPv4-mapped IPv6), DNS rebinding, redirect-to-internal, userinfo tricks, and dangerous schemes (file://, gopher://)
- building the defense layer by layer: scheme allowlist, reject credentials in the URL, resolve-then-pin, a private/reserved/link-local IP denylist, redirect re-validation, and an egress allowlist
- the crux move: validate at CONNECT, not at parse — resolve the host yourself, validate EVERY resolved address, and connect to the PINNED IP so the name cannot rebind between check and use
- why canonicalizing alternate IP encodings (inet_aton decodes 2130706433 -> 127.0.0.1) matters, and why a WAF/regex on the URL string is not sufficient
- the judgment call: allowlist-not-denylist, and the production do-it-better — a dedicated egress proxy, network segmentation, and cloud IMDSv2
Steps in this lab
- What SSRF is, and the sink you are about to build a safe version of
- Stand up the lab: an internal secret, a fake metadata endpoint, and a naive fetcher
- The bypass zoo: every way one internal address hides
- Layer 1 — scheme allowlist and reject credentials in the URL
- Layer 2 — resolve-then-pin: validate every resolved IP, then connect to the PINNED one
- Layer 3 — re-validate every redirect hop (never trust the Location header)
- The hardest bypass: DNS rebinding / TOCTOU, and why validate-at-connect wins
- Layer 4 + scoreboard: egress allowlist, then fire the whole zoo at both fetchers
- The judgment: allowlist-not-denylist, validate-at-connect, and the production do-it-better