Mirror of: http://ha.ckers.org/xss.html

XSS cheatsheet
Esp: for filter evasion


By RSnake

Note from the author: If you don't know how XSS (Cross Site Scripting) works, this page probably won't help you. This page is for people who already understand the basics of XSS but want a deep understanding of the nuances regarding filter evasion. This page will also not show you how to mitigate these risks or how to write the actual cookie/credential stealing portion of the attack. It will simply show the underlying attack vectors and you can infer the rest. I may add mitigation techniques or other forms of XSS like button/form overwriting later, since I haven't found many good resources on this topic thus far.

XSS (Cross Site Scripting):
    XSS locator (inject this string, view source and search for "XSS", if you see "<XSS" verses "&lt;XSS" it may be vulnerable):


    Normal XSS:


    No quotes and no semicolon:


    Case insensitive XSS attack vector:


    HTML entities:


    UTF-8 Unicode encoding (almost all of these encoding methods work only in Internet Explorer and Opera):


    Long UTF-8 Unicode encoding without semicolons (this is often effective in XSS that attempts to look for &#XX, since most people don't know about padding - up to 7 numeric charachters total). This is also useful against people who decode against strings like $tmp_string =~ s/.*\&#(\d+);.*/$1/; which incorrectly assumes a semicolon is required to terminate a html encoded string (I've seen this in the wild):


    Hex encoding without semicolons (this is also a viable attack against the above string $tmp_string =~ s/.*\&#(\d+);.*/$1/; which assumes that there is a numeric charachter following the pound symbol - which is not true with hex HTML charachters):


    Embedded tab to break up XSS. This works in IE and Opera. Some websites claim than any of the chars 09-13 (decimal) will work for this attack. That is incorrect. Only 09 (horizontal tab), 10 (newline) and 13 (carriage return) work. See the ascii chart for more details. The following four XSS examples illustrate this vector:


    Embedded newline to break up XSS:


    Embedded carriage return to break up XSS:


    Multiline Injected JS using ASCII carriage returns (same as above only a more extreme example of this XSS vector) these are not spaces just one of the three charachters as described above:

    Okay, I lied, null chars also work as XSS vectors in both IE and older versions of Opera, but not like above, you need to inject them directly using something like Burp Proxy or if you want to write your own you can either use vim (^V@ will produce a null) or the following program to generate it into a text file. Okay, I lied again, older versions of Opera (circa 7.11 on Windows) were vulnerable to one additional char 173 (the soft hypen control char). But the null char %00 is much more useful and helped me bypass certain real world filters with a variation on this example:

    Spaces before the JavaScript in images for XSS (this is useful if the pattern match doesn't take into account spaces in the word "javascript:" -which is correct since that won't render- and makes the false assumption that you can't have a space between the quote and the "javascript:" keyword):


    XSS with no single quotes or double quotes or semicolons:


    BODY image:


    BODY tag (I like this method because it doesn't require using any variants of "javascript:" or "<SCRIPT..." to accomplish the XSS attack):


    Event Handlers that can be used in similar XSS attacks to the one above (this is the most comprehensive list on the net, at the time of this writing):


    IMG Dynsrc (works in IE):


    Input Dynsrc and Src (This XSS works in IE but remember to use TYPE="image"):


    BGSOUND (works in IE):


    & JS includes (works in Netscape 4.x):


    Layer (also only works in Netscape 4.x)


    Style sheet:


    VBscript in an image:


    Mocha (older versions of Netscape only):


    Livescript (older versions of Netscape only):


    Meta (the odd thing about meta refresh is that it doesn't send a referrer in the header on IE, Firefox, Netscape or Opera - so it can be used for certain types of attacks where you need to get rid of referring URLs):


    Iframe (if iframes are allowed there are a lot of other XSS problems as well):


    Frame (frames have the same sorts of XSS problems as iframes):


    Tables (who would have thought tables were XSS targets... except me, of course):


    Div background-image:


    Div behavior for *.htc XSS exploits (Netscape only):


    Div expression (IE only) - a variant of this was effective against a real world XSS filter using a newline between the colon and "expression":


    STYLE tags with broken up JavaScript for XSS:


    IMG STYLE with expression (this is really a hybrid of the above XSS vectors, but it really does show how hard STYLE tags can be to parse apart):

    STYLE tag (Netscape only):


    STYLE tag using background-image:


    STYLE tag using background:


    BASE tag. You need the // to comment out the next charachters so you won't get a JS 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:


    OBJECT tag (IE only, but if they allow objects, you can also inject virus payloads to infect the users, etc. and same with the APPLET tag):


    Using an OBJECT tag you can imbed a flash movie that contains XSS:


    Using the above action script inside flash can obfuscate your XSS vector:


    XML:


    Assuming you can only write into the <IMG SRC="$yourinput"> field and the string "javascript:" is recursively removed:


    Assuming you can only fit in a few charachters and it filters against ".js" you can rename your JavaScript file to an image as an XSS vector:


    Half open HTML/JS XSS vector. This is useful as a vector because it doesn't require a close angle bracket. This assumes there is ANY HTML tags below where you are injecting your XSS. Even though there is no close ">" tag the tags below it will close it. Two notes 1) this does mess up the HTML, depending on what HTML is beneath it and 2) you definitely need the quotes or it will cause your JavaScript to fail as the next line it will try to render will be something like "</TABLE>". As a side note, this was also affective against a real world XSS filter I came accross using an open ended IFRAME tag instead of an IMG tag:


    SSI (Server Side Includes) requires SSI to be installed on the server:

    IMG Embedded commands - this works when the webpage where this is injected (like a web-board) is behind password protection and that password protection works with other commands on the same domain. This can be used to delete users, add users (if the user who visits the page is an administrator), send credentials elsewhere, etc.... This is one of the lesser used but most useful XSS vectors:



XSS using HTML quote encapsulation:
    This was tested in IE, your mileage may vary. For performing XSS on sites that allow "<SCRIPT>" but don't allow "<SCRIPT SRC..." by way of a regex filter "/<script[^>]+src/i":


    For performing XSS on sites that allow "<SCRIPT>" but don't allow "&ltscript src..." by way of a regex filter "/<script((\s+\w+(\s*=\s*(?:"(.)*?"|'(.)*?'|[^'">\s]+))?)+\s*|\s*)src/i" (this is an important one, because I've seen this regex in the wild):


    Another XSS to evade the same filter, "/<script((\s+\w+(\s*=\s*(?:"(.)*?"|'(.)*?'|[^'">\s]+))?)+\s*|\s*)src/i":


    Yet another XSS to evade the same filter, "/<script((\s+\w+(\s*=\s*(?:"(.)*?"|'(.)*?'|[^'">\s]+))?)+\s*|\s*)src/i". I know I said I wasn't goint to discuss mitigation techniques but the only thing I've seen work for this XSS example if you still want to allow <SCRIPT> tags but not remote script is a state machine (and of course there are other ways to get around this if they allow <SCRIPT> tags):


    This XSS still worries me, as it would be nearly impossible to stop this without blocking all active content:




