Bug #73535 [Opn->Csd]: php_sockop_write() returns 0 on error, can be used to trigger Denial of Service

From: 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

« previous php.bugs (#221896) next »