Wednesday, February 22, 2012

How to: set up a Web Application Firewall


This document should serve as a guide for configuring a Web Application Firewall running Apache, mod_proxy and mod_security. I've written this down mainly as a reminder for myself, but if it helps someone out there working on this task, then great.



For the OS, I've used Ubuntu, but you can use whatever distro you'd like. Just be sure to change the distribution-specific steps to meet your needs.


I've downloaded a copy of Ubuntu 11.10 Server, x64 bit Edition and performed a default install onto a VirtualBox vm.


# Update your installation before anything else.


root@waf3:~# apt-get update
root@waf3:~# apt-get upgrade
root@waf3:~# reboot


# Install Apache, mod_security and mod_proxy. apt will install the required dependencies.


root@waf3:~# apt-get install apache2 libapache2-modsecurity libapache2-mod-proxy-html


Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libcap2 modsecurity-crs ssl-cert
Suggested packages:
  apache2-doc apache2-suexec apache2-suexec-custom lua openssl-blacklist
The following NEW packages will be installed:
  apache2 apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common libapache2-mod-proxy-html libapache2-modsecurity libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libcap2
  modsecurity-crs ssl-cert
0 upgraded, 14 newly installed, 0 to remove and 3 not upgraded.
Need to get 3,650 kB of archives.
After this operation, 13.9 MB of additional disk space will be used.
Do you want to continue [Y/n]? 
---


# Create the log directory and DocumentRoot


root@waf3:~# mkdir -p /var/www/proxy/nothing/
root@waf3:~# mkdir /var/log/apache2/proxied-site.local 


# Enable the necessary modules


root@waf3:~# cd /etc/apache2/mods-enabled
root@waf3:~# ln -s ../mods-available/proxy.load 
root@waf3:~# ln -s ../mods-available/proxy_balancer.load 
root@waf3:~# ln -s ../mods-available/proxy_http.load 

root@waf3:~# service apache2 restart


# At this point we kinda have a working WAF, but it's not blocking anything. We need to download the latest core ruleset for mod_security.


root@waf3:~# cd 
root@waf3:~# wget http://sourceforge.net/projects/mod-security/files/modsecurity-crs/0-CURRENT/modsecurity-crs_2.2.3.tar.gz
root@waf3:~# tar xzvf modsecurity-crs_2.2.3.tar.gz 
root@waf3:~# mkdir /etc/apache2/modsecurity-rules/
root@waf3:~# cp -R modsecurity-crs_2.2.3/base_rules/ /etc/apache2/modsecurity-rules/
root@waf3:~# cp /usr/share/modsecurity-crs/modsecurity_crs_10_config.conf /etc/modsecurity/
root@waf3:~# echo 'Include /etc/apache2/modsecurity-rules/base_rules/*.conf' >> /etc/apache2/httpd.conf


# Make sure apache restarts clean


root@waf3:~# service apache2 restart


# Create your vhost, enable the site and restart apache
# See the Notes section for a sample vhost


root@waf3:~# cd /etc/apache2/sites-enabled
root@waf3:~# ln -s ../sites-available/proxied-site.local 
root@waf3:~# service apache2 restart


# Test your installation. So far I've been using dvwa for this. In this example, I'll send an injection to dvwa's sql injection section. You should see an entry in the error_log for the vhost and a 403 Forbidden in the browser


a=a' UNION ALL SELECT first_name, password from dvwa.users;#' 






[Tue Feb 21 18:10:27 2012] [error] [client 192.168.1.49] ModSecurity: Access denied with code 403 (phase 2). Pattern match "(\\\\/\\\\*\\\\!?|\\\\*\\\\/|\\\\-\\\\-[\\\\s\\\\r\\\\n\\\\v\\\\f]|(?:--[^-]*-)|([^\\\\-&])#.*[\\\\s\\\\r\\\\n\\\\v\\\\f]|;?\\\\x00)" at ARGS:id. [file "/etc/apache2/modsecurity-rules/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "37"] [id "981231"] [rev "2.2.3"] [msg "SQL Comment Sequence Detected."] [data ";#' "] [tag "WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"] [hostname "proxied-site.local"] [uri "/vulnerabilities/sqli/"] [unique_id "T0Qu738AAQEAAA@VAxEAAABG"]


Notes:


# If you get the following message in your error log, make sure you enabled proxy_http.load


[Tue Feb 21 18:08:51 2012] [warn] proxy: No protocol handler was valid for the URL /. If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule.


# If you're receiving the following annoying but innocuous message during an apache restart, give apache a name and restart:


apache2: Could not reliably determine this server's fully qualified domain name, using 127.0.1.1 for ServerName


root@waf3:~# echo 'ServerName "blah"' >> /etc/apache2/httpd.conf ; service apache2 restart


# If you plan to use this as a production system, you'll want to quiet the identifiable information apache gives out in /etc/apache2/conf.d/security:


ServerTokens Prod
ServerSignature Off


# Sample vhost


root@:~# cat /etc/apache2/sites-available/proxied-site.local 
<VirtualHost *:80>
       DocumentRoot /var/www/proxy/nothing/


       ServerName proxied-site.local
       ServerAlias proxied-site.local 


       SecRuleEngine On


       ErrorLog /var/log/apache2/proxied-site.local/error_log
       CustomLog /var/log/apache2/proxied-site.local/access_log combined


       <Proxy balancer://testcluster>
           BalancerMember http://192.168.1.26 route=http10 loadfactor=1
           ProxySet lbmethod=byrequests stickysession=BALANCEID
       </Proxy>


       ProxyPass / balancer://testcluster/ stickysession=BALANCEID nofailover=On
       ProxyPassReverse / http://192.168.1.26/


<LocationMatch ^/phpmyadmin>
     SecRuleEngine Off
</LocationMatch>


</VirtualHost>
Post a Comment