Bug #72345 [Opn->Ana]: session_start() is not subject to max_execution_time
| From: | yohgaki@php.net | Date: | Sat, 27 Aug 2016 07:19:18 +0000 |
| Subject: | Bug #72345 [Opn->Ana]: session_start() is not subject to max_execution_time | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-203607@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=72345&edit=1
ID: 72345
Updated by: yohgaki@php.net
Reported by: maggus dot staab at googlemail dot com
Summary: session_start() is not subject to max_execution_time
-Status: Open
+Status: Analyzed
Type: Bug
Package: Session related
PHP Version: Irrelevant
-Assigned To:
+Assigned To: yohgaki
Block user comment: N
Private report: N
New Comment:
Thank you for reporting. It's possible attackers setup clients that exploit session locking
mechanism to use all server processes/threads.
Counter measure is difficult because "locks" are handled by save handlers.
"lock" is implemented by save handler in various ways.
Any lock mechanism in PHP could be exploited. i.e. It's not a session only issue. Can we handle
timeout signal in the engine?
Previous Comments:
------------------------------------------------------------------------
[2016-07-14 13:00:46] maggus dot staab at googlemail dot com
put the following code into a file called "experiment.php" and you can reproduce the
issue.
with my custom session files handler (see comment above) registered
$handler = new FileSessionHandler(200);
session_set_save_handler($handler, true);
the queued up requests immediately fail.
with the native php-session handler 20 apache workers are are bound with just 1 request. depending
on how "slow" you simulate the first 8 workers, the things get very fast a lot worse as
the apache nearly needs forever to fullfill all the requests.
if (!empty($_GET['worker'])) {
$worker = $_GET['worker'];
echo "<xmp>";
echo "ID: ". $worker."\n";
$start = microtime(true);
echo "ACQUIRE LOCK: ". $start ."\n";
try {
session_start();
} catch (Exception $e) {
var_dump($e->getMessage());
exit();
}
$waited = ((microtime(true) - $start) * 1000);
// simulate work
$sleep = 500;
if ($worker < 8) {
$sleep = 5000;
}
usleep($sleep * 1000);
// make sure the server needs to update the sess file after each request
$_SESSION['worker'][$worker]++;
$finished = ((microtime(true) - $start) * 1000);
echo "FINISHED: ". $finished ."ms\n";
// highlight runs which were blocked by others
// (so session_start() couldn't return immediately)
if ($waited > 10) {
echo '</xmp><span style="color:red">';
}
echo 'BLOCKED FOR '. $waited .'ms';
return;
}
foreach(range(1,20) as $workerId) {
echo '<iframe src="experiment.php?worker='. $workerId
.'"></iframe>';
}
------------------------------------------------------------------------
[2016-07-14 12:56:50] maggus dot staab at googlemail dot com
I created a custom FileSessionHandler class which works arround this (in my eyes php bug) using a
non-blocking flock() call.
https://gist.github.com/staabm/ce225d4b01d7b4e2560848646e13d6fc
As anyone can easily DDOS any web-sapi based php application because of the blocking
default-file-session-handler I hope for a fix at php-src though.
------------------------------------------------------------------------
[2016-07-14 08:12:36] maggus dot staab at googlemail dot com
in the last 2 months we had at least 4 DDOS attacks which succeeded because php "never"
returns from session_start() of parallel running requests.
A few attackers were able to DOS a apache2 (mod_php) with 400 workers, because all the workers were
waiting for a session lock.
would it be possible to add a "lock_timeout" option (or similar) so one could configure
that session_start() should return (or throw) after a certain amount of milliseconds if it could not
acquire a session lock?
------------------------------------------------------------------------
[2016-06-06 17:48:57] maggus dot staab at googlemail dot com
I agree that it is a documented/known issue.
Like https://bugs.php.net/bug.php?id=72346 it is
a very fundamental problem.. The fact that there are a bunch of functions which are not subject to
any timeout makes it really easy to abuse/attack php based applications.
One just needs to block all available php workers and the website will be unavailble. There are no
means in php to protect against such kind of attacks (except you do everything async, but this is
not something 99% of php apps will do)
------------------------------------------------------------------------
[2016-06-06 16:36:58] cmb@php.net
It is documented[1] that:
| The maximum execution time is not affected by system calls,
| stream operations etc. Please see the set_time_limit() function
| for more details.
So, in my opinion, this is not a bug.
[1] <http://php.net/manual/en/info.configuration.php#ini.max-execution-time>
------------------------------------------------------------------------
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=72345
--
Edit this bug report at https://bugs.php.net/bug.php?id=72345&edit=1