Edit Page

Lab 9: Web Application Firewall (WAF)

Setup and configure ModSecurity, a Web Application Firewall (WAF) to detect common web application attacks and add geo-restriction.

A Web Application Firewall (WAF) is a system application firewall that sits between the Internet and your web application creating a shield that filters and blocks HTTP traffic to and from a web server. It can can be used to block common security attacks targeting your web application such as SQL injection, cross site scripting (XSS), local file inclusion, and many others.

In this lab, we will use OWASP’s ModSecurity, an open source WAF, with the Core Rule Set (CRS), which is a set of generic attack detection rules for use with ModSecurity. In addition to vulnerability protection, we will use ModSecurity to geo-restrict access to our web application and prevent users from outside the country access our website. For a more straightforward configuration, we will use the official ModSecurity Docker + Core Rule Set (CRS) images.

Setup/Prerequisites

Step 1: Provision a Virtual Machine (VM) instance

  1. Create a Linux VM instance. The instance type should be the cheapest general-purpose available type by your cloud provider. At the time of writing this activity, the cheapest types are listed in the follow table:

    Cloud ProviderInstance TypevCPUMemory
    AzureB1ls10.5 GiB
    AWSt4g.nano20.5 GiB
    GCPf1-micro10.6 GB
    Digital OceanBasic Droplet10.5 GiB

    Table 1: the cheapest VM instance types across different cloud providers

Please check the minimum hardware requirements to run the OS image as some images (e.g., Ubuntu) require more memory.

  1. Allow port 80 on the VM instance.

  2. SSH into the VM instance

ssh -i /path/to/private-key.pem username@ip-address
  1. Update and upgrade system packages
sudo apt update
sudo apt upgrade -y

Step 2: Install apache httpd, php, and deploy the sample web page

  • Install apache httpd server
sudo apt install -y apache2
  • Install PHP, the Apache PHP module, and the php cURL extension
sudo apt install -y php libapache2-mod-php php-curl
  • Install composer, the dependency manager for PHP applications. We will install composer globally as a system wide executable using the following installer script.
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'c8b085408188070d5f52bcfe4ecfbee5f727afa458b2573b8eaaf77b3419b0bf2768dc67c86944da1544f06fa544fd47') { echo 'Installer verified'.PHP_EOL; } else { echo 'Installer corrupt'.PHP_EOL; unlink('composer-setup.php'); exit(1); }"
php composer-setup.php
php -r "unlink('composer-setup.php');"

This should have downloaded the installer to the current directory, verified the installer SHA-384, ran the installer and removed it.

  • Next, move the installer into a location available in your PATH environment variable.
sudo mv composer.phar /usr/local/bin/composer
  • Test the installation
composer --version

You should see the version number (e.g., 2.7.6)

If you run into any error during the installation of composer, then please refer to the download and installation instructions at https://getcomposer.org/download/

  • Install git and clone the web application and install its dependencies
