SSRF (Server-Side Request Forgery) Explained

Share

TL;DR

SSRF happens when your server fetches URLs provided by users without proper validation. Attackers can use this to access internal services, cloud metadata endpoints, or scan your network. If you fetch URLs on the server, validate that they're public URLs and block requests to private IP ranges and cloud metadata endpoints.

What Is SSRF?

Server-Side Request Forgery (SSRF) occurs when an attacker can make your server send HTTP requests to arbitrary destinations. Unlike client-side attacks, SSRF uses your server's network position to access internal resources.

How SSRF Attacks Work

Vulnerable URL fetching
// User provides a URL to fetch
app.post('/api/fetch-preview', async (req, res) => {
  const { url } = req.body;
  const response = await fetch(url);  // VULNERABLE!
  const data = await response.text();
  res.json({ preview: data });
});

// Attacker sends:
// url = "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
// This accesses AWS metadata from inside your cloud!

Common SSRF Targets

  • Cloud metadata: 169.254.169.254 exposes AWS/GCP/Azure credentials
  • Internal services: http://localhost:8080/admin
  • Internal APIs: http://internal-api.local/secret
  • Network scanning: Probe internal IP addresses

Cloud danger: The metadata endpoint at 169.254.169.254 can expose IAM credentials, API keys, and other secrets. This is a primary target for SSRF attacks in cloud environments.

How to Prevent SSRF

Validate URLs before fetching
import { URL } from 'url';

function isValidPublicUrl(urlString) {
  try {
    const url = new URL(urlString);

    // Only allow HTTP(S)
    if (!['http:', 'https:'].includes(url.protocol)) {
      return false;
    }

    // Block private/internal IPs
    const blockedPatterns = [
      /^localhost$/i,
      /^127\./,
      /^10\./,
      /^172\.(1[6-9]|2[0-9]|3[0-1])\./,
      /^192\.168\./,
      /^169\.254\./,  // Cloud metadata
      /^0\./,
      /\.local$/i,
      /\.internal$/i,
    ];

    if (blockedPatterns.some(p => p.test(url.hostname))) {
      return false;
    }

    return true;
  } catch {
    return false;
  }
}

app.post('/api/fetch-preview', async (req, res) => {
  const { url } = req.body;

  if (!isValidPublicUrl(url)) {
    return res.status(400).json({ error: 'Invalid URL' });
  }

  // Now safer to fetch
  const response = await fetch(url);
});

When does SSRF apply to my app?

SSRF is relevant whenever your server fetches URLs based on user input. This includes URL preview features, webhook callbacks, image downloads, and file imports from URLs.

Is DNS rebinding a concern?

Yes. Attackers might use DNS that initially resolves to a public IP but later resolves to a private IP. Consider resolving DNS and validating the IP before making the request.

Check for SSRF Vulnerabilities

Our scanner tests URL fetching endpoints for SSRF issues.

Start Free Scan
Vulnerability Guides

SSRF (Server-Side Request Forgery) Explained