Server-Side Request Forgery (SSRF)¶
Server-Side Request Forgery, or SSRF, is a vulnerability where an attacker induces the server itself to issue an HTTP or other network request to a destination the attacker controls or chooses, by supplying or influencing a URL that the server later fetches. Unlike CSRF, which forges a request from a victim’s browser toward an application, SSRF forges a request from the application’s own server, using the server’s network position and credentials.
Typical entry points are any server-side code that fetches a user-supplied URL: webhook registration, image/PDF/archive fetchers and thumbnail generators, URL preview features, XML parsers that resolve external entities, and API integrations that accept a callback or resource URL.
Consequences include:
Reaching internal-only services that are not exposed to the public internet, effectively using the server as a proxy through the firewall.
Querying cloud metadata endpoints, such as
http://169.254.169.254/on AWS/GCP/Azure, to steal instance credentials or tokens.Port-scanning the internal network by observing timing or error differences on the fetch.
Reading local files if the fetching code also accepts
file://or other non-HTTP schemes.
Mitigation strategies include:
Validating the destination against an allowlist of hosts or URL patterns, rather than a denylist.
Resolving the hostname and rejecting requests to private, loopback, and link-local IP ranges (
127.0.0.0/8,10.0.0.0/8,169.254.0.0/16, etc.) before connecting.Disabling automatic redirect following, or re-validating the destination on every redirect hop.
Restricting the allowed URL schemes to
http/httpsand rejectingfile://,gopher://,dict://, and other wrapper.
<?php
// Vulnerable: server fetches whatever URL the attacker supplies.
$url = $_GET['image_url'];
$data = file_get_contents($url); // could target http://169.254.169.254/ or an internal host
// Safer: validate the host against an allowlist and resolved IP before fetching.
$host = parse_url($url, PHP_URL_HOST);
$ip = gethostbyname($host);
if (!in_array($host, ['images.example.com'], true) || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
throw new \InvalidArgumentException('Untrusted URL');
}
$data = file_get_contents($url);
?>
See also PortSwigger: SSRF.
Related : Cross Site Request Forgery (CSRF), Injection, Taint Analysis, Static Application Security Testing (SAST), Security, file_get_contents(), Client URL (CURL), Wrapper, Vulnerability