XSS WAF & Character limitation bypass like a boss

Hello fellow Hackers!
I am sitting in my room for the last 3 days due to the coronavirus outbreak worldwide and feeling really bored. So I thought why not do a write-up of what I promised really long ago 🀭. A few months back in My Tweet I shared a way to bypass XSS WAF & Character limitation what I found on a private bug bounty site. Today I will share more technical details about that bypass. Hope you guys will enjoy it πŸ˜‡

Back in 2019 I was testing a web application that allows a user to create a photo album and upload photos in it and the interface looks like the below screenshot:

Application Interface πŸ€”
Application Interface πŸ€”

Also, there is an option to rename images when I click on Edit, So normally any researcher will test for XSS here as there is a way to change the photo name. So I changed the photo name to xsstest'">{{7*7}}

Then I noticed the following things –

  • There is 15 character limitation in that input so I was able to inject xsstest'">{{7*7 these characters.
  • All special characters were being escaped properly.
  • And at last, I was being redirected to /error.aspx?code=500 when I tried to load that album again due to WAF and I have to rename the image to xsstest then I was able to load the album again.

It looks like this input is well protected form XSS attacks. Then I start playing with other available options and connected Burp Suit tools with my browser and keep it open to capture all background requests in HTTP History. Then when I was going through HTTP History tab and one background request endpoint caught my attention what looks like https://subdomain.company.com/ajax/generateImageList.ashx?json={albums:[{“id“:”“,”value”:”on”}]}. This request was for album Slideshow option and that endpoint page source was:

<a href="https://image-link.com/image.jpg" title="xsstest" rel="lightbox

Look at the title attribute value what is our image name in that album. So again I renamed my picture name to xsstest'”> and again checked ajax/generateImageList.ashx page source and this time it was –

<a href="https://image-link.com/image.jpg" title="xsstest'">" rel="lightbox

So in this new generateImageList.ashx endpoint –

  • User’s input is not being escaped properly.
  • No WAF detection.

But we still have the 15 character limitation what makes this xss useless. The smallest xss payload we can think of for this scenario is “oncut=”alert() Which will result a blank popup when we Press CTRL+X on Windows & COMMAND+X on OS X on keyboard:

<a href="https://image-link.com/image.jpg" title=""oncut="alert()" rel="lightbox
Blank Popup πŸ˜ͺ
Blank Popup πŸ˜ͺ

I tried all possible way to bypass this character limitation and was unable to do it. I stopped testing here and saved about this endpoint in my To do list note to take a look here when I again test this asset. After about seven months I again started testing this asset and again working on this endpoint. Now noticed that I can upload multiple photos on album and by selecting all photos of album the Slideshow option request endpoint changes to https://subdomain.company.com/ajax/generateAlbumImageList.ashx?json={albums:[{“id“:”“,”value”:”on”}]} and that page source is:

<a href="https://image-link.com/image.jpg" title="xsstest'">" rel="lightbox
">84**00000</a><a href="https://image-link.com/image.jpg" title="xsstest'">" rel="lightbox

So now we have multiple injections here. So why not upload 5 pictures in the album and use My Tweet mentioned payload?
Payload :

  • 1st Injection: */</script><!--
  • 2nd Injection:*/.domain)/*xxx
  • 3rd Injection: */(document/*xx
  • 4th Injection: */prompt/*xxxxx
  • 5th Injection: "><script>/*xss

Page source after final injection become:

<a href="https://image-link.com/image.jpg" title=""><script>/*xss" rel="lightbox
">84**00000</a><a href="https://image-link.com/image.jpg" title="*/prompt/*xxxxx" rel="lightbox
">84**00001</a><a href="https://image-link.com/image.jpg" title="*/(document/*xx" rel="lightbox
">84**00002</a><a href="https://image-link.com/image.jpg" title="*/.domain)/*xxx" rel="lightbox
">84**00003</a><a href="https://image-link.com/image.jpg" title="*/</script><!--" rel="lightbox

Now visiting https://subdomain.company.com/ajax/generateAlbumImageList.ashx?json={albums:[{“id“:”“,”value”:”on”}]} will execute the payload we used-

Popup Boom 😎πŸ”₯
Popup Boom 😎πŸ”₯

Now you may have a question why I used x character multiple times in the 2nd to 5th payload? The answer is in album images are sorting based on the name length + When it was uploaded. So I used x character multiple times to make all image name length the same, so that when I upload images it sort based on image upload time.

Hope you guys enjoyed this one.


4 Responses

Leave a Reply

Your email address will not be published. Required fields are marked *