Server-Side Request Forgery (SSRF)

Turning your application into a proxy to attack the internal network.

The idea

Many applications need to fetch data from external URLs provided by users (e.g., fetching a profile picture, rendering a webpage preview, or downloading a webhook payload). If the application doesn't validate the URL, an attacker can provide a URL pointing to the server's own internal network (like `localhost` or `169.254.169.254`).

Because the request originates from the server itself, it easily bypasses external firewalls and can access internal databases, admin panels, or cloud metadata endpoints.

Step 1: Normal usage. The user asks the server to fetch an image from Imgur.

How it works (Strict Network Boundaries)

Preventing SSRF is incredibly difficult because attackers use clever DNS tricks to bypass simple string filters. The best defense is to run the fetching service in a highly restricted, isolated network (VPC/Subnet) that has absolutely no access to internal systems.

# VULNERABLE: Blindly fetching a user-supplied URL
@app.route("/fetch_preview")
def fetch_preview():
    url = request.args.get('url')
    # DANGER: What if url is "http://localhost:6379" (Redis)?
    response = requests.get(url)
    return response.content

# FLAWED DEFENSE: Simple string matching
def is_safe(url):
    # Attackers bypass this using:
    # 1. IP Encodings: http://2130706433 (which is 127.0.0.1)
    # 2. DNS Rebinding: http://local.hacker.com (resolves to 127.0.0.1)
    if "127.0.0.1" in url or "localhost" in url:
        return False
    return True

Watch out for

Worked example

A PDF generation service converts HTML to PDF. It allows users to link external stylesheets (``). An attacker provides HTML with ``. The server-side headless browser fetches that URL to render the PDF. The resulting PDF, which the attacker downloads, contains the server's raw AWS access keys printed directly on the page.

Check yourself

Why do standard string-matching blacklists (like blocking 'localhost' or '169.254...') almost always fail to prevent SSRF?

Correct! This is called DNS Resolution bypass (or DNS Rebinding). The application checks the string 'safe.com' (which looks fine), but when the underlying OS resolves it, it connects to the internal network.
Incorrect. This has nothing to do with encryption.