Headline
CVE-2020-7066: get_headers() silently truncates after a null byte
In PHP versions 7.2.x below 7.2.29, 7.3.x below 7.3.16 and 7.4.x below 7.4.4, while using get_headers() with user-supplied URL, if the URL contains zero (\0) character, the URL will be silently truncated at it. This may cause some software to make incorrect assumptions about the target of the get_headers() and possibly send some information to a wrong server.
Sec Bug #79329
get_headers() silently truncates after a null byte
Submitted:
2020-03-01 18:40 UTC
Modified:
2020-03-17 05:39 UTC
From:
64796c6e69 at gmail dot com
Assigned:
stas (profile)
Status:
Closed
Package:
*URL Functions
PHP Version:
Irrelevant
OS:
any
Private report:
No
CVE-ID:
2020-7066
[2020-03-01 18:40 UTC] 64796c6e69 at gmail dot com
Description:
get_headers() silently truncates anything after a null byte in the URL it uses.
This was tested on PHP 7.3, but the function has always had this bug.
The test script shows that this can cause well-written scripts to get headers for an unexpected domain. Those headers could leak sensitive information or unexpectedly contain attacker-controlled data.
Test script:
<?php // user input $_GET[‘url’] = "http://localhost\0.example.com";
$host = parse_url($_GET[‘url’], PHP_URL_HOST); if (substr($host, -12) !== ‘.example.com’) { die(); } $headers = get_headers($_GET[‘url’]); var_dump($headers);
Expected result:
Warning: get_headers() expects parameter 1 to be a valid path, string given in php shell code on line 1 NULL
Actual result:
headers from http://localhost
Patches
Add a Patch
Pull Requests
Add a Pull Request
History
AllCommentsChangesGit/SVN commitsRelated reports
[2020-03-02 08:33 UTC] [email protected]
-Assigned To: +Assigned To: stas
[2020-03-02 08:33 UTC] [email protected]
Indeed, get_headers()'s $url has to be a valid path, because we’re passing it to php_stream_open_wrapper_ex().
ext/standard/url.c | 2 ± 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ext/standard/url.c b/ext/standard/url.c index 57fd80cc1d…fe6d7f9de1 100644 — a/ext/standard/url.c +++ b/ext/standard/url.c @@ -680,7 +680,7 @@ PHP_FUNCTION(get_headers) php_stream_context *context;
ZEND\_PARSE\_PARAMETERS\_START(1, 3)
Z\_PARAM\_STRING(url, url\_len)
Z\_PARAM\_PATH(url, url\_len) Z\_PARAM\_OPTIONAL Z\_PARAM\_LONG(format) Z\_PARAM\_RESOURCE\_EX(zcontext, 1, 0)
I don’t see the need for an regression test (ZPP only).
[2020-03-02 18:32 UTC] [email protected]
Note: the code in the test script is in no way secure. parse_url() does not guarantee the resulting URL is valid (or even HTTP URL) - it just tries its best to parse it in assumption it’s valid. If you need URL validation (as you should if you importing external URLs) other methods should be used.
That said. no reason for get_headers() to accept URLs with nulls, so it shouldn’t.
[2020-03-16 00:29 UTC] [email protected]
-CVE-ID: +CVE-ID: 2020-7066
[2020-03-17 05:39 UTC] [email protected]
-Status: Assigned +Status: Closed