[DOM based XSS] Or why you should not rely on Cloudflare too much

Foreword

So I found another XSS in a bug bounty program again. The website [redacted.com] is protected by Cloudflare WAF and hence many payloads are filtered. But the website is implemented in an extremely bad way that even Cloudflare can’t protect it.

Just a few days before the day I found this bug, I was telling my colleagues “don’t rely on firewalls / security products too much” during an internal presentation. Now I have a real example to talk about. LOL.

Summary

When I triggered an error on the login page, a parameter called Message is reflected in the body of the html AND a pop-up box (i.e. the value of “Message” is inserted in javascript, right inside alert(“[value_here]”)) without filtering. So I was able to insert anything I like in the script.

Payload:

This is an outdated page. You will now be redirected to our new page"); window.location="https://google.com"//

So we can spoof the users that they are going to an updated webpage and login again. (Redirecting to google for demonstration here)

How did I find it

In fact I was checking their register and sign in function and attempting to find some application flaws. I registered an account using email a@a.com without verifying it and tried to signup with the same email again. Then an error message is popped up:

And I found that the URL became

https://redacted.com/Secure/Login.aspx?UserID=a@a.com&ReturnUrl=&Message=The E-Mail Address entered (a@a.com) is already on file. If this is your correct e-mail address, you may sign in as an existing customer.

Exactly the same of that in the pop-up box and the text shown on the top:

So the message maybe reflected in the body of the HTML. I tried the straight forward <script>alert(1)</script> payload.

Then I got this:

Oops. Cloudflare. But that was in my expectation 🙂 . The payload is for dummies.

I noticed that the message is inserted in javascript directly:

So what we can do is closing the double quote and the parentheses like

alert("something_here");evil_script_here// ")

Then we can do anything we want.

Good firewalls can’t save bad code. That’s it. Thanks for reading.