// HackTricks · Network Services

PHP SSRF

PHP SSRF

URL-aware PHP functions

When URL-aware wrappers are enabled, functions such as file_get_contents(), fopen(), file(), and md5_file() can accept remote URLs. Passing an attacker-controlled URL to them without validating its resolved destination can create an SSRF vulnerability.[1]

file_get_contents("http://127.0.0.1:8081");
fopen("http://127.0.0.1:8081", "r");
file("http://127.0.0.1:8081");
md5_file("http://127.0.0.1:8081");

WordPress SSRF via DNS rebinding

Patchstack demonstrated that WordPress’s wp_safe_remote_get() checks could be bypassed with DNS rebinding in the versions they tested. The validation path called wp_http_validate_url() before the connection, allowing a hostname to resolve to an allowed address during validation and a different address during the request.[2] Treat this as version-dependent research: verify the exact WordPress and HTTP-library versions before reproducing it.

The same research identified the following callers or wrappers as potentially affected:[2]

  • wp_safe_remote_request()
  • wp_safe_remote_post()
  • wp_safe_remote_head()
  • WP_REST_URL_Details_Controller::get_remote_url()
  • download_url()
  • wp_remote_fopen()
  • WP_oEmbed::discover()

Historical CRLF header injection

PHP bug #81680 documented CRLF injection through the from INI setting used by the HTTP stream wrapper. The behavior is version-dependent and should not be assumed on a patched runtime.[3]

// The following creates a From header and injects an additional header.
ini_set("from", "Hi\r\nInjected: I HAVE IT");
file_get_contents("http://127.0.0.1:8081");
GET / HTTP/1.1
From: Hi
Injected: I HAVE IT
Host: 127.0.0.1:8081
Connection: close

[!WARNING] Test header-injection behavior only against an isolated target: the example sends attacker-controlled HTTP headers to the destination.

Separately, stream contexts intentionally support setting request headers. This is not itself a vulnerability, but it becomes dangerous when an application copies untrusted input into the header string.[4]

$url = "https://example.com/";
$options = [
    'http' => [
        'method' => 'GET',
        'header' => "Accept-Language: en\r\n" .
                    "Cookie: foo=bar\r\n" .
                    "User-Agent: SecurityTestClient/1.0\r\n",
    ],
];

$context = stream_context_create($options);
$file = file_get_contents($url, false, $context);

References