|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2015-10-05 15:34 UTC] ondrej@php.net
Description: ------------ As reported here: https://bugs.debian.org/800564 by brian m. carlson: Applies to all PHP versions. PHP uses the DJB "times 33" hash to hash strings in its hash tables, without the use of any secret key. Hash values are therefore the same between multiple invocations. As a result, it's trivial to precompute a set of values that all hash to the same bucket and cause positively abysmal performance. If a script accepts untrusted hash keys, such as from JSON input, it is subject to a DoS attack. PHP implemented the max_input_vars option, but this is not effective in the general case, especially in the era of JSON-laden POST requests. Perl, Python, and Ruby have all addressed their CVEs properly, but PHP has not and as a result is still vulnerable. Cloning my example repository[0] and running "php scripts/exploited.php < example/1048576.json" demonstrates the problem very quickly. The similar Perl and Python scripts are not vulnerable to this attack. A JSON file containing only 65536 entries takes PHP 5.6 22 seconds to process. A new CVE should probably be allocated and the bug should be fixed correctly this time, probably by seeding a key from /dev/urandom and using SipHash-2-4 or the like. Python had CVE-2012-1150 and CVE-2013-7040. Ruby had CVE-2011-4815. I can't find a CVE for Perl's 2003 fix, if one exists. The fix, which went into 5.8, was incomplete and was addressed by CVE-2013-1667. [0] https://github.com/bk2204/php-hash-dos Test script: --------------- https://github.com/bk2204/php-hash-dos PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Oct 27 10:00:01 2025 UTC |
Just got around to doing some microbenchmarks. For switching everything to siphash (incl integer hashes): SipHash Baseline Packed int insert: 16.9 mus +/- 0.3 mus 17.1 mus +/- 0.1 mus -1.0% Reverse int insert: 49.0 mus +/- 0.4 mus 17.3 mus +/- 0.2 mus +182.7% Reverse int insert x16 collisions: 54.0 mus +/- 1.1 mus 43.3 mus +/- 0.2 mus +24.6% Incrementing string insert: 62.6 mus +/- 0.7 mus 44.8 mus +/- 0.3 mus +39.6% This means unpacked integer hashtable is about 3x slower. The break-even point with the previous implementation is somewhere between 16x and 32x collisions per bucket. For very short strings w/o hash cache we have 40% slowdown. It's unlikely that this will be deemed acceptable even with more optimization work (like the semi-packed variant mentioned above). So we should probably go with the collision counting during insert.