查看文章 |
From http://dev.opera.com/articles/view/opera-javascript-for-hackers-1/ ======================================================================================== JavaScript for hackersBy garethheyes · 22 Apr, 2009 IntroductionI love to use JavaScript in unexpected ways, to create code that looks like it shouldn't work but does, or produces some unexpected behavior. This may sound trivial, but the results I've found lead to some very useful techniques. Each of the techniques described can be used for XSS filter evasion, which was my original intention when developing them. However, learning such JavaScript can dramatically increase your knowledge of the language, helping you become better at cleaning up input, and increase web application security. So read on and enjoy my weird and wonderful JavaScript hacks. RegExp replace can execute codeWhen using regular expressions with
This results in
But as you can see in the first example in this section, instead of a user defined function we are executing a native To see how this is used in a XSS context, imagine we have an unfiltered
Notice I use If I put all the code together and show you the output of the page it is easier to understand what is going on: Page output:
The above code is common in analytics scripts where your search string is stored by an advertising company. You often don't see these scripts but if you view the source of a web page you'll find that they are a regular occurrence; forums are another place where they are prevalent. "YOUR INPUT" is the string you have control of; this is also referred to as DOM based XSS if the input isn't filtered correctly. Input: alert(1)".replace(/.+/,eval)//
Resulting output: <script>somevariableUnfiltered="alert(1)".replace(/.+/,eval)//"</script>
Notice the single line comment used to remove the trailing quote. Unicode escapesAlthough it's not possible to use parentheses when escaping unicode characters, you can escape the name of the function being called, for example:
This calls Mixing and matching unicode escapes is possible with normal characters; the example below demonstrates this:
You can also include them in strings and even evaluate them using The example below shows how to use unicode escapes that are evaluated and split into separate parts:
By avoiding normal function names like JavaScript parser engineJavaScript is a very dynamic language. It can execute a surprising amount of code that at first glance doesn't look valid, however once you know how the parsers work, you begin to understand the logic behind it. JavaScript doesn't know the result of a function until it is executed, and obviously it has to call the function to return the variable type. This leads to an interesting quirk - for example, if the returning function doesn't return a valid value for the code block, a syntax error will occur after the execution of the function. What does this mean in English? Well, code speaks louder than words - check this example out
The alert function executes and returns undefined but by that time it is too late - the decrement operator is expecting a number and therefore raises an error. Here's a few more valid examples that don't raise errors but are interesting nevertheless.
You might think the above examples are pointless but in fact they offer great insight into how Javascript works. Once you understand the small details the bigger picture becomes clear and the way that your code executes can help you understand how the parser works. I find these sort of examples useful when tracking down syntax errors and DOM based XSS, and exploiting XSS Filters. Throw, Delete what?You can use the
Even though you'd think it couldn't possibly work, it's possible to call
Here are a few more examples
At first glance you'd think that they would raise a syntax error but when examining the code further it sorta makes sense. The parser finds a variable assignment first within a array, performs the assignment and then deletes the array. Likewise the delete is performed after a function call because it needs to know the result of the function before it can delete the returned object, even if it is null. Again these examples have been used to defeat XSS filters because they are often trying to match valid syntax and they don't expect the obscure nature of the code. You should consider such examples when programming your application data validation. Global objects are statementsIn certain instances of XSS filter evasion, it can be useful to send English-like text hidden within a vector. Clever systems like PHPIDS use English and vector comparisons to determine if a request is an attack or not, so it is a useful way to test these systems. Using global objects/functions on their own can produce English-like code blocks. In fact, on the sla.ckers security forum we had a little game to produce English-like sentences in JavaScript. To get an idea of how it works, check out the following example:
I coined the name Javascriptlish because it's possible to produce some crazy looking code:
We use the regular expression Next we use a label called Getters/Setters funWhen Firefox added the custom syntax for setters it enabled some interesting XSS vectors that didn't use parentheses. Opera doesn't support a custom syntax yet - this is good from a security point of view but not from a JavaScript hacker's perspective. Opera does however support the standard
In case you're not aware of setters/getters, the example above creates a setter for the global variable Location allows url encodingThe
Combining them with unicode escapes can hide strings quite nicely:
The first example works because the URL bar in Opera accepts urlencoded strings - you can hide JavaScript syntax by url encoding it. This is useful because when it is passed within a XSS vector you can double url encode it to help further with filter evasion. The second example combines the first technique with the unicode escape technique mentioned previously. So when you decode the string it results in the unicode representation of Hackvertor: Your second brainAs a JavaScript hacker I couldn't possibly remember every single encoding method that's possible with JavaScript, so I decided to create a open source tool to do the hard work for me. In the last example the string is double encoded, which can sometimes make it hard to understand. Using my Hackvertor tool makes it a piece of cake and it works nicely in Opera too. Hackvertor works by using tags to perform multiple levels of conversion; this is similar to HTML tags but it runs code instead of changing the display of the containing text. It converts from the innermost tag outwards, eg to convert the last vector it url decodes and then decodes the unicode escapes, which results in
|