PHP Multipart/form-data remote dos Vulnerability
catalog
. Description
. Analysis
1. Description
PHP is vulnerable to a remote denial of service, caused by repeatedly allocate memory、concatenate string、copy string and free memory when PHP parses header areas of body part of HTTP request with multipart/form-data. By sending multiple HTTP multipart requests to an affected application containing malicious header area of body part, a remote attacker could exploit this vulnerability to cause the consumption of CPU resources.
该漏洞利用PHP多次合并boundary里的参数,从而造成多次内存分配和拷贝,从而抢占CPU资源,造成性能下降。攻击者利用并发多包的方式,可以达到使目标系统拒绝服务的目的
HTTP协议中,multipart/form-data中可以包含多个报文,它们被合并在一个复杂报文中发送,每一个部分都是独立的,以':'分隔各自的参数和值,不同部分的报文通过分界字符串(boundary)连接在一起
PHP中实现了解析multipart/form-data协议的功能,在解析时,当出现一个不包含':'的行,且之前有一个有效键值对,则说明该行是上一个键值对里的值,PHP会将值拼接到上一个键值对里。在拼接的过程里,PHP进行了一次内存分配,两次内存复制,以及一次内存释放。当出现多个不包含':'的行时,PHP就会进行大量内存分配释放的操作,从而导致消耗CPU资源性能下降。短时间多次发送这类畸形请求将导致目标服务器DoS
Relevant Link:
http://www.chinaz.com/news/2015/0520/407861.shtml
https://portal.nsfocus.com/vulnerability/list/
2. Analysis
The vulnerable function is multipart_buffer_headers that is called internally by the function SAPI_POST_HANDLER_FUNC in main/rfc1867.c. SAPI_POST_HANDLER_FUNC is the entry-point function which parses body parts of HTTP request with multipart/form-data.
\php-src-master\main\rfc1867.c
SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
{
..
while (!multipart_buffer_eof(mbuff))
{
char buff[FILLUNIT];
char *cd = NULL, *param = NULL, *filename = NULL, *tmp = NULL;
size_t blen = , wlen = ;
zend_off_t offset;
zend_llist_clean(&header);
if (!multipart_buffer_headers(mbuff, &header)) {
goto fileupload_done;
}
..
multipart_buffer_headers
/* parse headers */
static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
{
char *line;
mime_header_entry prev_entry = {}, entry;
int prev_len, cur_len; /* didn't find boundary, abort */
if (!find_boundary(self, self->boundary))
{
return ;
} /* get lines of text, or CRLF_CRLF */
//1. Step 1. The multipart_buffer_headers executes while loop cycle to parse current body part headers, if the boundary string was found.
while( (line = get_line(self)) && line[] != '\0' )
{
/*
2. When parseing current body part headers which is represented as (header, value),
the multipart_buffer_headers function firstly call get_line function to read a line of characters, but get_line return a line when it meets character '\n', not '\r\n'.
After getting a line which is stored in the variable 'line', the multipart_buffer_headers function parses the variable line.
/* add header to table
PHP每次读取HTTP body header中的一行
*/
char *key = line;
char *value = NULL; if (php_rfc1867_encoding_translation())
{
self->input_encoding = zend_multibyte_encoding_detector((const unsigned char *) line, strlen(line), self->detect_order, self->detect_order_size);
} /* space in the beginning means same header */
if (!isspace(line[]))
{
//寻找":"作为key-value的分界符
value = strchr(line, ':');
} if (value)
{
*value = ;
do { value++; } while(isspace(*value));
entry.value = estrdup(value);
entry.key = estrdup(key);
}
//3. And then, it calls zend_llist_add_element function to store entry
else if (zend_llist_count(header))
{
/* If no ':' on the line, add to previous line */
/*
4. In this step, the multipart_buffer_headers function thinks current line is not a new header,
and current line should be append to value of prev_entry. Thus, prev_entry and current line merge into a new entry by executing the following codes:
*/
prev_len = (int)strlen(prev_entry.value);
cur_len = (int)strlen(line); entry.value = emalloc(prev_len + cur_len + );
memcpy(entry.value, prev_entry.value, prev_len);
memcpy(entry.value + prev_len, line, cur_len);
entry.value[cur_len + prev_len] = '\0'; entry.key = estrdup(prev_entry.key); //// free memory
zend_llist_remove_tail(header);
} else {
continue;
} zend_llist_add_element(header, &entry);
prev_entry = entry;
} return ;
}
0x1: The Remote Denial of Service Vulnerability
. If value of body part header consists of n lines
. and first character of each line is not blank character
. and each line did constains character ':'
当满足以上条件时,multipart_buffer_headers函数会不断进行内存申请、参数解析尝试、并尝试将当前行解析出的参数归并入前一个参数键、并释放当前申请内存块
. executes string copy operation twice, frees memory once.
. Each time mergence of entry.value increase length of body part header's value. 每次申请的内存在不断扩大
. thus string copy operations will cause the consumption of CPU resources, and then the service is not available.
//If n is the length of body part header's value, and copying one byte is the unit time complexity,the time complexity of multipart_buffer_headers function is O(n*m)
0x2: example
------WebKitFormBoundarypE33TmSNWwsMphqz
Content-Disposition: form-data; name="file"; filename="s
a
a
a
a"
Content-Type: application/octet-stream <?php phpinfo();?>
------WebKitFormBoundarypE33TmSNWwsMphqz
The value of Content-Disposition consists of 5 lines, and the length of the value of Content-Disposition is 5. The multipart_buffer_headers function executes Step 2.3(内存申请、字符串复制、内存释放) 4 times
. The first time execution copys bytes
. The second execution copys bytes
. The third time execution copys bytes
. The fourth time execution copys bytes
. Thus, the multipart_buffer_headers function executes times byte copy operation.
Default maximum size of body part is 2097152 bytes (2M), It is enough to cause the consumption of CPU resources by sending multiple HTTP multipart requests to an affected application containing malicious header area of body part.
Relevant Link:
https://bugs.php.net/bug.php?id=69364
Copyright (c) 2015 LittleHann All rights reserved
PHP Multipart/form-data remote dos Vulnerability的更多相关文章
- html5 file upload and form data by ajax
html5 file upload and form data by ajax 最近接了一个小活,在短时间内实现一个活动报名页面,其中遇到了文件上传. 我预期的效果是一次ajax post请求,然后在 ...
- Sending forms through JavaScript[form提交 form data]
https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript As in the ...
- form data和request payload的区别
HTML <form> 标签的 enctype 属性 在下面的例子中,表单数据会在未编码的情况下进行发送: <form action="form_action.asp&qu ...
- Web 前沿——HTML5 Form Data 对象的使用
XMLHttpRequest Level 2 添加了一个新的接口——FormData.利用 FormData 对象,我们可以通过 JavaScript 用一些键值对来模拟一系列表单控件,我们还可以使用 ...
- HTTP请求中的form data和request payload的区别
HTML <form> 标签的 enctype 属性 在下面的例子中,表单数据会在未编码的情况下进行发送: <form action="form_action.asp&qu ...
- [整理]Ajax Post请求下的Form Data和Request Payload
Ajax Post请求下的Form Data和Request Payload 通常情况下,我们通过Post提交表单,以键值对的形式存储在请求体中.此时的reqeuest headers会有Conten ...
- AJAX POST请求中参数以form data和request payload形式在servlet中的获取方式
转载:http://blog.csdn.net/mhmyqn/article/details/25561535 HTTP请求中,如果是get请求,那么表单参数以name=value&name1 ...
- Sending HTML Form Data
public Task<HttpResponseMessage> PostFormData(){ // Check if the request contains multipart/fo ...
- AJAX POST请求中參数以form data和request payload形式在servlet中的获取方式
HTTP请求中,假设是get请求,那么表单參数以name=value&name1=value1的形式附到url的后面,假设是post请求,那么表单參数是在请求体中,也是以name=value& ...
随机推荐
- c语言中%s与%c对读入字符串的区别
对于scanf函数,需求%s类型时,\n是不会影响scanf内容的对于需求%c类型时,\n也是字符,自然会有影响.
- 数据字典生成工具之旅(4):NPOI操作EXECL
这篇会介绍NPOI读写EXECL,读写EXECL的组件很多,可以使用微软自己的COM组件EXECL.exe读写,不过这种方式限制很大. 1:客户环境必须装Office(虽然现在机子上不装Office的 ...
- 基于DDD的.NET开发框架 - ABP工作单元(Unit of Work)
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- 让 Generator 自启动
文章同步自个人博客:http://www.52cik.com/2016/07/11/generator-co.html 此前只是简单使用而没有真正的去研究 Generator,这次要好好折腾下这货. ...
- 千呼万唤岂出来,写款软件不容易——Visual Entity 2.0 发布
在各位用户不继的催更中,终于完成了这次更新.Visual Entity这个软件发布于 2011年,这个软件完成后,便上班去了,也没有做什么推广工作.所以知道的用户并不多,尽管它是个非常好用.并且免费的 ...
- .net 估计要死在你手里了
最近不太爽,想换工作,上这些知名的招聘网站,一搜 .net 心凉了一截,很少有大公司用.net,工资也不是很高. 不用我多说什么,想必很多人应该有类似经历,只是打了牙往肚子里咽. 来两副图: 最近用滴 ...
- Dapper Vs Dbentry
公司项目数据库访问采用的dapper,以前没有用过.今天简单的测试下了,dapper和dbentry 查询效率情况. public ActionResult Test() { Sys_UserFaca ...
- Hadoop2.6.0伪分布环境搭建
用到的软件: 一.安装jdk: 1.要安装的jdk,我把它拷在了共享文件夹里面. (用优盘拷也可以) 2.我把jdk拷在了用户文件夹下面. (其他地方也可以,不过路径要相应改变) 3.执行复制安装 ...
- Bootstrap中glyphicons-halflings-regular.woff字体报404错notfound
今天查看网站的源代码,发现有个glyphicons-halflings-regular.woff文件没有找到,因为我的网站使用了bootstrap的Glyphicons 字体图标,因此需要加载Glyp ...
- doc2vec使用说明(一)gensim工具包TaggedLineDocument
gensim 是处理文本的很强大的工具包,基于python环境下: 1.gensim可以做什么? 它可以完成的任务,参加gensim 主页API中给出的介绍,链接如下: http://radimreh ...