Jan 7, 2016

Cookie blacklisting/whitelisting on Apache HTTPD

Apache HTTPD is often deployed as a reverse proxy, as part of which it has to support various security features, one of which is cookie filtering. I implemented cookie backlisting and whitelisting on Apache 2.4 using mod_header directive. It took me some time to figure out the right regex and syntax and would like to share the approach.

Blacklisting is relatively simple where you just need to identify the specific cookie (regex) and use RequestHeader edit to replace the cookie with a blank string.
Whitelisting is a little tricky where you need to extract/store the required cookies from the header, reset the cookie header and then add the whitelisted cookies back.

Before you start, make sure that you print cookies in the logs, just add \"%{Cookie}i\" in LogFormat definition.

Also, since we will be using  mod_header directive, make sure header_module is enabled in HTTPD conf

The request header edits can be added  directly in HTTPD.conf in any section in conf or virtual host.
For clarity, I created a separate conf file (cookie_blacklisting.conf) and included it in httpd.conf.

##Include custom conf for blacklisting
<IfModule headers_module>
                Include conf/custom/cookie_blacklisting.conf
</IfModule>

This is my cookie_blacklisting.conf file which removes blacklisted cookies (BACKLISTED_COOKIE_1 and BACKLISTED_COOKIE_2) from a specific uri (/protecteduri).

SetEnvIf Request_URI "^/ protecteduri " IsProtected

RequestHeader edit Cookie "(^BACKLISTED_COOKIE_1=[^;]*;|; BACKLISTED_COOKIE_1=[^;]*)" "" env= IsProtected
RequestHeader edit Cookie "(^BACKLISTED_COOKIE_2=[^;]*;|; BACKLISTED_COOKIE_2=[^;]*)" "" env= IsProtected

To test this, I created two pages /normal/index.html and /protecteduri/index.html and checked the cookie values in the access logs. The requests for /normal passed all the cookies whereas /protecteduri did not have blacklisted cookies.

This is my cookie_whitelisting.conf file, which tries to whitelist two cookies (WHITELISTED_COOKIE_1 and WHITELISTED_COOKIE_2)

##Get the values of WhileListing cookies
SetEnvIf Cookie "(^WHITELISTED_COOKIE_1=[^;]*| WHITELISTED_COOKIE_1=[^;]*)"  ENV_WHITELISTED_COOKIE_1=$1
SetEnvIf Cookie "(^WHITELISTED_COOKIE_2=[^;]*| WHITELISTED_COOKIE_2=[^;]*)"  ENV_WHITELISTED_COOKIE_2=$1

SetEnvIf Request_URI "^/protecteduri" IsProtected

###For IsProtected, unset cookies
RequestHeader unset Cookie env= IsProtected

###For IsProtected, append the whitelisted cookies

RequestHeader append Cookie "%{ENV_WHITELISTED_COOKIE_1}e; path=/;"  env= IsProtected
RequestHeader append Cookie "%{ ENV_WHITELISTED_COOKIE_2}e; path=/;"  env= IsProtected

I used the same /normal and /protecteduri pages to verify the whitelisting.

Hope this helps.