← Back to All Vulnerabilities

Server-Side Request Forgery (SSRF) Vulnerability

Server-Side Request Forgery (SSRF) is a vulnerability that allows an attacker to induce the server-side application to make requests to an unintended location. This can be used to access internal services behind firewalls, scan internal networks, or retrieve files from the server itself.

SSRF Demonstration

URL Preview Tool

This tool generates previews of websites by fetching their content server-side and displaying a summary.

http://websploit.fun/preview.php?url=https://example.com

SSRF Vulnerability:

This service is vulnerable to SSRF because it doesn't validate or restrict the URLs that can be requested. Try these payloads:

  • http://localhost:8080/latest/meta-data/iam/security-credentials/instance-role - Access cloud instance metadata
  • http://localhost:8081/api/settings - Access internal admin API
  • file:///etc/passwd - Read local files on the server
  • http://10.0.0.1 - Scan internal network
  • http://169.254.169.254/latest/meta-data/ - Common cloud metadata endpoint

URL Preview Tool (Secure)

This is a secure version of the URL preview tool that implements proper validation and restrictions.

http://websploit.fun/secure-preview.php?url=https://example.com

Security Implementations:

  • URL Validation - Only allows HTTP and HTTPS schemes
  • IP Address Filtering - Blocks requests to private IP ranges
  • Domain Whitelisting - Only allows specific trusted domains
  • Protocol Restrictions - Disables file:// and other non-HTTP protocols
  • DNS Rebinding Protection - Resolves hostnames only once

Try the same exploit URLs from the vulnerable service - they will all be blocked!

Typical Network Architecture

This diagram shows a typical cloud/network architecture and how SSRF can be used to bypass security boundaries.

Internet DMZ / Public Network Public-facing web servers Web App Server Private Network Admin API Database Metadata Service ... Normal Access SSRF Attack Path

How SSRF Bypasses Network Boundaries:

  1. Attacker sends a request to the public web server with a malicious URL
  2. Web server makes a request to the URL, which points to an internal service
  3. Internal service responds, believing the request is legitimate since it comes from the web server
  4. Web server returns the response to the attacker, revealing internal information

This attack works because the internal network trusts requests from the web server, but the web server is processing untrusted user input.

Common SSRF Attack Vectors

1. Cloud Metadata Services

Cloud providers expose instance metadata at well-known IP addresses:

Attackers can use SSRF to access these endpoints and retrieve sensitive information like IAM credentials.

2. Internal Services

Organizations often have internal services that aren't meant to be publicly accessible:

3. Local Files

If the application supports the file:// protocol, attackers can read local files:

4. Port Scanning

SSRF can be used to scan internal ports and map the network:

Response timing and error messages can reveal if ports are open or closed.

5. Evading Defenses

Various techniques to bypass URL filtering:

How to Prevent SSRF Vulnerabilities

1. Input Validation

Implement thorough URL validation:

// Whitelist allowed schemes
$allowed_schemes = ['http', 'https'];
$parsed_url = parse_url($url);
if (!isset($parsed_url['scheme']) || !in_array($parsed_url['scheme'], $allowed_schemes)) {
    return 'Invalid URL scheme';
}

// Whitelist allowed domains
$allowed_domains = ['example.com', 'trusted-domain.com'];
$hostname = $parsed_url['host'];
$is_allowed = false;
foreach ($allowed_domains as $domain) {
    if (strcasecmp($hostname, $domain) === 0 || 
        preg_match('/\\.' . preg_quote($domain, '/') . '$/', $hostname)) {
        $is_allowed = true;
        break;
    }
}
if (!$is_allowed) {
    return 'Domain not in whitelist';
}
        

2. Block Private IP Ranges

Prevent requests to internal networks:

// Resolve hostname to IP
$ip = gethostbyname($hostname);

// Check against private IP ranges
$private_ranges = [
    '10.0.0.0/8',       // Private network
    '172.16.0.0/12',    // Private network
    '192.168.0.0/16',   // Private network
    '127.0.0.0/8',      // Localhost
    '169.254.0.0/16',   // Link-local
    // ... other restricted ranges
];

foreach ($private_ranges as $range) {
    if (ip_in_range($ip, $range)) {
        return 'IP address not allowed';
    }
}
        

3. Use Allow Lists Instead of Block Lists

Whitelist allowed resources rather than trying to block malicious ones:

// Instead of trying to block all internal IPs,
// only allow specific external domains or APIs

$allowed_endpoints = [
    'api.github.com',
    'api.stripe.com',
    'maps.googleapis.com'
];

if (!in_array($hostname, $allowed_endpoints)) {
    return 'Endpoint not allowed';
}
        

4. Disable Unused URL Schemas

Restrict the application to only use necessary protocols:

// In PHP with curl
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);

// In Java with URLConnection
if (!"http".equals(url.getProtocol()) && !"https".equals(url.getProtocol())) {
    throw new IllegalArgumentException("Only HTTP(S) is allowed");
}
        

5. Use a Separate Service

Isolate URL-fetching functionality in a separate service with limited privileges:

6. Implement DNS Rebinding Protection

Prevent DNS rebinding attacks by validating the IP both before and after the request:

// Resolve the hostname once and use that IP for the actual request
$hostname = parse_url($url, PHP_URL_HOST);
$ip = gethostbyname($hostname);

// In curl, use CURLOPT_RESOLVE to force the IP
curl_setopt($ch, CURLOPT_RESOLVE, ["$hostname:443:$ip"]);
        

7. Use Network-Level Protection