Georgi Guninski recently discovered a bug in the Apache Web Server, making it possible to crash the http-daemon under certain circumstances.
Whilst version 1.3 appears to be immune to the exploit, version 2.0.49 proved to be affectable. A flaw in the HTTP-Header handling routines may cause Apache to allocate virtually infinite amounts of memory, resulting in heavy swapping activity, and sometimes even a crash of the daemon itself.
For version 2.0.49, there is a patch dealing with the problem. Apache 2.0.50, still to be released, will of course contain a workaround as well.
Disclaimer: The information in this advisory is believed to be true though it may be false. The opinions expressed in this advisory and program are my own and not of any company. The usual standard disclaimer applies, especially the fact that Georgi Guninski is not liable for any damages caused by direct or indirect use of the information or functionality provided by this advisory or program. Georgi Guninski bears no responsibility for content or misuse of this advisory or program or any derivatives thereof.
Description:
There is denial of service in apache httpd 2.0.49. It is possible to consume arbitrary amount of memory. On 64 bit systems with more than 4GB virtual memory this may lead to heap based buffer overflow whose exploitation is unclear at the moment.
Details: The problem is in server/protocol.c ap_get_mime_headers_core: ------ if (last_field != NULL) { if ((len > 0) && ((*field == '\t') || *field == ' ')) { ... fold_buf = (char *)apr_palloc(r->pool, alloc_len); ----- If header lines starts with TAB or SPACE, apache allocates memory for it.
This allows making arbitrary long header lines.
The following applies to 64 bit systems with a lot of virtual memory if sizeof(long)==8 and sizeof(int)==4.
This code can be hit on line 743: ap_escape_html(r->pool, last_field), last_field can be arbitrary long. Looking into ap_escape_html shows: ---- int i, j;
for (i = 0, j = 0; s[i] != '\0'; i++) if (s[i] == '<' || s[i] == '>') j += 3; else if (s[i] == '&') j += 4;
if (j == 0) return apr_pstrmemdup(p, s, i);
x = apr_palloc(p, i + j + 1);
---- (i+j+1) can be made almost arbitraty because of int signedness. On linux x86_64 it was confirmed that sending about 820MB of data overflows (i+j+1) which leads to a crash in memcpy, but with good heap layout more can be done.
Probably only (i) can wrap, but because of the way in which apache leaks memory this is not tested yet.
Fix:
Unofficial fix from an Apache httpd developer, use at your risk. ---------------------------------- Index: server/protocol.c =================================================================== RCS file: /home/cvspublic/httpd-2.0/server/protocol.c,v retrieving revision 1.148 diff -u -r1.148 protocol.c --- server/protocol.c 22 Apr 2004 22:38:03 -0000 1.148 +++ server/protocol.c 13 Jun 2004 19:47:36 -0000 @@ -716,6 +716,23 @@ * continuations that span many many lines. */ apr_size_t fold_len = last_len + len + 1; /* trailing null */
+ if ((fold_len - 1) > r->server->limit_req_fieldsize) { + r->status = HTTP_BAD_REQUEST; + /* report what we have accumulated so far before the + * overflow (last_field) as the field with the problem + */ + apr_table_setn(r->notes, "error-notes", + apr_pstrcat(r->pool, + "Size of a request header field " + "after folding " + "exceeds server limit.<br />\n" + "<pre>\n", + ap_escape_html(r->pool, last_field), + "</pre>\n", NULL)); + return; + }
if (fold_len > alloc_len) { char *fold_buf; alloc_len += alloc_len; ---------------------------------- Workaround: not known.