The HAProxy Enterprise WAF

The HAProxy Enterprise WAF, with support for ModSecurity rulesets, protects your web applications from sophisticated, Layer 7 threats left unhandled by network firewalls.

Data breaches. Loss of consumer confidence. An endless cycle of companies being compromised. Not just fly-by-night, sketchy websites either. Large companies—companies that you’d think would do better—are being caught without reliable security measures in place.

There’s a reason that one of the most consulted security guides, the OWASP Top 10, is a list of web application security risks: Applications that can be accessed online provide opportunities for attackers the most often. They typically listen on open ports like 80 and 443, ports that must be open to the Internet to allow access to the company’s website and services. Unlike traditional services like FTP and SSH, it’s not as though you can just raise the drawbridge and shut out traffic to those ports. A network firewall, which operates at the TCP layer to restrict access to your networks, isn’t the right tool to prevent these types of threats.

Web Application Firewalls were created specifically as a countermeasure to stop attacks against web applications. The HAProxy Enterprise WAF supports three modes: SQLi / XSS mode, safelist-only mode, and ModSecurity mode. We will cover ModSecurity mode in this blog post. The ModSecurity rulesets can detect and stop SQL injection attacks (SQLi), cross-site scripting (XSS), remote file inclusion (RFI), remote code execution (RCE), and other hostile actions. WAFs are tools that don’t just make the Internet safer for your customers. They also allow you to prevent disclosing information about your applications, such as the operating system and installed packages, by analyzing the responses as well. They make doing business online viable.

In this blog post, you’ll learn more about the problems a WAF solves and get a look at how the HAProxy Enterprise WAF provides an essential layer of defense.

A Specific Countermeasure

We’ve enjoyed the benefits of network firewalls since the 1980s. They allow IT admins to filter traffic between networks based on any of the information in the network protocol headers: source IP address, source port, destination IP address, and destination port. Don’t want someone to access your database from the Internet? Run it on a non-routable internal network or put a firewall in front of it and close off access to the outside world. In fact, common practice is to block everything by default and only punch a hole through for specific applications.

Next-generation firewalls (NGFW) took this to the next level. They often include deep packet inspection (DPI) and intrusion detection systems (IDS) that allows the firewall to open up IP packets and look at their contents, even up to the application layer. For instance, an IDS might analyze packets to discover what type of messages they contain. Is this FTP? VoIP? HTTP traffic from video streaming or social media websites? Or is it a virus, matched against a set of known signatures?

Traditional network firewalls and NGFWs don’t adequately secure against the unique attacks aimed at web applications, though. For one thing, more and more online communication is being encrypted with SSL/TLS. An NGFW would have to decrypt this traffic as a man-in-the-middle to inspect it. Another problem is the level of sophistication of modern-day, application-layer attacks. What may seem like a reasonable HTTP request may actually be an attempt at SQL injection.

Web application firewalls are built with the intent of recognizing and preventing attacks against websites and web applications. The HAProxy Enterprise WAF with ModSecurity rulesets fills in the gaps left by other types of firewalls, protecting against the vulnerabilities listed in the OWASP Top 10. Really, network firewalls and WAFs complement each other well. It’s always good to have multiple layers of security, which, as it happens, is a core strength of our entire platform.

Routine Scanning

First things first. You need a way to evaluate the security of your application. There are a number of web security scanners and tools out there including Acunetix, Nessus, and Burp Suite. We’ll use one called OWASP Zed Attack Proxy (ZAP), which you can download and install onto Windows, Linux, or Mac. I’ve found ZAP to be one of the easier scanners to use and it’s able to detect an impressive range of vulnerabilities. Also, go ahead and install sqlmap, which is a pen testing tool laser-focused on finding web pages susceptible to SQL injection.

Routinely scanning your applications will help to make sure that flaws aren’t slipping past you into production. It creates a baseline against which you can compare software releases. Injecting security into your regular development pipeline helps to keep everyone sharp. As you build out your product’s features, you’ll know early on when a vulnerability has been introduced.

We’re going to demonstrate the types of threats that a scanner will detect and ultimately that a WAF will stop. To do that, we need an application that has some known flaws baked in. The Damn Vulnerable Web Application (DVWA) is perfect for this because it’s been built to be, well, vulnerable.

Download the sample project from GitHub. It uses Terraform to launch DVWA into a virtual machine running on AWS EC2. In front of it, we have an instance of the HAProxy Enterprise load balancer, which you can run as a free trial and which comes with the WAF. Note that you must subscribe to the HAProxy Enterprise software on the AWS AMI webpage before launching the Terraform script.

