nginx and Apache killer

Maxim Dounin mdounin at
Sun Aug 28 16:36:35 UTC 2011


On Sun, Aug 28, 2011 at 05:19:25PM +0300, Gena Makhomed wrote:

> On 27.08.2011 11:11, Igor Sysoev wrote:
> >Following "Apache Killer" discussions and the advisory from 2011-08-24
> >(Advisory: Range header DoS vulnerability Apache HTTPD 2.x CVE-2011-3192)
> >we'd like to clarify a couple of things in regards to nginx behavior
> >either in standalone or "combo" (nginx+apache) modes.
> CVE-2011-3192 updated 26 Aug 2011. UPDATE 2 version available from
> >In order to mitigate this attack when your installation includes
> >apache behind nginx we recommend you the following:
> >
> >1. Refer to the above mentioned security advisory CVE-2011-3192 for apache
> >and implement described measures accordingly.
> these workarounds are needed only if "naked" apache open to internet.
> if apache listen only at and located behind nginx frontend,
> enough ipmlement protection only at nginx level.

I don't recommend relying on only nginx level protection even if 
your backend server is only reachable from localhost.  It's 
always a good idea to follow vendor recommendation and apply 
needed security fixes to affected software.  This applies to other 
cases as well, not only to this particular Apache problem.

> >2. Consider using nginx configuration below (in server{} section of
> >configuration). This particular example filters 5 and more ranges
> >in the request:
> >
> >   if ($http_range ~ "(?:\d*\s*-\s*\d*\s*,\s*){5,}") {
> >       return 416;
> >   }
> this example allow 5 ranges in the request,
> and blocks with 416 return code only 6 and more ranges.
> to protect apache it is necessary filter malicious range requests
> not only in "Range:" header, but also in "Request-Range:" header.

Yes, this is valid point.  Please note that Apache's updated 
advisory incorrectly calls the header as "Range-Request" in some 
places, while it's instead "Request-Range".  Actual 
countermeasures in advisory are correct though.

> to emulate directive "max_ranges 5;" to allow max 5 ranges:
> if ($http_range ~ "(?:\d*\s*-\s*\d*\s*,\s*){5,}") {return 416;}
> if ($http_request_range ~ "(?:\d*\s*-\s*\d*\s*,\s*){5,}") {return 416;}
> to emulate directive "max_ranges 1;" to allow only one range:
> if ($http_range ~ ",") {return 416;}
> if ($http_request_range ~ ",") {return 416;}
> to completely remove these headers while proxying requests to apache:
> proxy_set_header Range "";
> proxy_set_header Request-Range "";

In case of Request-Range you don't need any checks, just unset it 

    proxy_set_header Request-Range "";

in nginx or equivalent

    RequestHeader unset Request-Range

in Apache.

It's long obsolete one used by ancient browsers, never defined in any 
standard.  It's not even supported by nginx.

> >We'd also like to notify you that for standalone nginx installations
> >we've produced the attached patch. This patch prevents handling
> >malicious range requests at all, instead outputting just the entire file
> >if the total size of all ranges is greater than the expected response.
> this not protect nginx from "frequent nginx disk seek (D)Dos attack",
> and additional max_ranges checks/protections for nginx is required!!!

I don't think the "attack" you are talking about is something 
practical.  It requires prior knowledge of urls of many really 
large (and "cold", i.e. not cached) files on the attacked site, 
and it as well relies on disk seeks to be costly which is not 
always true (and almost always not true for a single file, as even 
"really large" still usually means "much less than disk size", 
i.e. one can't force full disk seeks).  Additionally, maximum 
number of ranges requested in such "attack" is effectively limited 
by maximum header length to something about 500 by default.

(On the other hand, I *do* think that limiting number of ranges to 
low number like 5 suggested here and there *is* harmfull.  Quick 
look over logs on my server for a couple of days reveals perfectly 
valid requests from Adobe Reader with up to 17 ranges.  Minimum 
sane value will be something about 50.)

Maxim Dounin

More information about the nginx mailing list