16 Nov 2023
Most organizations only hire a dedicated security role once they're at dozens, if not hundreds, of engineers.
By default, this leaves the security of web applications in the hands of the development team.
This article gives developers a mental framework for improving their web application securifty. It focuses on how to consider Web Application Firewalls as they are far and away the number one category of security tool used to defend web apps from attack.
Frustratingly, the spectrum of what people call a WAF goes from "paste these dozen commands into your .htaccess" file to massive global networks of interconnected data centers that proxy all of your traffic.
This makes answering questions like "Should we use a WAF?" or even "Don't we already have a WAF?" difficult to answer, as it's incredibly easy to either make assumptions or talk past each other.
If you're reading this and thinking: "Well, we've survived this far without a WAF, why should we add one now?" There are three main reasons most developers add a WAF to their application stack:
This last category is the most common as it's a catch-all for hundreds of different, more niche reasons like absurd levels of bot traffic, unending vulnerability scanners, or just a general sense of unease at the state of the internet.
Our industry is in a weird state where if we described the process to an outsider, they'd be horrified.
Consider if the following question came from your CFO, an investor, or a customer:
Question: "So you looked in our webserver's logs, saw that every day there were thousands of probes and exploitation attempts against the server and you didn't do anything about it?"
Answer: "Well, most of the requests were looking for Wordpress paths, and we don't use Wordpress, so we figured it was fine."
Which is the standard way of handling things today. Most developers figure that they're not going to make a mistake that will allow an attacker to compromise their application, so they don't worry about it.
The core feature of all WAFs is that they make it easier to block web requests.
In the prior sentence, "easier" is doing a lot of work, as you could theoretically handle much of what a WAF does in your web server or application framework.
The volume and ease of implementing the blocking rules are where theory smashes into reality. You might consider it reasonable to block a few dozen IP addresses in your web server, but it's functionally unworkable to tweak your web server config to block more advanced rules/requests like:
Bottomline: WAFs aren't magic; they are just tools that make implementing some or all of these rules into your web application easier.
Blocking is the easy part of a WAF. The hard part is figuring out what to block.
There's a feedback loop between:
In traditional systems, even if you're lucky enough to have all the above in place, you still have to identify patterns in your logging system manually, turn around and export/copy those into your WAF, monitor for changes, and then rinse and repeat that process ad infinitum.
Wafris is designed to make this process easier by holding a sliding window (by default, the last 24 hours) of request data that you can interactively filter and review from which it becomes apparent what to block.
A common critique of WAFs is that "we already do that" - an excellent example is SQL Injection (SQLi) protection.
The argument goes that a WAF is redundant since "we already use prepared statements" or "we already use an ORM," so a WAF is redundant.
These types of arguments only cover half the story. A better framework for considering this is splitting the security jobs (responsibilities) into Application and Operational categories.
Web application security covers the code correctness side of the equation.
Generally speaking, if you can quickly test for it in your development environment, it's an application security issue.
Having multiple systems working to prevent SQLi (and other application attacks) is a good thing, as it means that if one system fails, you have another method that can catch the attack.
Developers are also (shockingly) human, and humans make mistakes. They sometimes check in extra files in their git commits, publicly store files they didn't realize were sensitive, or forget to do things under pressure.
A WAF provides a safety net for these easily made mistakes.
This layered architecture is formally called "Defense in Depth" and is a core concept of modern secure applications.
Further, it's important to note that application security is a moving target. New vulnerabilities are discovered daily, and having a WAF lets you react more quickly than the upgrade, test, and deploy cycle typically would.
Operational security covers the "how do we run this thing" side. This includes things like:
Put another way, it's the "we don't already do that" side of the equation, which is why it's often overlooked.
An excellent example of the difference between application and operational security is the recent 23andMe data breach:
No vulnerabilities in the 23andMe application stack were exploited. Still, the attackers could exploit operational loopholes like the lack of behavioral detection, rate limiting, and bot detection to perform the attack.
To be 100% clear, this is not a criticism of 23andMe; many, if not most, significant services are vulnerable to these operational exploits. Their honest and open communications about the incident are a model for handling these types of attacks.
And bad news for the humans reading this: humans make mistakes.
So, yes, you may have a framework that does SQLi protection, but what if you have a legacy app that doesn't? Or what if you have a framework that does SQLi protection but includes a library that doesn't?
You need multiple layers of protection, and a WAF is one of those layers.
WAFs fall into three categories: Ruleset, DNS Based, and In-App.
Rulesets WAFs have a very specific scope of functionality. They operate by applying a set of predefined rules (regexes) to HTTP requests. These rules identify and mitigate common web application vulnerabilities such as SQL injection, cross-site scripting (XSS), and remote file inclusion (RFI).
This is a big step up from not having any protection, but they squarely cover existing application framework security features and by design don't provide any operational security functionality. For example, they don't provide any way to block an IP address or rate limit requests.
Further, it can be tricky to handle both false positives (legitimate requests that are blocked by the WAF) and false negatives (new threats that have emerged since the ruleset was created).
The other forms of WAF are supersets of the functionality that ruleset WAFs provide.
DNS-based WAFs operate at the DNS level as a secure gateway for all incoming traffic to your web application. They work by routing incoming traffic through their network of servers and filtering out malicious requests based on various factors such as IP reputation, geolocation, and behavioral analysis. DNS-based WAFs are particularly effective at mitigating DDoS attacks, as they can absorb and distribute the traffic across their network.
They incorporate rulesets and some traffic analysis but are generally configured for all web applications and don't provide the same level of customization as in-app WAFs.
The major downside to DNS-based WAFs is (predictably) DNS. Depending on the provider, they may require you to change your DNS provider, which can be a non-starter for many organizations.
It is also the case that all of your traffic will be routed through the WAF; while it's primarily transient this can still be a security issue for some organizations as it complicates compliance and auditing.
Expedited WAF (linked above) doesn't require you to give them full DNS control, only a single DNS record change.
In-app WAFs are integrated directly into your web framework or ingress application. Since they're local to your web application servers, they're typically much faster and provide higher customization and control than other types of WAFs. They can be tailored to your application's specific needs and characteristics, allowing for more precise and effective protection.
They offer modular rulesets that you can enable or disable as needed, and they can be configured to block requests based on various factors such as IP reputation, geolocation, and behavioral analysis.
Wafris is an in-app WAF that provides a simple, easy-to-use interface for creating and managing WAF rules and policies backed by Redis.
We are biased in thinking that every web app needs a WAF. This viewpoint stems from spending several years working with developers to protect sites actively under attack and seeing the difference a WAF can make.
Our frustrations with the existing WAFs on the market led us to build Wafris, the WAF of our dreams: a WAF made from the ground up to help developers protect their web applications.