php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #79405 gethostbyname() silently truncates after a null byte
Submitted: 2020-03-23 02:01 UTC Modified: 2021-01-04 09:21 UTC
From: bigshaq at wearehackerone dot com Assigned: stas (profile)
Status: Closed Package: *Network Functions
PHP Version: All OS: All
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: bigshaq at wearehackerone dot com
New email:
PHP Version: OS:

 

 [2020-03-23 02:01 UTC] bigshaq at wearehackerone dot com
Description:
------------
gethostbyname() silently truncates anything after a null byte in the hostname it uses

This was tested on PHP 8.0.0-dev (cli) and PHP 5.5.9-1ubuntu4.29 (cli) but looks like it's relevant for all versions.

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

$host = "localhost\0.example.com"; //un-trusted source

if (substr($host, -12) !== '.example.com') { //psudo-validation, for PoC purposes
    die('Not allowed');
}

$ip = gethostbyname($host);
var_dump($ip);

?>

Expected result:
----------------
Expected a PHP error that says the host parameter contains invalid characters

Actual result:
--------------
output:
string(9) "127.0.0.1"

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-03-23 02:09 UTC] bigshaq at wearehackerone dot com
***sorry!***, please ignore this part of the report: 
[QUOTE]
"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"
[/QUOTE]
I used a convenient template from another bug I found here and forgot to delete this(so it's not relevant here). 

What I meant to say is:
The test script shows that the null-byte poisoning can cause a PHP application to get un-expected IP addresses while bypassing input validation filters in the same time.
 [2020-03-23 04:14 UTC] stas@php.net
-Status: Open +Status: Feedback
 [2020-03-23 04:14 UTC] stas@php.net
I'm not sure why it is a security issue. What you mean by "unexpected IP addresses"? If you don't own the DNS server, there's no expectation of which IP address can be produced. And DNS server could return any address, including 127.0.0.1 of course. If your app can't deal with it then it's already broken.
 [2020-03-23 08:17 UTC] bigshaq at wearehackerone dot com
-Status: Feedback +Status: Open -PHP Version: Irrelevant +PHP Version: All
 [2020-03-23 08:17 UTC] bigshaq at wearehackerone dot com
I agree that it can be fixed in the networking layer (because the DNS server actually responsible for which address is coming back) 
However, I still think it's a security issue because:
  1. The developer is not aware of the truncation AT ALL. He can write filters/validations in the applicative layer and nothing will really work.
  2. When I wrote "un-expected IP addresses" I meant that gethostbyname() will return an IP address that doesn't belong to anyone from .example.com subdomains. It can be a malicious host. This can lead to info leakage because it's very typical to perform network operation after calling this function (maybe connect to this IP address & send info / other things from this kind)
  3. [QUOTE=stas]If you don't own the DNS server, there's no expectation of which IP address can be produced[/QUOTE] Correct, but if you apply a filter to resolve **subdomains only**, you will be expected to trust the result that gethostbyname() returns because you automatically assume that this IP address belong to one of the "trusted" .example.com subdomains. 


thanks
 [2020-03-23 17:22 UTC] pollita@php.net
While I agree with stas that this is something the app could do as a basic check, I also feel like it wouldn't be wholly unreasonable to just not accept null-bytes in calls to this, or really any non-binary-safe POSIX function.  It's a one-line change in the runtime and any app it breaks is, to quote stas' take: "broken already".
 [2020-03-25 19:58 UTC] bigshaq at wearehackerone dot com
i'm not exactly sure what you mean by saying "broke already", this bug has the same impact as #79329(which, you marked this as a security bug with a CVE). It can lead to impersonation attacks and info leaks.

also, like i said before, the developer is not aware of the truncation at all(this is why the title says "silently truncates after a null byte"). nothing is mentioned in the documentation as well.


I think it's reasonable to follow one of these options:

* deploy a hotfix in the C code
* add a warning in the documentation that says this function truncates everything after a null-byte. And then the truncation won't be silent.

I wouldn't go for the second option just because it will make PHP itself look buggy and, "broken already" :/
 [2020-03-26 12:21 UTC] cmb@php.net
In my opinion, the current behavior is clearly a bug.  The
question is whether it is a security issue.
 [2020-03-26 14:02 UTC] bigshaq at wearehackerone dot com
I think it is, mainly because it's very common to perform network operation after calling gethostbyname (maybe connect to the returned IP address & send info / other things from this kind), which can easily lead to info leaks. 

And this is not a wild example, I actually reported about the attack vector above in a private bounty program that has a popular product that's written in PHP(and this product is not broken at all...they are definitely aware of security. In fact, this is one of the only vulns i found there and it lead to an info leak). We tried to figure out together how it happened because the code looks fine....then, we realized that the filters worked properly, and it was PHP's fault. 

imho, i think it has the same impact as `CVE-2020-7066` if not, then more(because unlike CVE-2020-7066, it's not just HTTP response headers that are spoofed, with this bug, the attacker can spoof the entire packet)

thanks!
 [2020-03-26 14:17 UTC] pollita@php.net
@cmb, Security? Yes, but a low CVSS.  The ability to *trivially* mitigate this in userspace code makes me less enthusiastic about applying it to anything lower than the 7.4 branch at most.  Honestly, given the "break" of disallowing perfectly valid (but odd) strings like "example.com\0" which may be coming from some only-slightly-wonky network code makes me want to apply to 8.0 only.
 [2020-04-09 08:07 UTC] bigshaq at wearehackerone dot com
hi guys, any updates? can we attach a CVE to this bug?

thanks!
 [2020-04-09 14:52 UTC] pollita@php.net
This comes out at a CVSS of 2.8, so no CVE is warranted.
Making this change in 8.0 will be discussed and implemented shortly.
 [2020-04-11 12:09 UTC] bigshaq at wearehackerone dot com
Hi @pollita
This bug basically has the exact same impact as CVE-2020-7066
"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."
I believe it should be a Medium. 
Plus, it's relevant for almost any PHP versions so it (should somehow) lower the complexity. 

Side-note: It's your right to choose the severity and I totally respect that, I'm not trying to tell you how you should rate things. But I think this bug's severity should be re-calculated. And in case you choose not to re-calculate: I'd appreciate if you elaborate why this bug has a rate of 2.8 and the other is Medium (note that in the #79329 report the PoC code was "broken" too).

Thanks! :)
 [2020-04-13 18:08 UTC] stas@php.net
I think we may also need different error messaging, gethostbyname() certainly has nothing to do with filesystem paths. 

> Plus, it's relevant for almost any PHP versions so it (should somehow) lower the complexity. 

Complexity is not the same as security issue. 

> I'd appreciate if you elaborate why this bug has a rate of 2.8 and the other is Medium 

Please read https://wiki.php.net/security#faq
 [2020-04-14 09:30 UTC] bigshaq at wearehackerone dot com
@stas
Actually I was reading that document before sending this report to make sure my bug is valid...but I didn't read the last part(FAQ) so now after reading it I get it.

I still don't agree with the severity BUT php is not my project and i'll have to respect the maintainers' decision :)
Thanks for your time(and patience! haha)
 [2020-05-02 11:33 UTC] cmb@php.net
Note that gethostbynamel() seems to have the same issue.
 [2021-01-04 09:21 UTC] stas@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: stas
 [2021-01-04 09:21 UTC] stas@php.net
The fix for this bug has been committed.
If you are still experiencing this bug, try to check out latest source from https://github.com/php/php-src and re-test.
Thank you for the report, and for helping us make PHP better.


 [2021-01-04 09:54 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=8768621149fbedc0e5aaf847b71108fd459a548a
Log: Fix bug #79405 - gethostbyname() silently truncates after a null byte
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Apr 24 23:01:34 2024 UTC