sudo apt install git -y
git clone https://gitlab.com/cpit490/ip-info-webpage.git
sudo mv ip-info-webpage/* /var/www/html
sudo rm index.html
  • Build the web app
cd /var/www/html
sudo composer install
sudo chown -R www-data:www-data /var/www/html/
  • Restart Apache
sudo systemctl restart apache2
  • Check the status to make sure the configs are loaded and apache is running
sudo systemctl status apache2
  • Test the web page by visiting the public ip address of your VM instance.

screenshot of the deployed web page

Step 3: Install ModSecurity

We will install ModSecurity and configure it with OWASP’s CRS, a set of common attack detection rules. ModSecurity will be configured to accept requests to our Apache web server only from a specific country, rejecting all others. It will also be set up to intercept and log common web application attacks to /var/log/apache2/modsec_audit.log.

  • Install ModSecurity
sudo apt install -y libapache2-mod-security2
  • Enable ModSecurity
sudo a2enmod security2
  • Use the included and recommended modsecurity.conf-recommended file as a starter config file that we will customize and modify:
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
sudo nano /etc/modsecurity/modsecurity.conf
  • Find the line that says SecRuleEngine DetectionOnly and change it from DetectionOnly to On. Save the file and exit.

  • Download OWASP’s ModSecurity Core Rule Set (CRS) and configure ModSecurity to use it. OWASP CRS is a set of generic attack detection rules for use with ModSecurity.

cd ~/
git clone https://github.com/coreruleset/coreruleset.git
sudo mv coreruleset /etc/apache2/modsecurity-crs
  • Use the CRS example setup.conf file crs-setup.conf.example
sudo cp /etc/apache2/modsecurity-crs/crs-setup.conf.example /etc/apache2/modsecurity-crs/crs-setup.conf
  • Next, we will configure ModSecurity to use the CRS in the Apache configuration file. Open the security2.conf file:
sudo nano /etc/apache2/mods-enabled/security2.conf
  • Find the line IncludeOptional /usr/share/modsecurity-crs/*.load and commented it out by inserting # at the beginning of the line.
#IncludeOptional /usr/share/modsecurity-crs/*.load
  • Add the following lines to the end of the file before the closing tag </IfModule>. Please maintain the exact whitespace indentation in the config file:
Include /etc/apache2/modsecurity-crs/crs-setup.conf
Include /etc/apache2/modsecurity-crs/rules/*.conf

Save the file and exit

  • Restart Apache to apply the changes:
sudo systemctl restart apache2

If you do not see any errors, then this indicates that the configuration has been successfully completed.

  • Test ModSecurity by sending a request that triggers one of the CRS rules. For example, we can send a request that includes ?exec=/bin/bash in the URL, which is a common pattern in command injection attacks:
    • Open your web browser and visit http://your-public-ip/index.php?exec=/bin/bash
    • If ModSecurity is working correctly, you should see a 403 Forbidden response.
    • Check the ModSecurity audit log to see the details of the blocked request using sudo cat /var/log/apache2/modsec_audit.log
      • You should see an entry for the blocked request, including the matched CRS rule that triggered the block.

Step 4: Configure Geo-Restriction

  • Install the GeoIP module and the GeoIP database:
sudo apt install -y libapache2-mod-geoip geoip-database
  • Enable the GeoIP module:
sudo a2enmod geoip
  • Configure the GeoIP module to use the free GeoLite database:
  • Open the geoip.conf file:
sudo nano /etc/apache2/mods-enabled/geoip.conf
  • Modify the config file to include the following:
GeoIPEnable On
GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
  • Configure ModSecurity to block requests from outside your country. However, since we need to test the geo blocking and we do not want to setup a VPN or proxy server, we will block access that is not from the United States country (using the US ISO country code).

  • Open the ModSecurity configuration file.

sudo nano /etc/modsecurity/modsecurity.conf

Scroll to the bottom of a file in the nano text editor, you can use the Ctrl + V keyboard shortcut multiple times. Add the following at the end of the file:

# Configure geolocation database
SecGeoLookupDb /usr/share/GeoIP/GeoIP.dat
# Lookup IP address
SecRule REMOTE_ADDR "@geoLookup" "phase:1,id:155,nolog,pass"
# Block IP address for which geolocation failed
SecRule &GEO "@eq 0" "phase:1,id:156,deny,msg:'Failed to lookup IP'"
# Block non US IP Addresses
SecRule REMOTE_ADDR "@geoLookup" "chain,id:22,drop,msg:'Non-US IP address'"
SecRule GEO:COUNTRY_CODE "!@streq US"
  • Restart Apache to apply the changes:
sudo systemctl restart apache2
  • Now, ModSecurity should block requests from our country and log them to /var/log/apache2/modsec_audit.log.

  • Visit the web page and make sure your request is blocked. You should see no response from the web server since there’s no 403 page was configured.

  • Now, we know that we can restrict access to a single country, replace US with SA to block requests that is not from Saudi Arabia.

# Configure geolocation database
SecGeoLookupDb /usr/share/GeoIP/GeoIP.dat
# Lookup IP address
SecRule REMOTE_ADDR "@geoLookup" "phase:1,id:155,nolog,pass"
# Block IP address for which geolocation failed
SecRule &GEO "@eq 0" "phase:1,id:156,deny,msg:'Failed to lookup IP'"
# Block non SA IP Addresses
SecRule REMOTE_ADDR "@geoLookup" "chain,id:22,drop,msg:'Non-SA IP address'"
SecRule GEO:COUNTRY_CODE "!@streq SA"
  • Restart Apache to apply the changes:
sudo systemctl restart apache2
  • Now, ModSecurity should block requests not from our country and log them to /var/log/apache2/modsec_audit.log. Visit the web page and make sure your request is allowed.

  • Tear down all resources.

Limitations

While implementing a web application firewall (WAF) provides significant security benefits, there are several important limitations to consider:

  1. GeoIP Database Accuracy: The GeoIP databases may not always reflect the most current IP address assignments especially the free database that we used is typically updated less frequently than commercial databases. In addition, IP address reassignments between regions can lead to incorrect geolocation results

  2. VPN and Proxy Challenges: Users can bypass geographic restrictions using VPNs or proxy servers. Some VPN services include headers like X-Forwarded-For or X-Real-IP that indicate the original client IP, many do not for privacy reasons These headers can be easily spoofed and are unreliable method to detect the geolocation.

  3. Performance Overhead: ModSecurity and WAF in general inspects every HTTP request in real-time. This inspection process adds latency to each request

  4. Maintenance Requirements: WAFs are critical components of securing web applications. Therefore, they must be kept uptodate, and the GeoIP databases need periodic updates and tuned for false positive. Log files require higher storage and regular rotation and monitoring.

Submission

Submit a PDF document containing screenshots that demonstrate your completed work.

Extra Credit

Configure Apache to serve a custom 403 page that tells users the webpage is not available in their country.