The load balancer is exposed via a public IP address that’s assigned by AWS after Terraform has run and created the VM. Remember to call terraform destroy to delete all resources from AWS afterwards so that you aren’t billed for extra usage. When setting up the project with Terraform, you should set the my_source_ip variable to your own IP address. That way, the site is only accessible to you. More information can be found in the git repository’s README file.

Once you have it up and running, open the site in a browser.

the dvwa login

The DVWA login

Log in with the credentials admin and password. I didn’t find a way to change these in DVWA, but that’s more reason to lock down access to only your own IP address. Once in, click the Create / Reset Database button to initialize the site’s MySQL database. At this point, there is no WAF protecting the site. It’s wide open to security exploits.

Let’s run sqlmap and see what it finds. When you log into DVWA, it places a cookie in your browser called PHPSESSID that tells the site that you’re a logged-in user. So that sqlmap can bypass the login screen and scan the site, it needs the value of this cookie. Open your browser’s Developers Tools and view the site’s cookies on the Network tab. Then, find the PHPSESSID cookie and copy its value.

In the following command, we pass the --cookie parameter to sqlmap with the value of the PHPSESSID cookie. You should also set security to low in the cookie, as shown. This tells DVWA to not use its own built-in, practice WAF. Replace the session ID and IP address of the site with your own values:

$ python /usr/bin/sqlmap \
--random-agent \
--cookie="PHPSESSID={YOUR SESSION ID};security=low" \
--dbs \
--url="http://{YOUR SITE IP}/vulnerabilities/sqli/?id=&Submit=Submit" \
-p id

This command probes the /vulnerabilities/sqli page for SQL injection flaws, substituting various strings for the id parameter in the URL, looking for a way in. When it’s successful, it will gain access to the MySQL instance and enumerate the databases it finds, as shown below:

[09:24:38] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian
web application technology: Apache 2.4.25
back-end DBMS: MySQL 5.0.12
[09:24:38] [INFO] fetching database names
available databases [2]:
[*] dvwa
[*] information_schema

As you can see, sqlmap was able to find information about the website’s databases and list out sensitive information. That’s certainly a security weakness! You’ll see in the next section how the HAProxy Enterprise WAF stops this from happening.

Next, let’s use the ZAP scanner to find pages susceptible to cross-site scripting. You can use ZAP to scan for other sorts of vulnerabilities, too, if you like. Open ZAP and, from the right-hand panel, choose Manual Explore and then Launch Browser.

launch zap

Launch ZAP

In the browser that opens, go to the DVWA website and log in. Using Launch Browser helps ZAP to learn the layout of the site. You can also have it crawl the site on its own, but that isn’t as effective. To demonstrate a vulnerability, we’ll focus on cross-site scripting (XSS) by going to the XSS (Reflected) page and typing a value into the What’s your name? field. Then click Submit. After that, you can close the browser window.

dvwa website

The DVWA website

When you go back to ZAP, you’ll see that it has filled in the address of the DVWA website under Sites in the left-hand panel. Expand that folder and then expand the vulnerabilities folder. You should see that it captured two GET requests for the /vulnerabilities/xss_r page: GET:xss_r and GET:xss_r(name).

target a page

Target a page

Right-click on GET:xss_r(name) and choose Attack > Active Scan. ZAP will inspect that page, trying various strings for the name URL parameter. After it finishes, open the Alerts tab at the bottom and you should see that a Cross Site Scripting (Reflected) vulnerability was discovered.

vulnerabilities were discovered

Vulnerabilities were discovered

If sqlmap and ZAP can find these vulnerabilities, we had better beef up our defenses before an attacker exploits them. In the next section, you’ll see how to set up the WAF module in HAProxy Enterprise to add a wall of protection.

HAProxy Enterprise WAF

The native WAF module utilizes ModSecurity to classify and detect malicious behavior. Our version of ModSecurity has been uniquely hardened against certain types of denial of service attacks, which has made it impervious to exploits like CVE-2020-15598.

You can add your own attack detection rules, but you get immediate access to the OWASP ModSecurity Core Rule Set (CRS), which protects against many common threats. Log into your HAProxy Enterprise load balancer so that you can enable the WAF module. If you’re following along with the sample project, then you can use SSH to log into the VM via its public IP address. Use the haproxy_demo.pem file as your SSH key:

$ ssh -i ./haproxy_demo.pem ubuntu@[HAPROXY_IP_ADDRESS]

You need to download the CRS. There’s a script that will take care of this for you. Simply run the following command and the files will be downloaded to the /etc/hapee-2.2/modsec.rules.d directory:

$ sudo /opt/hapee-2.2/bin/hapee-lb-modsecurity-getcrs

Next, go to /etc/hapee-2.2 and edit the hapee-lb.cfg file with your text editor (i.e. vi or nano). Add the following module-load directive to the global section:


Also, add a filter directive to the frontend section to enable protection for that proxy. Here’s what it looks like:

frontend fe_main
filter modsecurity owasp_crs rules-file /etc/hapee-2.2/modsec.rules.d/lb-modsecurity.conf

Then save the file and reload the load balancer services with the systemctl command:

$ sudo systemctl reload hapee-2.2-lb

At this point, the WAF is in detection-only mode. That means that it will classify attacks as it sees them and write warnings to the file /var/log/modsec_audit.log. However, it will not block any requests. To turn on blocking, edit the file /etc/hapee-2.2/modsec.rules.d/modsecurity.conf. Near the beginning, change SecRuleEngine DetectionOnly to SecRuleEngine On. Then reload the load balancer service again.

Did you know?

The modsec_audit.log file should be disabled in production use, since writing to disk will hinder performance.

Retesting With WAF Protection

Now that it is configured, a quick test with sqlmap shows that the WAF is working (remember to get the value of the PHPSESSID cookie):

$ python /usr/bin/sqlmap \
--random-agent \
--cookie="PHPSESSID={SESSION ID};security=low" \
--dbs \
--url="http://{SITE IP}/vulnerabilities/sqli/?id=&Submit=Submit" \
-p id
[09:51:40] [WARNING] GET parameter 'id' is not injectable
[09:51:40] [CRITICAL] all tested parameters appear to be not injectable.
[09:51:40] [WARNING] HTTP error codes detected during run:
403 (Forbidden) - 1 times

Here, even though we gave it a page that we know is susceptible to SQL injection, it wasn’t able to find it. That’s because the WAF is blocking requests that seem malicious with 403 Forbidden responses.

Did you know?

When sqlmap runs it caches the results. So, if you ran it while the WAF was in detection-only mode, you’ll want to delete the cache. It can be found under your user directory, ~/.sqlmap/output.

Stopping sqlmap from gaining access to the DVWA MySQL database is no small accomplishment! The tool scans for half a dozen types of relational databases and throws a barrage of injection attacks at its target. Yet, not a single one got through.

What you may find is that ModSecurity can be too aggressive, triggering false positives and blocking legitimate users. If this is the first time you’ve used it, test it for a while in the detection-only mode. Then you can determine which rules are right for your application and traffic, adding exceptions for those that are not or adjusting the severity levels of the rules. Just don’t disable it so much that the WAF loses its effectiveness!

Next, run ZAP again now that the WAF is enabled. Using the same steps as before, scan the XSS (Reflected) page for cross-site scripting vulnerabilities. Or, if you’re feeling adventurous, try browsing around the rest of the site to map out more paths for ZAP. Then start an Active Scan against the vulnerabilities path.

the waf protected vulnerabilities

The WAF protected vulnerabilities

The WAF rejects many of the suspicious requests with 403 Forbidden responses. This definitely strengthens your security posture. Remember, this was a website purposely built to be insecure. Your own applications will, no doubt, have more safeguards. However, it’s never easy to catch all of the potential pitfalls and the HAProxy Enterprise WAF will create an essential layer of defense.

In an upcoming release of HAProxy Enterprise, you will be able to configure ModSecurity to defer its decision making to HAProxy Enterprise. This will give you a wider range of options for how you deal with suspicious clients, beyond the blocking behavior of the WAF. ModSecurity will set variables, which the load balancer will be able to see, and action can be decided by ACL statements.

acl waf_blocked var(txn.owasp_crs.block) -m bool
http-request send-challenge ... if waf_blocked

For example, you might show the client a Javascript challenge if they’re flagged as potentially malicious. Subscribe to our blog to be alerted when this functionality becomes available.


In this post, we demonstrated the need for a web application firewall to protect you from threats like SQL injection and cross-site scripting. A WAF can filter out malicious behavior before it gets to your application, even defending against threats before you become aware of them. It’s important to routinely scan for vulnerabilities and to share the responsibility for security with your entire team.

The HAProxy Enterprise WAF has three modes. In this article, we explored the ModSecurity mode, which protects your web applications from common attacks. Interested in learning more about HAProxy Enterprise and all it has to offer? Contact us to learn more! Want to know when content like this is published? Subscribe to our blog or follow us on Twitter. You can also join the conversation on Slack!

Subscribe to our blog. Get the latest release updates, tutorials, and deep-dives from HAProxy experts.