URL string evasion (assuming "http://www.google.com/" is programmatically disallowed):
    IP verses hostname:


    URL encoding:


    Protocol resolution bypass (ht:// translates in IE to http:// and there are many others that work with XSS as well, such as htt://, hta://, help://, etc...). This is really handy when space is an issue too (two less charachters can go a long way):


    Removing cnames (when combined with the above URL, removing "www." will save an additional 4 bytes for a total byte savings of 6 for servers that have this set up properly):

    Extra dot for absolute DNS:


    JavaScript link location:


    Content replace as attack vector (assuming "http://www.google.com/" is programmatically replaced with nothing). I actually used a similar attack vector against a real world XSS filter by using the conversion filter itself to help create the attack vector (IE: "java&#x26;#x09;script:" was converted into "java&#x09;script:", which renders in IE and Opera):


Charachter Encoding:
    All the possible combinations of the charachter "<" in HTML and JavaScript (standards are great, aren't they?):




Character Encoding Calculator

ASCII Text:

Hex Value:
    URL:


    HTML (with semicolons):
Decimal Value:
    HTML (without semicolons):

Base64 Value
    Base64:

Written in vim, and UTF-8 encoded, for her pleasure.
Image theft protection provided by VERO Vault.
All rights reserved, all wrongs observed.
© 1995-2005 RSnake