~ 7 min read
Bypassing the AWS WAF protection with an 8KB bullet
A Web Application Firewall (WAF) is a very common resource or a service that infrastructure and application administrators rely on to protect applications facing the Internet. A WAF sits in front of a web application facing the Internet and inspects the HTTP traffic that is reaching the perimeter to ensure nothing suspicious or malicious goes through.
Most WAFs allow you to edit and create custom rules of inspection that can be used for granular analysis of the incoming HTTP traffic and block even the most sophisticated attack payloads.
This blogpost talks about a documented limitation within the AWS WAF when inspecting a request body, what particular configurations are vulnerable and how an attacker can take advantage of this limitation.
The 8KB Limitation
The AWS WAF is a popular service in the long list of security tools that AWS provides. The AWS WAF essentially plays the role of a gatekeeper for Web Applications running across various compute resources. There are a whole bunch of free managed rules that you can configure to protect your application against threats like SQL Injection, SSRF, XSS etc. The rule creation feature allows you to create customized rules for your application and business needs.
You can use the AWS WAF to protect applications on CloudFront, the Application Load Balancer, API Gateway for your REST APIs, AWS Lambda and AWS AppSync for GraphQL APIs. Regardless of the use case, the AWS WAF nicely fits into the AWS compute infrastructure ensuring attackers don’t attack your web application thus ensuring data and infrastructure security.
There is a caveat however. AWS WAF only inspects the first 8,192 bytes (8 KB) of the web request body. If a web request body is larger than 8KB, the packet is forwarded to the web server resource for processing!
If you have ever tried to create a rule set within the AWS WAF, you would have been greeted with the following warning.
This limitation is well documented and presented via multiple warning messages every time you are creating a ruleset that contains a body inspection rule.
What does the limitation mean in the real world?
Imagine you have a web application running on an EC2 instance. A load balancer sits in front of the EC2 instance. All web traffic trying to reach the web application from the Internet goes through AWS WAF before reaching the load balancer.
Now, if the web application is vulnerable to a vulnerability that an Internet located attacker can exploit, most SREs, application and infrastructure administrators would presume the AWS WAF to thwart the attacker.
Now the WAF functions as advertised for any web traffic that is less than 8KB in size, but as soon as the attack traffic exceeds 8KB, a malicious payload will go right through the AWS WAF, the load balancer and will be processed by the application.
Here’s an example of an application hosted on AWS as described in the setup above. This application accepts a domain or a web URL as user input and attempts to fetch and show the HTTP response headers that the supplied input sends when a web request is made to it.
The server side logic for this functionality is built using the cURL command. The user input is passed to cURL as is, without any sanitisation. This results in a vulnerability called Command Injection which allows the user to enter their own commands by using special characters to separate the server side cURL command and their own command.
For example due to the vulnerability, entering the input kloudle.com;id will cause the server to fetch the HTTP headers for kloudle.com and then run the id command.
However, because we have the AWS WAF configured with rules to block exactly these types of attacks, the attack fails.
The AWS WAF sends us a Forbidden message as our HTTP request was not allowed to reach the web application.
Making the attack work
Given that the attack payload was sent via a POST request and that we were blocked, as an attacker, we can safely assume that a rule that inspects the HTTP request body is in place. Using the knowledge of the 8KB limitation, we can now craft an attack that can be used to bypass the AWS WAF and reach the web application.
We use an interception proxy to add extra parameters to the request body to make its size larger than 8KB. This causes the AWS WAF to ignore the request and forwards it to the web application.
It is important to note that the attack payload must come after 8KB of junk data in the request body for the bypass to work.
The response now contains the HTTP headers for kloudle.com and the output of the id command, showing that the AWS WAF was bypassed because the request body is larger than 8KB.
How do you fix this?
Now that we understand the limitation and how attackers can abuse this to still attack your protected web applications, how do we go about fixing this? If we look at the warning that AWS presents when adding a rule that will inspect the request body, they recommend that a size constraint rule be run before the body inspection to block requests with body size greater than 8 KBs that a size constraint rule must be added alongside other rules to ensure packets larger than 8KB.
A SizeConstraint rule can be added to the ACL to perform actions on the request when a size criteria is met. AWS supports multiple criteria that can be used to work with web requests that are less than, equal to or greater than a specified number of bytes. Adding a SizeConstraint rule to block web packets of size equal to or more than 8192 bytes will ensure any malicious attempts to breach the WAF are denied. The downside to having this rule in place is that legitimate requests like file uploads or POST requests containing large VIEWSTATE data in .NET applications may also get blocked. In such cases, you may want to set the SizeConstraint rule action to Count instead of Block and evaluate if the application does receive any web request body larger than 8KB.
Most AWS admins often rely on the Core rule set managed rule group which contains a
SizeRestrictions_BODY rule that does block requests with request body size that is at most 8,192 bytes, however as this can lead to restricted functionality in applications that do work with larger request body sizes, the rule action is set to
Count instead of
Block, resulting in this same scenario to play out.
Look out for a detailed fix about this on Kloudle Academy today!
Update: Osama Elnaggar has also done an in-depth analysis about this limitation. You can read more about this here.
Attackers are constantly researching new ways of bypassing protection mechanisms that SREs and infrastructure owners impose. Although documented by AWS, the 8KB limitation is not well known and worse, the implications of the limitations are not well understood. In the event when a new team member joins, they inherit the infrastructure and nuances such as these, and are often unaware of the potential dangers they can create. Some organisations even choose to accept these risks as part of their infrastructure design and proceed to believe the most secure configuration is already in place.
This blog post showed what the 8KB limitation looks like in an AWS WAF configuration and how an attacker can abuse it to attack and exploit vulnerabilities on web applications behind the AWS WAF. The damage that an attacker can cause is only limited by the vulnerability that can be exploited, like in the case of the recently disclosed Log4J set of vulnerabilities, it could mean a complete compromise of the server instances from the Internet.