Bug #73535 [Opn->Csd]: php_sockop_write() returns 0 on error, can be used to trigger Denial of Service
| From: | nikic@php.net | Date: | Mon, 22 Jul 2019 19:13:18 +0000 |
| Subject: | Bug #73535 [Opn->Csd]: php_sockop_write() returns 0 on error, can be used to trigger Denial of Service | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-221896@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=73535&edit=1
ID: 73535
Updated by: nikic@php.net
Reported by: webmaster_20161114 at cubiclesoft dot com
Summary: php_sockop_write() returns 0 on error, can be used
to trigger Denial of Service
-Status: Open
+Status: Closed
Type: Bug
Package: Streams related
Operating System: All
PHP Version: Irrelevant
-Assigned To:
+Assigned To: nikic
Block user comment: N
Private report: N
New Comment:
This should be fixed in PHP 7.4.
Previous Comments:
------------------------------------------------------------------------
[2019-07-18 14:33:14] nikic@php.net
PR up at https://github.com/php/php-src/pull/4433. We
should take the chance to fix this in 7.4 before we get too late in the release cycle.
------------------------------------------------------------------------
[2018-07-20 15:32:57] webmaster_20161114 at cubiclesoft dot com
It's clearly NOT a documentation problem but a bug in PHP. Please stop marking it as such.
stream_select() returns a writeable socket, so software will attempt to write, the fwrite() fails
due to disconnect but returns 0 instead of false. The code loops around to stream_select() on the
socket again, which returns again immediately, fwrite() fails, etc. As such, it's simply not
possible to detect write failures with non-blocking sockets which means there is no userland
workaround. 0 !== false. Returning false from fwrite() is absolutely necessary.
------------------------------------------------------------------------
[2018-07-10 15:07:09] bwoebi@php.net
I am aware of that behavior and I agree it's suboptimal.
The documentation should be updated to properly handle 0 bytes written (return value is 0). There
generally are just two possible reasons why it would return 0 on an otherwise perfectly clean
stream: a) the buffer is full or b) the other end closed their connection end. The former only
applies for non-blocking streams, where, to distinguish between both cases you use stream_select()
(or equivalents).
I wish as well for a refactoring of these APIs allowing for easier error handling. But it's not
a bug nor a security issue inherent to PHP, an user can work around it.
------------------------------------------------------------------------
[2018-01-20 14:43:08] webmaster_20161114 at cubiclesoft dot com
I definitively ran into this issue this week in a live production environment. When running PHP
userland code as a server (aka non-blocking sockets bound to a port), this bug can be triggered
fairly easily to take out the whole server. To date I had only triggered the bug in testing but
realized it could happen with any userland server written in PHP at any point in time. As
technology progresses, more people are writing servers in various languages, including PHP (e.g.
ReactPHP). Eventually someone else will independently discover this bug and they won't play
nice. Please prioritize a fix.
Also, someone please update this bug report with the CVE so that it gets noticed/triaged.
------------------------------------------------------------------------
[2017-09-07 16:17:44] cmb@php.net
Hm, your suggested patch wouldn't work, since php_sockop_write()
and php_stream_write() both return a size_t. Since the latter is
a PHP_API, we can't change that.
Not sure, what to do. :(
[1] <https://php-lxr.adamharvey.name/source/xref/PHP-7.2/main/streams/xp_socket.c#61>
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=73535
--
Edit this bug report at https://bugs.php.net/bug.php?id=73535&edit=1