Test Your Security Equipment’s Ability to Block JavaScript Obfuscations
by Ricky LawshaeThese days, many companies have locked down security for their servers pretty tightly. That has made the bad guys look for softer targets to hack into, especially Web browsers on client machines — such as the computer you’re reading this on. JavaScript, which is ubiquitous on Web pages, is a key vector for these attacks. As security devices get better about detecting malicious JavaScript, hackers are getting more clever about hiding these attacks with layers of obfuscations. We’ve just updated our own security attacks so you can test your equipment to find out how well it stops attacks that use JavaScript evasion techniques.
This is obviously an important topic. In fact, just recently Metasploit revamped its JavaScript obfuscation library to include nicer function and variable name randomization, as well as some new string and number mutations. This work was great, and I felt like we could take it much further — and now we have. In this post and a follow-up, I’ll illustrate some of the JavaScript techniques that we’ve recently released.
Obfuscating JavaScript, Step-by-Step
Take a look at the following simple code example:
It is very easy to tell exactly what the code is doing. Now take a look at what that same code example might look like after being passed through our obfuscator:
This code evaluates the same way as the code in the first example when run in the browser, but it has become much more difficult to read and analyze. Let’s step through it piece by piece.
One way to disguise strings in JavaScript is through base conversion. Using toString(32) you can convert a number into a string using the characters [1-9a-v]. So 720094129..toString(32<<0) evaluates to “length,” which makes the code snippet -~-~'Tg'["length"].
The next thing to notice here is that in JavaScript, as in many other languages, a tilde character in front of any number N equates to -(N + 1). Therefore, -~N is the same as N + 1. So that gives us 'Tg'["length"] + 2, which means that -~-~'Tg'[720094129..toString(32<<0)+""] equates to the number 4.
We now know that -~-~'Tg'[720094129..toString(32<<0)+""] equals 4 and can therefore figure out that -~-~-~'hUYbdq'[720094129..toString(16<<1)+""] equals 9, so the first part of this statement is 4 > 9. The ? after the conditional indicates that this is a ternary statement, which means that whatever is after the question mark but before the colon will be returned if the statement is true, and whatever is after the colon will be returned if the statement is false. Since 4 > 9 is false, all that matters is what is after the colon, which is 18306744..toString(1<<5)+"", or “hello”.
Once again using the base conversion technique, we can see that 11189117..toString(8<<2) is the same as the string “alert”. FfnEDHmYwcm={}.valueOf,FFnEDHmYwcm() is a trick that I picked up from the sla.ckers.org forums that results in a reference to the window object. I can then use the object[“method”] form of calling functions, and what we end up with is window[“alert”]. By doing this, I am able to hide calls to functions that would normally be indicative of malicious JavaScript code, such as “unescape” and “eval”.
As you can see, the limitless possibilities make it extremely difficult, if not impossible, to implement signature-based methods for detecting and blocking pages containing malicious JavaScript code. These methods for obfuscating our code are already plenty evil, but — as we will discuss in Part Two — it gets much, much worse. Stay tuned!
Related Posts:
- Three DDoS Flood Attacks
- Simulate Spear Phishing Attacks to Validate Enterprise Network Security
- Creating the Next Stuxnet
- Using the New to Refactor the Old: Port Scanner Edition




