modsecurity vs content compression

June 17, 2009

For some time I run modsecurity on Apache as a reverse proxy. It is just monitoring,  and I’m always uncomfortable with the message bellow:

[Wed Jun 17 11:38:40 2009] [error] [client 192.168.1.1] ModSecurity: Warning. Operator EQ matched 0 at GLOBAL. [file “/etc/httpd/conf.d/modsecurity2/
modsecurity_crs_30_http_policy.conf”] [line “120”] [id “960903”] [msg “ModSecurity does not support content encodings”] [severity “WARNING”] [hostname “w
ww.example.org”] [uri “/overlib/over.js”] [unique_id “P02WQH8AAAEAAGGvs4EAAAAK”]

This happen because modsecurity is not able to handle content compressed by backend server!

Deploying a new reverse proxy with Apache, I look for a solution to this problem I found http://thread.gmane.org/gmane.comp.apache.mod-security.user/5041/focus=5042 , a very effective solution. But has a collateral effect, you loose the compression between the reverse proxy and the backend server. Actually is possible to don’t loose this compression, but I believe that is more “cheaper” to loose this compression instead off compress at backend, decompress at reverse proxy and compress again to deliver to client. One other way to achieve this is to turn off compression at backend, but as mentioned in the mail thread above, is not always easy do this, because some times the backend are not on your hands, I you cant guarantee that the admin ll keep the compression off.

I change the proposed Apache setup a little bit, from the Bryan (link above), to make it more simple if you need turn off modsecurity or mod_deflate. Check it bellow

<IfModule mod_deflate.c>

ExtFilterDefine nodeflate mode=output cmd=/bin/true \
enableenv=SomeVarThatWillNeverBeSet

SetOutputFilter DEFLATE

# Netscape 4.x has some problems…
BrowserMatch ^Mozilla/4 gzip-only-text/html
# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip
# IE is ok, but looked like Netscape, so we reset it
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

SetEnvIfNoCase Accept-Encoding gzip force-gzip
SetEnvIfNoCase TE gzip force-gzip

RequestHeader unset Accept-Encoding
RequestHeader unset TE

# Skip images based on extension
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|zip|exe|swf|mp?eg|mp3|tgz|tar.gz|avi|ico|gz)$ no-gzip dont-vary

# Make sure caching still works
Header append Vary User-Agent env=!dont-vary

<IfModule mod_security2.c>
FilterDeclare modsec CONTENT_SET
FilterProvider modsec modsecurity_out env=modsec-ignore !=1
</IfModule>
FilterDeclare compress CONTENT_SET
FilterProvider compress deflate env=force-gzip =1
#FilterProvider compress inflate Content-Type $image/jpeg
#FilterProvider compress inflate Content-Type $image/gif
#FilterProvider compress inflate Content-Type $image/png
FilterProtocol compress “change=yes”
<IfModule mod_security2.c>
FilterChain modsec compress
</IfModule>

<IfModule !mod_security2.c>
FilterChain compress
</IfModule>
</IfModule>

After this you still deliver the content compressed to the web browser and modsecurity can now check every content, from all your applications and backends.

Advertisements