Since the time bug bounties have started, a lot of security vulnerabilities can be seen reported. From the college students to Hard Core Security Researchers, all researchers have been into it. Cross-site scripting or XSS is one such type of security flaw which is very frequently reported as this can be found much more easily than other flaws. But wait, are you sure this can be found easily always? Well, we disagree.
Most testers use two payloads, i.e., “><img src=aa onerror=alert(1);> and <script>alert(1)</script>; and try them out at most of the injection points. If you are also following the same approach, then you are likely to find XSS in most of conditions, but not in ALL of them. What about those which do not lie in this category (say the application has got a filter, or say they encode some characters).
So instead of just passing random payloads, it’s pretty obvious to first understand where and how the payloads are getting reflected (if any). It simply means, if you can understand the request and response properly, you can be the champion. So we will be talking about the “approach for bypassing XSS filters” in this article.
Here we will mention some of the unique XSS vulnerabilities we found recently.
This is one which I loved personally. While testing an application there were five columns on the EDIT profile page and all were vulnerable to improper sanitization. All the payloads were getting reflected in Attribute of input tag, however the only problem with all of them was they were not allowing more than 14 characters in each field. As I started with the following:
Successfully injected and complete the input tag and displayed “aaaa” on the page. So I injected:
Injected successfully but didn’t executed my script due to length based filtration and page was tampered. Tried several other payloads, and then got to know that only 14 characters were allowed. Suddenly thought of comments and along with partial payloads. So I broke my payload into three parts and then injected in three columns simultaneously:
Part 2: */alert(1);/*
Part 3: */</script><!—
So once injected in HTML page, it was something like
<input value=””>script>/* BLAH BLAH BLAH */alert(1);/* BLAH BLAH BLAH */</script><!—
While testing a FILE upload functionality, I intercepted the request using burp. While the contents of file were being transferred as an XML, the inputs were getting echoed on the page which was used to show the progress of the upload. So I tried to include a CDATA into the XML file and thought of including my XSS payload in between the CDATA. This worked fine and I got an XSS. The response where XSS was being echoed was something like below.
The payload used in this scenario was :
While testing a .NET (.aspx) application which was sanitizing almost all the inputs (both falling in attributes as well as in main HTML). There was a module to modify the USER Details. At first I tried with the following string as the first name value:
Page redirected to Error Page, thought <script> might be blocked. So passed this:
Page redirected to Error Page, thought “tags” might be blocked. And as this string was not passing in any attribute so only way to inject HTML or JS required a TAG. So I tried with full width encoding. Here is a complete chart which you can refer for the same. http://www.unicode.org/charts/PDF/UFF00.pdf . Using this I encoded the right angular bracket (>) and left angular bracket (<) to %uff1e and %uff1c respectively. Resulting payload with XSS script:
This time payload got injected but did not got executed. When I analyzed the source code, got to see that due to length based filtering some part of payload was not injected which was in fact defacing the site. So I made another account. This time I thought to encode half of the payload instead of encoding the complete payload. So I encoded (<) to %uff1c but left (>) as it is. This reduced the length of my payload by 22 characters. Therefore I passed:
And voila, this worked and I was able to report an XSS.
The place where my values were injecting was:
var a=(“bbbbb”, “abcdef”);’ — where bbbb was my injection point.
Obviously, there was no point of injecting “><img src stuff. So at the very first I tried to take the things out of the variable, then function and then execute.
aaa”aaa, “abcdef”);’ alert(1);
This got blocked as “SPACES” were not allowed in the input. So I used “plus sign”. And the page got redirected to an error page.
This didn’t work as “comma” was not allowed. Next:
It still didn’t work. I wondered why it was not working. Then deeply analyzed the code, and realized, I was supposed to close the string, so I entered this:
aaa”aaa);’+alert(1); var c=”
Again there was something wrong; string was not getting closed properly. At this point, I was able to inject the payload easily but was unable to execute it properly. So next:
And finally a pop up. This payload actually, closed the string, took my value out of the function, executed the alert(1), made another variable in the same manner as previous one was made (in which values were getting injected), and then left the double quote opened so as to complete the actual string in the page.
So the main point which I wanted to explain from this article is, don’t just “BRUTE FORCE” the payloads, instead try to analyze the injection point and then make the payload.
This one I found on one of the BUG BOUNTY sites and was also out of my favourite ones. While exploring the site, I got to see a Word-press based blog being employed which moreover was using a theme which used an older version of “timthumb.php” and to the surprise this was not properly patched. Developers have patched the XSS in the file but partially.
When I tried
The page echoed only aaaa aa and <bb> was sanitized in an awesome manner. Then I tried RFI and tried to include a PHP file on the server (by first uploading to a free web host), but the page came up with an error that PHP files are not allowed. Again proper validation. Everything was fine until I tried with a JS file.
When I uploaded JS file on my free web hosting account and then included it in timthumb with the following URL:
the page said:
File type not supported: data/www/wp_blog/wp-content/themes/yamidoo_pro/scripts
Where abcd/xyz/pqr was the internal path disclosure and the MD5 was the hash of the (abcdef.my3gb.com/flicker.com/shubham.js)
Being very obvious, I modified the URL to http://example.com/wp-content/themes/yamidoo_pro/scripts/temp/17ba317694138461350bacd42cb37908.js
And BOOM. My js file was here. But as we know PHP files were not supported, I tried with .cgi and .inc, both went waste as the file started getting downloaded instead of executing there.
And named the file shubham.html
When I included the file to the example.com using the following URL:
Again the error came
Unable to Open Image:
So modified the URL to
And as this was a page with malicious script, I got three Message boxes and confirmed the XSS on the site. As this was a stored XSS, and complete page can be made with whatever malicious script, this was patched within a day by the site to which I reported.
So for the time being, we have included 5 case studies in the article which we encountered while testing for bugs. We tried to convey some of the approaches for finding Cross Site Scripting vulnerabilities and bypassing filters.
Hope you enjoyed the article and learnt something. Comments and suggestions are most welcome.