C

Web › Module 4 › Lesson 5

BeginnerModule 4Lesson 5/6

Lab — SSRF Lab

Build a tiny URL fetcher locally, demonstrate SSRF to localhost, then add defenses—ethical lab only

25 min+46 XP2 quiz
Module progress5 of 6

Opening

Fetch a URL—then fetch trouble

You will run a minimal vulnerable web app on your machine, trigger SSRF against a local secret endpoint, and then patch the allowlist. Use 127.0.0.1 only—never aim SSRF payloads at third-party sites or cloud metadata you do not own.

1. Step 1 — Vulnerable fetch app

ssrf_lab.py — save and run locallyfrom flask import Flask, request import requests app = Flask(__name__) SECRET = "cyberlium-local-secret" @app.get("/secret") def secret(): return SECRET @app.get("/fetch") def fetch(): url = request.args.get("url", "") r = requests.get(url, timeout=3) return r.text[:500] if __name__ == "__main__": app.run(port=5050)

from flask import Flask, request
import requests

app = Flask(__name__)
SECRET = "cyberlium-local-secret"

@app.get("/secret")
def secret():
    return SECRET

@app.get("/fetch")
def fetch():
    url = request.args.get("url", "")
    r = requests.get(url, timeout=3)
    return r.text[:500]

if __name__ == "__main__":
    app.run(port=5050)

2. Step 2 — Trigger SSRF

Request internal secret via fetch (same machine)curl "http://127.0.0.1:5050/fetch?url=http://127.0.0.1:5050/secret"

curl "http://127.0.0.1:5050/fetch?url=http://127.0.0.1:5050/secret"

You should see the secret string in the response—proving the server accessed an internal URL you chose. Note how the browser never talked to /secret directly; the server did.

3. Step 3 — Add a basic allowlist

Patch idea — block loopback and private rangesfrom urllib.parse import urlparse import ipaddress, socket def safe_host(url): host = urlparse(url).hostname ip = ipaddress.ip_address(socket.gethostbyname(host)) if ip.is_private or ip.is_loopback: raise ValueError("blocked") return url

from urllib.parse import urlparse
import ipaddress, socket

def safe_host(url):
    host = urlparse(url).hostname
    ip = ipaddress.ip_address(socket.gethostbyname(host))
    if ip.is_private or ip.is_loopback:
        raise ValueError("blocked")
    return url

Complete SSRF lab

Run ssrf_lab.py, retrieve /secret through /fetch, then implement at least one defense (allowlist or private IP block) and confirm the bypass no longer works.

Knowledge Check

1

In this lab, SSRF succeeded because:

Multiple choice

Knowledge Check

2

True or False: Blocking private and loopback IPs in outbound fetchers is a valid SSRF mitigation.

True or False

← Previous

Answer all 2 knowledge checks to continue. (0/2 answered)