Master of XSS WAF Bypass - Part 1
Hello, I'm Meydi. I have been working in bug bounty for a year and a half, and over the past year, my main focus has been on client-side bugs and I have earned more than $25k in bounties through XSS
In this part, my focus is on situations where you can inject tags or event handlers. Without Any Time Wasting: Let's Dive Straight into this blog
Differences Between Browser and WAF Parsing:
Parsing Differences
1. Browser Parsing: Browsers parse HTML and construct the DOM according to the HTML specification. They handle complex and nested elements, tolerate errors, and apply their own corrections to malformed HTML to ensure the best possible rendering.
2. WAF Parsing: WAFs, on the other hand, often use simpler parsing mechanisms to inspect and filter requests. They may rely on pattern matching (e.g., regex) to detect potentially harmful content. This simplified parsing doesn't always follow the same robust rules as a browser's HTML parser.
Bypassing WAFs: The discrepancy between the comprehensive parsing done by browsers and the pattern-based or rule-based parsing by WAFs can indeed be exploited. Attackers can craft payloads that appear harmless to a WAF's parser but are interpreted differently when processed by a browser. For example, using encoding tricks or malformed attributes can cause the WAF to miss malicious payloads while the browser successfully executes them.
Overall, while the statement holds true, the effectiveness and methods of bypassing WAFs depend on the specific WAF's capabilities and the attacker's understanding of both browser behavior and WAF parsing logic.
To bypass WAFs, the first step is understanding regex and how it works. When the browser tries to parse HTML and construct the DOM, it follows a set of rules that differ from those used by WAFs. This difference is why WAFs can be bypassed quite easily.
If we can inject a tag or be inside a tag and add an event handler, we can proceed step by step with the bypass:
How to Escape Double Quotes (or Single Quotes):
There are several ways, and I will try to cover them all. But first, let me explain how a WAF works. Initially, the WAF attempts to decode your packet. This decoding includes:
HTML decode
URL decode
Hex decode
Unicode decode
etc ..
After decoding, it validates whether you are using dangerous event handlers or not. To bypass a WAF, we need to make our payload appear harmless after decoding.
To begin payload injection, it is better to proceed step by step and understand how the WAF operates. Below, you can see several methods with explanations and images:
Another method is to use escape characters, like this:
Handling Cases Where Only Double Quotes Can Be Used:
But sometimes, we cannot use anything except (double quote or single quote). So, how do we bypass this:
Handling Cases Where Parentheses Cannot Be Used:
Sometimes, we are unable to use open and close parentheses. Here's the method I use for bypassing:func(payload/*%0a*/) or func(payload/*%250a*/)
The following payload is an example I used to trigger alert(origin):
<details open="\u0022x="ontoggle="x=atob;z=x('YWxlcnQob3JpZ2luKQ');meydi=top;n=`ev`;meydi[n+'al'](z)">
I may publish another part to explain other sections or provide more details. Follow me on Twitter to stay updated on my future articles if you enjoyed this one.
Subscribe to my newsletter
Read articles from meydi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by