Of all the workarounds, this is probably the best option because it will still allow ranges to function.
Option 1: (Apache 2.0 and 2.2)
# Drop the Range header when more than 5 ranges.
# CVE-2011-3192
SetEnvIf Range (,.*?){5,} bad-range=1
RequestHeader unset Range env=bad-range
# optional logging.
CustomLog logs/range-CVE-2011-3192.log common env=bad-range
Option 2: (Also for Apache 1.3)
# Reject request when more than 5 ranges in the Range: header.
# CVE-2011-3192
#
RewriteEngine on
RewriteCond %{HTTP:range} !(^bytes=[^,]+(,[^,]+){0,4}$|^$)
RewriteRule .* - [F]
Yes, but very few people are using browsers / download clients that will actually resume downloads, and in many cases sites don't support it for files anyway. However with video it's absolutely expected behaviour.
Additional info : Changing this slightly to drop range header when more than 10 ranges (i:e the 5 on the third line becomes a 10 instead ), can avoid problems where serving of large pdfs get broken by this fix.
I've been testing this fix today on Apache 2.0.53 and observed that when running the attack script against a server patched with option 1 (minus the optional logging) there was still a significant hike in CPU usage, perhaps because there is a cost in processing the header analysis.
Option 2 produced no such hike, and protected the server from attack.
One hypothetical use would be for dealing with formats that have both headers and footers: For example, an MP3 will have a frame header at the start of every frame, so you'd want the beginning of the file to get that header. But you'd also want the last few KB of the MP3, because ID3 tags go there.
You make a request for several ranges of a file using the range header, something like:
Range: bytes=100-200, 600-800, 1500-
If the server supports ranges, it will respond with a 206 Partial Content status, and send a multipart/byteranges response body, which looks like this http://www.freesoft.org/CIE/RFC/2068/225.htm. Basically a delimited string containing all the ranges.
This is useful for some streaming audio/video formats and especially for large pdfs. IIRC, pdfs typically have header information at the end of the file, so it's useful for a pdf reader to get the end of the file first.
For sites that don't serve large files, option #4, disabling the range header, is the simplest option.
Note that this means that downloads are not resumable, which can easily annoy site users even if there is no multimedia involved. You only need to specify one range in the header in this case, but to do that you need option #1.
If you want to limit to one then ? is simpler. Doesn't that version limit to 1+0-1 -> 1-2 though?
But why bother with a complex anchored regex when you can just search for "," in the range header.
I created a little mini site that lets you check if your server is vulnerable, along with some information about the exploit:
http://apache-range-exploit.com/
I've used it for a recent one-off project and it's great and meant for that kind of things: good looking pages even if they were thrown together quickly.
"When using a third party attack tool to verify vulnerability - know that most
of the versions in the wild currently check for the presence of mod_deflate;
and will (mis)report that your server is not vulnerable if this module is not
present. This vulnerability is not dependent on presence or absence of
that module."
Not sure if that's how you are checking for vulnerability, however it was reporting that my site was "not vulnerable" when it was very much so.
I recently fixed an issue where the server wouldn't follow redirects which was causing some false negatives. If your site still shows as a no would you mind letting me know what the domain is so I can fix any other issue?
The way I check for the vulnerability is based on the original perl script in the OP link. I submit 20 byte range requests and check for a Partial string in the response, if I see that I assume that the server is vulnerable. It's more of an educated guess, but I've been using it myself to fix misc servers I have running.
Although pedantically correct, it is quite common for people to use thee term "Apache" to refer to the web server. The folder for settings is "/etc/apache2" on debian based distros for example.
22 comments
[ 2.6 ms ] story [ 59.4 ms ] threadOption 2 produced no such hike, and protected the server from attack.
Range: bytes=100-200, 600-800, 1500-
If the server supports ranges, it will respond with a 206 Partial Content status, and send a multipart/byteranges response body, which looks like this http://www.freesoft.org/CIE/RFC/2068/225.htm. Basically a delimited string containing all the ranges.
This is useful for some streaming audio/video formats and especially for large pdfs. IIRC, pdfs typically have header information at the end of the file, so it's useful for a pdf reader to get the end of the file first.
Note that this means that downloads are not resumable, which can easily annoy site users even if there is no multimedia involved. You only need to specify one range in the header in this case, but to do that you need option #1.
That will allow downloads to still resume and it works in any version of apache.
I've used it for a recent one-off project and it's great and meant for that kind of things: good looking pages even if they were thrown together quickly.
"When using a third party attack tool to verify vulnerability - know that most of the versions in the wild currently check for the presence of mod_deflate; and will (mis)report that your server is not vulnerable if this module is not present. This vulnerability is not dependent on presence or absence of that module."
Not sure if that's how you are checking for vulnerability, however it was reporting that my site was "not vulnerable" when it was very much so.
The way I check for the vulnerability is based on the original perl script in the OP link. I submit 20 byte range requests and check for a Partial string in the response, if I see that I assume that the server is vulnerable. It's more of an educated guess, but I've been using it myself to fix misc servers I have running.