1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Class Protector |
5
|
|
|
*/ |
6
|
|
|
class Protector |
7
|
|
|
{ |
8
|
|
|
public $mydirname; |
9
|
|
|
|
10
|
|
|
public $_conn; |
11
|
|
|
public $_conf = array(); |
12
|
|
|
public $_conf_serialized = ''; |
13
|
|
|
|
14
|
|
|
public $_bad_globals = array(); |
15
|
|
|
|
16
|
|
|
public $message = ''; |
17
|
|
|
public $warning = false; |
18
|
|
|
public $error = false; |
19
|
|
|
public $_doubtful_requests = array(); |
20
|
|
|
public $_bigumbrella_doubtfuls = array(); |
21
|
|
|
|
22
|
|
|
public $_dblayertrap_doubtfuls = array(); |
23
|
|
|
public $_dblayertrap_doubtful_needles = array( |
24
|
|
|
'information_schema', |
25
|
|
|
'select', |
26
|
|
|
"'", |
27
|
|
|
'"'); |
28
|
|
|
|
29
|
|
|
public $_logged = false; |
30
|
|
|
|
31
|
|
|
public $_done_badext = false; |
32
|
|
|
public $_done_intval = false; |
33
|
|
|
public $_done_dotdot = false; |
34
|
|
|
public $_done_nullbyte = false; |
35
|
|
|
public $_done_contami = false; |
36
|
|
|
public $_done_isocom = false; |
37
|
|
|
public $_done_union = false; |
38
|
|
|
public $_done_dos = false; |
39
|
|
|
|
40
|
|
|
public $_safe_badext = true; |
41
|
|
|
public $_safe_contami = true; |
42
|
|
|
public $_safe_isocom = true; |
43
|
|
|
public $_safe_union = true; |
44
|
|
|
|
45
|
|
|
public $_spamcount_uri = 0; |
46
|
|
|
|
47
|
|
|
public $_should_be_banned_time0 = false; |
48
|
|
|
public $_should_be_banned = false; |
49
|
|
|
|
50
|
|
|
public $_dos_stage; |
51
|
|
|
|
52
|
|
|
public $ip_matched_info; |
53
|
|
|
|
54
|
|
|
public $last_error_type = 'UNKNOWN'; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Constructor |
58
|
|
|
*/ |
59
|
|
|
protected function __construct() |
60
|
|
|
{ |
61
|
|
|
$this->mydirname = 'protector'; |
62
|
|
|
|
63
|
|
|
// Preferences from configs/cache |
64
|
|
|
$this->_conf_serialized = @file_get_contents($this->get_filepath4confighcache()); |
65
|
|
|
$this->_conf = @unserialize($this->_conf_serialized); |
66
|
|
|
if (empty($this->_conf)) { |
67
|
|
|
$this->_conf = array(); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
if (!empty($this->_conf['global_disabled'])) { |
71
|
|
|
return; |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
// die if PHP_SELF XSS found (disabled in 2.53) |
75
|
|
|
// if ( preg_match( '/[<>\'";\n ]/' , @$_SERVER['PHP_SELF'] ) ) { |
76
|
|
|
// $this->message .= "Invalid PHP_SELF '{$_SERVER['PHP_SELF']}' found.\n" ; |
77
|
|
|
// $this->output_log( 'PHP_SELF XSS' ) ; |
78
|
|
|
// die( 'invalid PHP_SELF' ) ; |
79
|
|
|
// } |
80
|
|
|
|
81
|
|
|
// sanitize against PHP_SELF/PATH_INFO XSS (disabled in 3.33) |
82
|
|
|
// $_SERVER['PHP_SELF'] = strtr( @$_SERVER['PHP_SELF'] , array( '<' => '%3C' , '>' => '%3E' , "'" => '%27' , '"' => '%22' ) ) ; |
83
|
|
|
// if( ! empty( $_SERVER['PATH_INFO'] ) ) $_SERVER['PATH_INFO'] = strtr( @$_SERVER['PATH_INFO'] , array( '<' => '%3C' , '>' => '%3E' , "'" => '%27' , '"' => '%22' ) ) ; |
84
|
|
|
|
85
|
|
|
$this->_bad_globals = array( |
86
|
|
|
'GLOBALS', |
87
|
|
|
'_SESSION', |
88
|
|
|
'HTTP_SESSION_VARS', |
89
|
|
|
'_GET', |
90
|
|
|
'HTTP_GET_VARS', |
91
|
|
|
'_POST', |
92
|
|
|
'HTTP_POST_VARS', |
93
|
|
|
'_COOKIE', |
94
|
|
|
'HTTP_COOKIE_VARS', |
95
|
|
|
'_SERVER', |
96
|
|
|
'HTTP_SERVER_VARS', |
97
|
|
|
'_REQUEST', |
98
|
|
|
'_ENV', |
99
|
|
|
'_FILES', |
100
|
|
|
'xoopsDB', |
101
|
|
|
'xoopsUser', |
102
|
|
|
'xoopsUserId', |
103
|
|
|
'xoopsUserGroups', |
104
|
|
|
'xoopsUserIsAdmin', |
105
|
|
|
'xoopsConfig', |
106
|
|
|
'xoopsOption', |
107
|
|
|
'xoopsModule', |
108
|
|
|
'xoopsModuleConfig'); |
109
|
|
|
|
110
|
|
|
$this->_initial_recursive($_GET, 'G'); |
111
|
|
|
$this->_initial_recursive($_POST, 'P'); |
112
|
|
|
$this->_initial_recursive($_COOKIE, 'C'); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* @param $val |
117
|
|
|
* @param $key |
118
|
|
|
*/ |
119
|
|
|
protected function _initial_recursive($val, $key) |
120
|
|
|
{ |
121
|
|
|
if (is_array($val)) { |
122
|
|
|
foreach ($val as $subkey => $subval) { |
123
|
|
|
// check bad globals |
124
|
|
View Code Duplication |
if (in_array($subkey, $this->_bad_globals, true)) { |
125
|
|
|
$this->message .= "Attempt to inject '$subkey' was found.\n"; |
126
|
|
|
$this->_safe_contami = false; |
127
|
|
|
$this->last_error_type = 'CONTAMI'; |
128
|
|
|
} |
129
|
|
|
$this->_initial_recursive($subval, $key . '_' . base64_encode($subkey)); |
130
|
|
|
} |
131
|
|
|
} else { |
132
|
|
|
// check nullbyte attack |
133
|
|
|
if (@$this->_conf['san_nullbyte'] && false !== strpos($val, chr(0))) { |
134
|
|
|
$val = str_replace(chr(0), ' ', $val); |
135
|
|
|
$this->replace_doubtful($key, $val); |
136
|
|
|
$this->message .= "Injecting Null-byte '$val' found.\n"; |
137
|
|
|
$this->output_log('NullByte', 0, false, 32); |
138
|
|
|
// $this->purge() ; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
// register as doubtful requests against SQL Injections |
142
|
|
|
if (preg_match('?[\s\'"`/]?', $val)) { |
143
|
|
|
$this->_doubtful_requests["$key"] = $val; |
144
|
|
|
} |
145
|
|
|
} |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* @return Protector |
150
|
|
|
*/ |
151
|
|
|
public static function getInstance() |
152
|
|
|
{ |
153
|
|
|
static $instance; |
154
|
|
|
if (!isset($instance)) { |
155
|
|
|
$instance = new Protector(); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
return $instance; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* @return bool |
163
|
|
|
*/ |
164
|
|
|
public function updateConfFromDb() |
165
|
|
|
{ |
166
|
|
|
$constpref = '_MI_' . strtoupper($this->mydirname); |
167
|
|
|
|
168
|
|
|
if (empty($this->_conn)) { |
169
|
|
|
return false; |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
$result = @mysqli_query($this->_conn, 'SELECT conf_name,conf_value FROM ' . XOOPS_DB_PREFIX . "_config WHERE conf_title like '" . $constpref . "%'"); |
173
|
|
|
if (!$result || mysqli_num_rows($result) < 5) { |
174
|
|
|
return false; |
175
|
|
|
} |
176
|
|
|
$db_conf = array(); |
177
|
|
|
while (list($key, $val) = mysqli_fetch_row($result)) { |
178
|
|
|
$db_conf[$key] = $val; |
179
|
|
|
} |
180
|
|
|
$db_conf_serialized = serialize($db_conf); |
181
|
|
|
|
182
|
|
|
// update config cache |
183
|
|
|
if ($db_conf_serialized != $this->_conf_serialized) { |
184
|
|
|
$fp = fopen($this->get_filepath4confighcache(), 'w'); |
185
|
|
|
fwrite($fp, $db_conf_serialized); |
186
|
|
|
fclose($fp); |
187
|
|
|
$this->_conf = $db_conf; |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
return true; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* @param $conn |
195
|
|
|
*/ |
196
|
|
|
public function setConn($conn) |
197
|
|
|
{ |
198
|
|
|
$this->_conn = $conn; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* @return array |
203
|
|
|
*/ |
204
|
|
|
public function getConf() |
205
|
|
|
{ |
206
|
|
|
return $this->_conf; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* @param bool $redirect_to_top |
211
|
|
|
*/ |
212
|
|
|
public function purge($redirect_to_top = false) |
213
|
|
|
{ |
214
|
|
|
// clear all session values |
215
|
|
|
if (isset($_SESSION)) { |
216
|
|
|
foreach ($_SESSION as $key => $val) { |
217
|
|
|
$_SESSION[$key] = ''; |
218
|
|
|
if (isset($GLOBALS[$key])) { |
219
|
|
|
$GLOBALS[$key] = ''; |
220
|
|
|
} |
221
|
|
|
} |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
if (!headers_sent()) { |
225
|
|
|
// clear typical session id of PHP |
226
|
|
|
setcookie('PHPSESSID', '', time() - 3600, '/', '', 0); |
227
|
|
|
if (isset($_COOKIE[session_name()])) { |
228
|
|
|
setcookie(session_name(), '', time() - 3600, '/', '', 0); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
// clear autologin cookie |
232
|
|
|
$xoops_cookie_path = defined('XOOPS_COOKIE_PATH') ? XOOPS_COOKIE_PATH : preg_replace('?http://[^/]+(/.*)$?', "$1", XOOPS_URL); |
233
|
|
|
if ($xoops_cookie_path == XOOPS_URL) { |
234
|
|
|
$xoops_cookie_path = '/'; |
235
|
|
|
} |
236
|
|
|
setcookie('autologin_uname', '', time() - 3600, $xoops_cookie_path, '', 0); |
237
|
|
|
setcookie('autologin_pass', '', time() - 3600, $xoops_cookie_path, '', 0); |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
if ($redirect_to_top) { |
241
|
|
|
header('Location: ' . XOOPS_URL . '/'); |
242
|
|
|
exit; |
|
|
|
|
243
|
|
|
} else { |
244
|
|
|
$ret = $this->call_filter('prepurge_exit'); |
245
|
|
|
if ($ret == false) { |
246
|
|
|
die('Protector detects attacking actions'); |
|
|
|
|
247
|
|
|
} |
248
|
|
|
} |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* @param string $type |
253
|
|
|
* @param int $uid |
254
|
|
|
* @param bool $unique_check |
255
|
|
|
* @param int $level |
256
|
|
|
* |
257
|
|
|
* @return bool |
|
|
|
|
258
|
|
|
*/ |
259
|
|
|
public function output_log($type = 'UNKNOWN', $uid = 0, $unique_check = false, $level = 1) |
260
|
|
|
{ |
261
|
|
|
if ($this->_logged) { |
262
|
|
|
return true; |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
if (!($this->_conf['log_level'] & $level)) { |
266
|
|
|
return true; |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
if (empty($this->_conn)) { |
270
|
|
|
$this->_conn = @mysqli_connect(XOOPS_DB_HOST, XOOPS_DB_USER, XOOPS_DB_PASS); |
271
|
|
|
if (!$this->_conn) { |
272
|
|
|
die('db connection failed.'); |
|
|
|
|
273
|
|
|
} |
274
|
|
|
if (!mysqli_select_db($this->_conn, XOOPS_DB_NAME)) { |
275
|
|
|
die('db selection failed.'); |
|
|
|
|
276
|
|
|
} |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
$ip = \Xmf\IPAddress::fromRequest()->asReadable(); |
280
|
|
|
$agent = @$_SERVER['HTTP_USER_AGENT']; |
281
|
|
|
|
282
|
|
|
if ($unique_check) { |
283
|
|
|
$result = mysqli_query($this->_conn, 'SELECT ip,type FROM ' . XOOPS_DB_PREFIX . '_' . $this->mydirname . '_log ORDER BY timestamp DESC LIMIT 1'); |
284
|
|
|
list($last_ip, $last_type) = mysqli_fetch_row($result); |
285
|
|
|
if ($last_ip == $ip && $last_type == $type) { |
286
|
|
|
$this->_logged = true; |
287
|
|
|
|
288
|
|
|
return true; |
289
|
|
|
} |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
mysqli_query( |
293
|
|
|
$this->_conn, |
294
|
|
|
'INSERT INTO ' . XOOPS_DB_PREFIX . '_' . $this->mydirname . "_log SET ip='" |
295
|
|
|
. mysqli_real_escape_string($this->_conn, $ip) . "',agent='" |
296
|
|
|
. mysqli_real_escape_string($this->_conn, $agent) . "',type='" |
297
|
|
|
. mysqli_real_escape_string($this->_conn, $type) . "',description='" |
298
|
|
|
. mysqli_real_escape_string($this->_conn, $this->message) . "',uid='" |
299
|
|
|
. (int)$uid . "',timestamp=NOW()" |
300
|
|
|
); |
301
|
|
|
$this->_logged = true; |
302
|
|
|
|
303
|
|
|
return true; |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
/** |
307
|
|
|
* @param $expire |
308
|
|
|
* |
309
|
|
|
* @return bool |
310
|
|
|
*/ |
311
|
|
View Code Duplication |
public function write_file_bwlimit($expire) |
312
|
|
|
{ |
313
|
|
|
$expire = min((int)$expire, time() + 300); |
314
|
|
|
|
315
|
|
|
$fp = @fopen($this->get_filepath4bwlimit(), 'w'); |
316
|
|
|
if ($fp) { |
317
|
|
|
@flock($fp, LOCK_EX); |
|
|
|
|
318
|
|
|
fwrite($fp, $expire . "\n"); |
319
|
|
|
@flock($fp, LOCK_UN); |
|
|
|
|
320
|
|
|
fclose($fp); |
321
|
|
|
|
322
|
|
|
return true; |
323
|
|
|
} else { |
324
|
|
|
return false; |
325
|
|
|
} |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
/** |
329
|
|
|
* @return mixed |
330
|
|
|
*/ |
331
|
|
|
public function get_bwlimit() |
332
|
|
|
{ |
333
|
|
|
list($expire) = @file(Protector::get_filepath4bwlimit()); |
|
|
|
|
334
|
|
|
$expire = min((int)$expire, time() + 300); |
335
|
|
|
|
336
|
|
|
return $expire; |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
/** |
340
|
|
|
* @return string |
341
|
|
|
*/ |
342
|
|
|
public static function get_filepath4bwlimit() |
343
|
|
|
{ |
344
|
|
|
return XOOPS_TRUST_PATH . '/modules/protector/configs/bwlimit' . substr(md5(XOOPS_ROOT_PATH . XOOPS_DB_USER . XOOPS_DB_PREFIX), 0, 6); |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
/** |
348
|
|
|
* @param $bad_ips |
349
|
|
|
* |
350
|
|
|
* @return bool |
351
|
|
|
*/ |
352
|
|
View Code Duplication |
public function write_file_badips($bad_ips) |
353
|
|
|
{ |
354
|
|
|
asort($bad_ips); |
355
|
|
|
|
356
|
|
|
$fp = @fopen($this->get_filepath4badips(), 'w'); |
357
|
|
|
if ($fp) { |
358
|
|
|
@flock($fp, LOCK_EX); |
|
|
|
|
359
|
|
|
fwrite($fp, serialize($bad_ips) . "\n"); |
360
|
|
|
@flock($fp, LOCK_UN); |
|
|
|
|
361
|
|
|
fclose($fp); |
362
|
|
|
|
363
|
|
|
return true; |
364
|
|
|
} else { |
365
|
|
|
return false; |
366
|
|
|
} |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
/** |
370
|
|
|
* @param int $jailed_time |
371
|
|
|
* @param null $ip |
372
|
|
|
* |
373
|
|
|
* @return bool |
374
|
|
|
*/ |
375
|
|
|
public function register_bad_ips($jailed_time = 0, $ip = null) |
376
|
|
|
{ |
377
|
|
|
if (empty($ip)) { |
378
|
|
|
$ip = \Xmf\IPAddress::fromRequest()->asReadable(); |
379
|
|
|
} |
380
|
|
|
if (empty($ip)) { |
381
|
|
|
return false; |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
$bad_ips = $this->get_bad_ips(true); |
385
|
|
|
$bad_ips[$ip] = $jailed_time ?: 0x7fffffff; |
386
|
|
|
|
387
|
|
|
return $this->write_file_badips($bad_ips); |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
/** |
391
|
|
|
* @param bool $with_jailed_time |
392
|
|
|
* |
393
|
|
|
* @return array|mixed |
394
|
|
|
*/ |
395
|
|
|
public function get_bad_ips($with_jailed_time = false) |
396
|
|
|
{ |
397
|
|
|
list($bad_ips_serialized) = @file(Protector::get_filepath4badips()); |
|
|
|
|
398
|
|
|
$bad_ips = empty($bad_ips_serialized) ? array() : @unserialize($bad_ips_serialized); |
399
|
|
|
if (!is_array($bad_ips) || isset($bad_ips[0])) { |
400
|
|
|
$bad_ips = array(); |
401
|
|
|
} |
402
|
|
|
|
403
|
|
|
// expire jailed_time |
404
|
|
|
$pos = 0; |
405
|
|
|
foreach ($bad_ips as $bad_ip => $jailed_time) { |
406
|
|
|
if ($jailed_time >= time()) { |
407
|
|
|
break; |
408
|
|
|
} |
409
|
|
|
++$pos; |
410
|
|
|
} |
411
|
|
|
$bad_ips = array_slice($bad_ips, $pos); |
412
|
|
|
|
413
|
|
|
if ($with_jailed_time) { |
414
|
|
|
return $bad_ips; |
415
|
|
|
} else { |
416
|
|
|
return array_keys($bad_ips); |
417
|
|
|
} |
418
|
|
|
} |
419
|
|
|
|
420
|
|
|
/** |
421
|
|
|
* @return string |
422
|
|
|
*/ |
423
|
|
|
public static function get_filepath4badips() |
424
|
|
|
{ |
425
|
|
|
return XOOPS_TRUST_PATH . '/modules/protector/configs/badips' . substr(md5(XOOPS_ROOT_PATH . XOOPS_DB_USER . XOOPS_DB_PREFIX), 0, 6); |
426
|
|
|
} |
427
|
|
|
|
428
|
|
|
/** |
429
|
|
|
* @param bool $with_info |
430
|
|
|
* |
431
|
|
|
* @return array|mixed |
432
|
|
|
*/ |
433
|
|
|
public function get_group1_ips($with_info = false) |
434
|
|
|
{ |
435
|
|
|
list($group1_ips_serialized) = @file(Protector::get_filepath4group1ips()); |
|
|
|
|
436
|
|
|
$group1_ips = empty($group1_ips_serialized) ? array() : @unserialize($group1_ips_serialized); |
437
|
|
|
if (!is_array($group1_ips)) { |
438
|
|
|
$group1_ips = array(); |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
if ($with_info) { |
442
|
|
|
$group1_ips = array_flip($group1_ips); |
443
|
|
|
} |
444
|
|
|
|
445
|
|
|
return $group1_ips; |
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
/** |
449
|
|
|
* @return string |
450
|
|
|
*/ |
451
|
|
|
public static function get_filepath4group1ips() |
452
|
|
|
{ |
453
|
|
|
return XOOPS_TRUST_PATH . '/modules/protector/configs/group1ips' . substr(md5(XOOPS_ROOT_PATH . XOOPS_DB_USER . XOOPS_DB_PREFIX), 0, 6); |
454
|
|
|
} |
455
|
|
|
|
456
|
|
|
/** |
457
|
|
|
* @return string |
458
|
|
|
*/ |
459
|
|
|
public function get_filepath4confighcache() |
460
|
|
|
{ |
461
|
|
|
return XOOPS_TRUST_PATH . '/modules/protector/configs/configcache' . substr(md5(XOOPS_ROOT_PATH . XOOPS_DB_USER . XOOPS_DB_PREFIX), 0, 6); |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
/** |
465
|
|
|
* @param $ips |
466
|
|
|
* |
467
|
|
|
* @return bool |
468
|
|
|
*/ |
469
|
|
|
public function ip_match($ips) |
470
|
|
|
{ |
471
|
|
|
$requestIp = \Xmf\IPAddress::fromRequest()->asReadable(); |
472
|
|
|
if (false === $requestIp) { // nothing to match |
473
|
|
|
$this->ip_matched_info = null; |
474
|
|
|
return false; |
475
|
|
|
} |
476
|
|
|
foreach ($ips as $ip => $info) { |
477
|
|
|
if ($ip) { |
478
|
|
|
switch (strtolower(substr($ip, -1))) { |
479
|
|
|
case '.' : |
|
|
|
|
480
|
|
|
case ':' : |
|
|
|
|
481
|
|
|
// foward match |
482
|
|
|
if (substr($requestIp, 0, strlen($ip)) == $ip) { |
483
|
|
|
$this->ip_matched_info = $info; |
484
|
|
|
return true; |
485
|
|
|
} |
486
|
|
|
break; |
487
|
|
|
case '0' : |
|
|
|
|
488
|
|
|
case '1' : |
|
|
|
|
489
|
|
|
case '2' : |
|
|
|
|
490
|
|
|
case '3' : |
|
|
|
|
491
|
|
|
case '4' : |
|
|
|
|
492
|
|
|
case '5' : |
|
|
|
|
493
|
|
|
case '6' : |
|
|
|
|
494
|
|
|
case '7' : |
|
|
|
|
495
|
|
|
case '8' : |
|
|
|
|
496
|
|
|
case '9' : |
|
|
|
|
497
|
|
|
case 'a' : |
|
|
|
|
498
|
|
|
case 'b' : |
|
|
|
|
499
|
|
|
case 'c' : |
|
|
|
|
500
|
|
|
case 'd' : |
|
|
|
|
501
|
|
|
case 'e' : |
|
|
|
|
502
|
|
|
case 'f' : |
|
|
|
|
503
|
|
|
// full match |
504
|
|
|
if ($requestIp == $ip) { |
505
|
|
|
$this->ip_matched_info = $info; |
506
|
|
|
return true; |
507
|
|
|
} |
508
|
|
|
break; |
509
|
|
|
default : |
|
|
|
|
510
|
|
|
// perl regex |
511
|
|
|
if (@preg_match($ip, $requestIp)) { |
512
|
|
|
$this->ip_matched_info = $info; |
513
|
|
|
return true; |
514
|
|
|
} |
515
|
|
|
break; |
516
|
|
|
} |
517
|
|
|
} |
518
|
|
|
} |
519
|
|
|
$this->ip_matched_info = null; |
520
|
|
|
return false; |
521
|
|
|
} |
522
|
|
|
|
523
|
|
|
/** |
524
|
|
|
* @param null $ip |
525
|
|
|
* |
526
|
|
|
* @return bool |
527
|
|
|
*/ |
528
|
|
|
public function deny_by_htaccess($ip = null) |
529
|
|
|
{ |
530
|
|
|
if (empty($ip)) { |
531
|
|
|
$ip = \Xmf\IPAddress::fromRequest()->asReadable(); |
532
|
|
|
} |
533
|
|
|
if (empty($ip)) { |
534
|
|
|
return false; |
535
|
|
|
} |
536
|
|
|
if (!function_exists('file_get_contents')) { |
537
|
|
|
return false; |
538
|
|
|
} |
539
|
|
|
|
540
|
|
|
$target_htaccess = XOOPS_ROOT_PATH . '/.htaccess'; |
541
|
|
|
$backup_htaccess = XOOPS_ROOT_PATH . '/uploads/.htaccess.bak'; |
542
|
|
|
|
543
|
|
|
$ht_body = file_get_contents($target_htaccess); |
544
|
|
|
|
545
|
|
|
// make backup as uploads/.htaccess.bak automatically |
546
|
|
|
if ($ht_body && !file_exists($backup_htaccess)) { |
547
|
|
|
$fw = fopen($backup_htaccess, 'w'); |
548
|
|
|
fwrite($fw, $ht_body); |
549
|
|
|
fclose($fw); |
550
|
|
|
} |
551
|
|
|
|
552
|
|
|
// if .htaccess is broken, restore from backup |
553
|
|
|
if (!$ht_body && file_exists($backup_htaccess)) { |
554
|
|
|
$ht_body = file_get_contents($backup_htaccess); |
555
|
|
|
} |
556
|
|
|
|
557
|
|
|
// new .htaccess |
558
|
|
|
if ($ht_body === false) { |
559
|
|
|
$ht_body = ''; |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
if (preg_match("/^(.*)#PROTECTOR#\s+(DENY FROM .*)\n#PROTECTOR#\n(.*)$/si", $ht_body, $regs)) { |
563
|
|
|
if (substr($regs[2], -strlen($ip)) == $ip) { |
564
|
|
|
return true; |
565
|
|
|
} |
566
|
|
|
$new_ht_body = $regs[1] . "#PROTECTOR#\n" . $regs[2] . " $ip\n#PROTECTOR#\n" . $regs[3]; |
567
|
|
|
} else { |
568
|
|
|
$new_ht_body = "#PROTECTOR#\nDENY FROM $ip\n#PROTECTOR#\n" . $ht_body; |
569
|
|
|
} |
570
|
|
|
|
571
|
|
|
// error_log( "$new_ht_body\n" , 3 , "/tmp/error_log" ) ; |
572
|
|
|
|
573
|
|
|
$fw = fopen($target_htaccess, 'w'); |
574
|
|
|
@flock($fw, LOCK_EX); |
|
|
|
|
575
|
|
|
fwrite($fw, $new_ht_body); |
576
|
|
|
@flock($fw, LOCK_UN); |
|
|
|
|
577
|
|
|
fclose($fw); |
578
|
|
|
|
579
|
|
|
return true; |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
/** |
583
|
|
|
* @return array |
584
|
|
|
*/ |
585
|
|
|
public function getDblayertrapDoubtfuls() |
586
|
|
|
{ |
587
|
|
|
return $this->_dblayertrap_doubtfuls; |
588
|
|
|
} |
589
|
|
|
|
590
|
|
|
/** |
591
|
|
|
* @param $val |
592
|
|
|
* @return null |
593
|
|
|
*/ |
594
|
|
|
protected function _dblayertrap_check_recursive($val) |
595
|
|
|
{ |
596
|
|
|
if (is_array($val)) { |
597
|
|
|
foreach ($val as $subval) { |
598
|
|
|
$this->_dblayertrap_check_recursive($subval); |
599
|
|
|
} |
600
|
|
|
} else { |
601
|
|
|
if (strlen($val) < 6) { |
602
|
|
|
return null; |
603
|
|
|
} |
604
|
|
|
$val = get_magic_quotes_gpc() ? stripslashes($val) : $val; |
605
|
|
|
foreach ($this->_dblayertrap_doubtful_needles as $needle) { |
606
|
|
|
if (false !== stripos($val, $needle)) { |
607
|
|
|
$this->_dblayertrap_doubtfuls[] = $val; |
608
|
|
|
} |
609
|
|
|
} |
610
|
|
|
} |
611
|
|
|
} |
612
|
|
|
|
613
|
|
|
/** |
614
|
|
|
* @param bool $force_override |
615
|
|
|
* @return null |
616
|
|
|
*/ |
617
|
|
|
public function dblayertrap_init($force_override = false) |
618
|
|
|
{ |
619
|
|
|
if (!empty($GLOBALS['xoopsOption']['nocommon']) || defined('_LEGACY_PREVENT_EXEC_COMMON_') || defined('_LEGACY_PREVENT_LOAD_CORE_')) { |
620
|
|
|
return null; |
621
|
|
|
} // skip |
622
|
|
|
|
623
|
|
|
$this->_dblayertrap_doubtfuls = array(); |
624
|
|
|
$this->_dblayertrap_check_recursive($_GET); |
625
|
|
|
$this->_dblayertrap_check_recursive($_POST); |
626
|
|
|
$this->_dblayertrap_check_recursive($_COOKIE); |
627
|
|
|
if (empty($this->_conf['dblayertrap_wo_server'])) { |
628
|
|
|
$this->_dblayertrap_check_recursive($_SERVER); |
629
|
|
|
} |
630
|
|
|
|
631
|
|
|
if (!empty($this->_dblayertrap_doubtfuls) || $force_override) { |
632
|
|
|
@define('XOOPS_DB_ALTERNATIVE', 'ProtectorMysqlDatabase'); |
|
|
|
|
633
|
|
|
require_once dirname(__DIR__) . '/class/ProtectorMysqlDatabase.class.php'; |
634
|
|
|
} |
635
|
|
|
} |
636
|
|
|
|
637
|
|
|
/** |
638
|
|
|
* @param $val |
639
|
|
|
*/ |
640
|
|
|
protected function _bigumbrella_check_recursive($val) |
641
|
|
|
{ |
642
|
|
|
if (is_array($val)) { |
643
|
|
|
foreach ($val as $subval) { |
644
|
|
|
$this->_bigumbrella_check_recursive($subval); |
645
|
|
|
} |
646
|
|
|
} else { |
647
|
|
|
if (preg_match('/[<\'"].{15}/s', $val, $regs)) { |
648
|
|
|
$this->_bigumbrella_doubtfuls[] = $regs[0]; |
649
|
|
|
} |
650
|
|
|
} |
651
|
|
|
} |
652
|
|
|
|
653
|
|
|
public function bigumbrella_init() |
654
|
|
|
{ |
655
|
|
|
$this->_bigumbrella_doubtfuls = array(); |
656
|
|
|
$this->_bigumbrella_check_recursive($_GET); |
657
|
|
|
$this->_bigumbrella_check_recursive(@$_SERVER['PHP_SELF']); |
658
|
|
|
|
659
|
|
|
if (!empty($this->_bigumbrella_doubtfuls)) { |
660
|
|
|
ob_start(array($this, 'bigumbrella_outputcheck')); |
661
|
|
|
} |
662
|
|
|
} |
663
|
|
|
|
664
|
|
|
/** |
665
|
|
|
* @param $s |
666
|
|
|
* |
667
|
|
|
* @return string |
668
|
|
|
*/ |
669
|
|
|
public function bigumbrella_outputcheck($s) |
670
|
|
|
{ |
671
|
|
|
if (defined('BIGUMBRELLA_DISABLED')) { |
672
|
|
|
return $s; |
673
|
|
|
} |
674
|
|
|
|
675
|
|
|
if (function_exists('headers_list')) { |
676
|
|
|
foreach (headers_list() as $header) { |
677
|
|
|
if (false !== stripos($header, 'Content-Type:') && false === stripos($header, 'text/html')) { |
678
|
|
|
return $s; |
679
|
|
|
} |
680
|
|
|
} |
681
|
|
|
} |
682
|
|
|
|
683
|
|
|
if (!is_array($this->_bigumbrella_doubtfuls)) { |
684
|
|
|
return 'bigumbrella injection found.'; |
685
|
|
|
} |
686
|
|
|
|
687
|
|
|
foreach ($this->_bigumbrella_doubtfuls as $doubtful) { |
688
|
|
|
if (false !== strpos($s, $doubtful)) { |
689
|
|
|
return 'XSS found by Protector.'; |
690
|
|
|
} |
691
|
|
|
} |
692
|
|
|
|
693
|
|
|
return $s; |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
/** |
697
|
|
|
* @return bool |
698
|
|
|
*/ |
699
|
|
|
public function intval_allrequestsendid() |
700
|
|
|
{ |
701
|
|
|
global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS; |
|
|
|
|
702
|
|
|
|
703
|
|
|
if ($this->_done_intval) { |
704
|
|
|
return true; |
705
|
|
|
} else { |
706
|
|
|
$this->_done_intval = true; |
707
|
|
|
} |
708
|
|
|
|
709
|
|
View Code Duplication |
foreach ($_GET as $key => $val) { |
710
|
|
|
if (substr($key, -2) === 'id' && !is_array($_GET[$key])) { |
711
|
|
|
$newval = preg_replace('/[^0-9a-zA-Z_-]/', '', $val); |
712
|
|
|
$_GET[$key] = $HTTP_GET_VARS[$key] = $newval; |
713
|
|
|
if ($_REQUEST[$key] == $_GET[$key]) { |
714
|
|
|
$_REQUEST[$key] = $newval; |
715
|
|
|
} |
716
|
|
|
} |
717
|
|
|
} |
718
|
|
View Code Duplication |
foreach ($_POST as $key => $val) { |
719
|
|
|
if (substr($key, -2) === 'id' && !is_array($_POST[$key])) { |
720
|
|
|
$newval = preg_replace('/[^0-9a-zA-Z_-]/', '', $val); |
721
|
|
|
$_POST[$key] = $HTTP_POST_VARS[$key] = $newval; |
722
|
|
|
if ($_REQUEST[$key] == $_POST[$key]) { |
723
|
|
|
$_REQUEST[$key] = $newval; |
724
|
|
|
} |
725
|
|
|
} |
726
|
|
|
} |
727
|
|
View Code Duplication |
foreach ($_COOKIE as $key => $val) { |
728
|
|
|
if (substr($key, -2) === 'id' && !is_array($_COOKIE[$key])) { |
729
|
|
|
$newval = preg_replace('/[^0-9a-zA-Z_-]/', '', $val); |
730
|
|
|
$_COOKIE[$key] = $HTTP_COOKIE_VARS[$key] = $newval; |
731
|
|
|
if ($_REQUEST[$key] == $_COOKIE[$key]) { |
732
|
|
|
$_REQUEST[$key] = $newval; |
733
|
|
|
} |
734
|
|
|
} |
735
|
|
|
} |
736
|
|
|
|
737
|
|
|
return true; |
738
|
|
|
} |
739
|
|
|
|
740
|
|
|
/** |
741
|
|
|
* @return bool |
742
|
|
|
*/ |
743
|
|
|
public function eliminate_dotdot() |
744
|
|
|
{ |
745
|
|
|
global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS; |
|
|
|
|
746
|
|
|
|
747
|
|
|
if ($this->_done_dotdot) { |
748
|
|
|
return true; |
749
|
|
|
} else { |
750
|
|
|
$this->_done_dotdot = true; |
751
|
|
|
} |
752
|
|
|
|
753
|
|
|
foreach ($_GET as $key => $val) { |
754
|
|
|
if (is_array($_GET[$key])) { |
755
|
|
|
continue; |
756
|
|
|
} |
757
|
|
|
if (substr(trim($val), 0, 3) === '../' || false !== strpos($val, '/../')) { |
758
|
|
|
$this->last_error_type = 'DirTraversal'; |
759
|
|
|
$this->message .= "Directory Traversal '$val' found.\n"; |
760
|
|
|
$this->output_log($this->last_error_type, 0, false, 64); |
761
|
|
|
$sanitized_val = str_replace(chr(0), '', $val); |
762
|
|
|
if (substr($sanitized_val, -2) !== ' .') { |
763
|
|
|
$sanitized_val .= ' .'; |
764
|
|
|
} |
765
|
|
|
$_GET[$key] = $HTTP_GET_VARS[$key] = $sanitized_val; |
766
|
|
|
if ($_REQUEST[$key] == $_GET[$key]) { |
767
|
|
|
$_REQUEST[$key] = $sanitized_val; |
768
|
|
|
} |
769
|
|
|
} |
770
|
|
|
} |
771
|
|
|
|
772
|
|
|
/* foreach ($_POST as $key => $val) { |
773
|
|
|
if( is_array( $_POST[ $key ] ) ) continue ; |
774
|
|
|
if ( substr( trim( $val ) , 0 , 3 ) == '../' || false !== strpos( $val , '../../' ) ) { |
775
|
|
|
$this->last_error_type = 'ParentDir' ; |
776
|
|
|
$this->message .= "Doubtful file specification '$val' found.\n" ; |
777
|
|
|
$this->output_log( $this->last_error_type , 0 , false , 128 ) ; |
778
|
|
|
$sanitized_val = str_replace( chr(0) , '' , $val ) ; |
779
|
|
|
if( substr( $sanitized_val , -2 ) != ' .' ) $sanitized_val .= ' .' ; |
780
|
|
|
$_POST[ $key ] = $HTTP_POST_VARS[ $key ] = $sanitized_val ; |
781
|
|
|
if ($_REQUEST[ $key ] == $_POST[ $key ]) { |
782
|
|
|
$_REQUEST[ $key ] = $sanitized_val ; |
783
|
|
|
} |
784
|
|
|
} |
785
|
|
|
} |
786
|
|
|
foreach ($_COOKIE as $key => $val) { |
787
|
|
|
if( is_array( $_COOKIE[ $key ] ) ) continue ; |
788
|
|
|
if ( substr( trim( $val ) , 0 , 3 ) == '../' || false !== strpos( $val , '../../' ) ) { |
789
|
|
|
$this->last_error_type = 'ParentDir' ; |
790
|
|
|
$this->message .= "Doubtful file specification '$val' found.\n" ; |
791
|
|
|
$this->output_log( $this->last_error_type , 0 , false , 128 ) ; |
792
|
|
|
$sanitized_val = str_replace( chr(0) , '' , $val ) ; |
793
|
|
|
if( substr( $sanitized_val , -2 ) != ' .' ) $sanitized_val .= ' .' ; |
794
|
|
|
$_COOKIE[ $key ] = $HTTP_COOKIE_VARS[ $key ] = $sanitized_val ; |
795
|
|
|
if ($_REQUEST[ $key ] == $_COOKIE[ $key ]) { |
796
|
|
|
$_REQUEST[ $key ] = $sanitized_val ; |
797
|
|
|
} |
798
|
|
|
} |
799
|
|
|
}*/ |
800
|
|
|
|
801
|
|
|
return true; |
802
|
|
|
} |
803
|
|
|
|
804
|
|
|
/** |
805
|
|
|
* @param $current |
806
|
|
|
* @param $indexes |
807
|
|
|
* |
808
|
|
|
* @return bool |
809
|
|
|
*/ |
810
|
|
|
public function &get_ref_from_base64index(&$current, $indexes) |
811
|
|
|
{ |
812
|
|
|
foreach ($indexes as $index) { |
813
|
|
|
$index = base64_decode($index); |
814
|
|
|
if (!is_array($current)) { |
815
|
|
|
return false; |
816
|
|
|
} |
817
|
|
|
$current =& $current[$index]; |
818
|
|
|
} |
819
|
|
|
|
820
|
|
|
return $current; |
821
|
|
|
} |
822
|
|
|
|
823
|
|
|
/** |
824
|
|
|
* @param $key |
825
|
|
|
* @param $val |
826
|
|
|
*/ |
827
|
|
|
public function replace_doubtful($key, $val) |
828
|
|
|
{ |
829
|
|
|
global $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS; |
|
|
|
|
830
|
|
|
|
831
|
|
|
$index_expression = ''; |
|
|
|
|
832
|
|
|
$indexes = explode('_', $key); |
833
|
|
|
$base_array = array_shift($indexes); |
834
|
|
|
|
835
|
|
|
switch ($base_array) { |
836
|
|
|
case 'G' : |
|
|
|
|
837
|
|
|
$main_ref =& $this->get_ref_from_base64index($_GET, $indexes); |
838
|
|
|
$legacy_ref =& $this->get_ref_from_base64index($HTTP_GET_VARS, $indexes); |
839
|
|
|
break; |
840
|
|
|
case 'P' : |
|
|
|
|
841
|
|
|
$main_ref =& $this->get_ref_from_base64index($_POST, $indexes); |
842
|
|
|
$legacy_ref =& $this->get_ref_from_base64index($HTTP_POST_VARS, $indexes); |
843
|
|
|
break; |
844
|
|
|
case 'C' : |
|
|
|
|
845
|
|
|
$main_ref =& $this->get_ref_from_base64index($_COOKIE, $indexes); |
846
|
|
|
$legacy_ref =& $this->get_ref_from_base64index($HTTP_COOKIE_VARS, $indexes); |
847
|
|
|
break; |
848
|
|
|
default : |
|
|
|
|
849
|
|
|
exit; |
|
|
|
|
850
|
|
|
} |
851
|
|
|
if (!isset($main_ref)) { |
852
|
|
|
exit; |
|
|
|
|
853
|
|
|
} |
854
|
|
|
$request_ref =& $this->get_ref_from_base64index($_REQUEST, $indexes); |
855
|
|
|
if ($request_ref !== false && $main_ref == $request_ref) { |
856
|
|
|
$request_ref = $val; |
857
|
|
|
} |
858
|
|
|
$main_ref = $val; |
859
|
|
|
$legacy_ref = $val; |
860
|
|
|
} |
861
|
|
|
|
862
|
|
|
/** |
863
|
|
|
* @return bool |
864
|
|
|
*/ |
865
|
|
|
public function check_uploaded_files() |
866
|
|
|
{ |
867
|
|
|
if ($this->_done_badext) { |
868
|
|
|
return $this->_safe_badext; |
869
|
|
|
} else { |
870
|
|
|
$this->_done_badext = true; |
871
|
|
|
} |
872
|
|
|
|
873
|
|
|
// extensions never uploaded |
874
|
|
|
$bad_extensions = array('php', 'phtml', 'phtm', 'php3', 'php4', 'cgi', 'pl', 'asp'); |
875
|
|
|
// extensions needed image check (anti-IE Content-Type XSS) |
876
|
|
|
$image_extensions = array( |
877
|
|
|
1 => 'gif', |
878
|
|
|
2 => 'jpg', |
879
|
|
|
3 => 'png', |
880
|
|
|
4 => 'swf', |
881
|
|
|
5 => 'psd', |
882
|
|
|
6 => 'bmp', |
883
|
|
|
7 => 'tif', |
884
|
|
|
8 => 'tif', |
885
|
|
|
9 => 'jpc', |
886
|
|
|
10 => 'jp2', |
887
|
|
|
11 => 'jpx', |
888
|
|
|
12 => 'jb2', |
889
|
|
|
13 => 'swc', |
890
|
|
|
14 => 'iff', |
891
|
|
|
15 => 'wbmp', |
892
|
|
|
16 => 'xbm'); |
893
|
|
|
|
894
|
|
|
foreach ($_FILES as $_file) { |
895
|
|
|
if (!empty($_file['error'])) { |
896
|
|
|
continue; |
897
|
|
|
} |
898
|
|
|
if (!empty($_file['name']) && is_string($_file['name'])) { |
899
|
|
|
$ext = strtolower(substr(strrchr($_file['name'], '.'), 1)); |
900
|
|
|
if ($ext === 'jpeg') { |
901
|
|
|
$ext = 'jpg'; |
902
|
|
|
} elseif ($ext === 'tiff') { |
903
|
|
|
$ext = 'tif'; |
904
|
|
|
} |
905
|
|
|
|
906
|
|
|
// anti multiple dot file (Apache mod_mime.c) |
907
|
|
|
if (count(explode('.', str_replace('.tar.gz', '.tgz', $_file['name']))) > 2) { |
908
|
|
|
$this->message .= "Attempt to multiple dot file {$_file['name']}.\n"; |
909
|
|
|
$this->_safe_badext = false; |
910
|
|
|
$this->last_error_type = 'UPLOAD'; |
911
|
|
|
} |
912
|
|
|
|
913
|
|
|
// anti dangerous extensions |
914
|
|
View Code Duplication |
if (in_array($ext, $bad_extensions)) { |
915
|
|
|
$this->message .= "Attempt to upload {$_file['name']}.\n"; |
916
|
|
|
$this->_safe_badext = false; |
917
|
|
|
$this->last_error_type = 'UPLOAD'; |
918
|
|
|
} |
919
|
|
|
|
920
|
|
|
// anti camouflaged image file |
921
|
|
|
if (in_array($ext, $image_extensions)) { |
922
|
|
|
$image_attributes = @getimagesize($_file['tmp_name']); |
923
|
|
|
if ($image_attributes === false && is_uploaded_file($_file['tmp_name'])) { |
924
|
|
|
// open_basedir restriction |
925
|
|
|
$temp_file = XOOPS_ROOT_PATH . '/uploads/protector_upload_temporary' . md5(time()); |
926
|
|
|
move_uploaded_file($_file['tmp_name'], $temp_file); |
927
|
|
|
$image_attributes = @getimagesize($temp_file); |
928
|
|
|
@unlink($temp_file); |
|
|
|
|
929
|
|
|
} |
930
|
|
|
|
931
|
|
|
if ($image_attributes === false || $image_extensions[(int)$image_attributes[2]] != $ext) { |
932
|
|
|
$this->message .= "Attempt to upload camouflaged image file {$_file['name']}.\n"; |
933
|
|
|
$this->_safe_badext = false; |
934
|
|
|
$this->last_error_type = 'UPLOAD'; |
935
|
|
|
} |
936
|
|
|
} |
937
|
|
|
} |
938
|
|
|
} |
939
|
|
|
|
940
|
|
|
return $this->_safe_badext; |
941
|
|
|
} |
942
|
|
|
|
943
|
|
|
/** |
944
|
|
|
* @return bool |
945
|
|
|
*/ |
946
|
|
|
public function check_contami_systemglobals() |
947
|
|
|
{ |
948
|
|
|
/* if( $this->_done_contami ) return $this->_safe_contami ; |
949
|
|
|
else $this->_done_contami = true ; */ |
950
|
|
|
|
951
|
|
|
/* foreach ($this->_bad_globals as $bad_global) { |
952
|
|
|
if ( isset( $_REQUEST[ $bad_global ] ) ) { |
953
|
|
|
$this->message .= "Attempt to inject '$bad_global' was found.\n" ; |
954
|
|
|
$this->_safe_contami = false ; |
955
|
|
|
$this->last_error_type = 'CONTAMI' ; |
956
|
|
|
} |
957
|
|
|
}*/ |
958
|
|
|
|
959
|
|
|
return $this->_safe_contami; |
960
|
|
|
} |
961
|
|
|
|
962
|
|
|
/** |
963
|
|
|
* @param bool $sanitize |
964
|
|
|
* |
965
|
|
|
* @return bool |
966
|
|
|
*/ |
967
|
|
|
public function check_sql_isolatedcommentin($sanitize = true) |
968
|
|
|
{ |
969
|
|
|
if ($this->_done_isocom) { |
970
|
|
|
return $this->_safe_isocom; |
971
|
|
|
} else { |
972
|
|
|
$this->_done_isocom = true; |
973
|
|
|
} |
974
|
|
|
|
975
|
|
|
foreach ($this->_doubtful_requests as $key => $val) { |
976
|
|
|
$str = $val; |
977
|
|
|
while ($str = strstr($str, '/*')) { /* */ |
978
|
|
|
$str = strstr(substr($str, 2), '*/'); |
979
|
|
|
if ($str === false) { |
980
|
|
|
$this->message .= "Isolated comment-in found. ($val)\n"; |
981
|
|
|
if ($sanitize) { |
982
|
|
|
$this->replace_doubtful($key, $val . '*/'); |
983
|
|
|
} |
984
|
|
|
$this->_safe_isocom = false; |
985
|
|
|
$this->last_error_type = 'ISOCOM'; |
986
|
|
|
} |
987
|
|
|
} |
988
|
|
|
} |
989
|
|
|
|
990
|
|
|
return $this->_safe_isocom; |
991
|
|
|
} |
992
|
|
|
|
993
|
|
|
/** |
994
|
|
|
* @param bool $sanitize |
995
|
|
|
* |
996
|
|
|
* @return bool |
997
|
|
|
*/ |
998
|
|
|
public function check_sql_union($sanitize = true) |
999
|
|
|
{ |
1000
|
|
|
if ($this->_done_union) { |
1001
|
|
|
return $this->_safe_union; |
1002
|
|
|
} else { |
1003
|
|
|
$this->_done_union = true; |
1004
|
|
|
} |
1005
|
|
|
|
1006
|
|
|
foreach ($this->_doubtful_requests as $key => $val) { |
1007
|
|
|
$str = str_replace(array('/*', '*/'), '', preg_replace('?/\*.+\*/?sU', '', $val)); |
1008
|
|
|
if (preg_match('/\sUNION\s+(ALL|SELECT)/i', $str)) { |
1009
|
|
|
$this->message .= "Pattern like SQL injection found. ($val)\n"; |
1010
|
|
|
if ($sanitize) { |
1011
|
|
|
// $this->replace_doubtful($key, preg_replace('/union/i', 'uni-on', $val)); |
1012
|
|
|
$this->replace_doubtful($key, str_ireplace('union', 'uni-on', $val)); |
1013
|
|
|
} |
1014
|
|
|
$this->_safe_union = false; |
1015
|
|
|
$this->last_error_type = 'UNION'; |
1016
|
|
|
} |
1017
|
|
|
} |
1018
|
|
|
|
1019
|
|
|
return $this->_safe_union; |
1020
|
|
|
} |
1021
|
|
|
|
1022
|
|
|
/** |
1023
|
|
|
* @param $uid |
1024
|
|
|
* |
1025
|
|
|
* @return bool |
1026
|
|
|
*/ |
1027
|
|
|
public function stopforumspam($uid) |
1028
|
|
|
{ |
1029
|
|
|
if (!function_exists('curl_init')) { |
1030
|
|
|
return false; |
1031
|
|
|
} |
1032
|
|
|
|
1033
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { |
1034
|
|
|
return false; |
1035
|
|
|
} |
1036
|
|
|
|
1037
|
|
|
$query = 'f=serial&ip=' . $_SERVER['REMOTE_ADDR']; |
1038
|
|
|
$query .= isset($_POST['email']) ? '&email=' . $_POST['email'] : ''; |
1039
|
|
|
$query .= isset($_POST['uname']) ? '&username=' . $_POST['uname'] : ''; |
1040
|
|
|
$url = 'http://www.stopforumspam.com/api?' . $query; |
1041
|
|
|
$ch = curl_init(); |
1042
|
|
|
curl_setopt($ch, CURLOPT_URL, $url); |
1043
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
1044
|
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); |
1045
|
|
|
$result = unserialize(curl_exec($ch)); |
1046
|
|
|
curl_close($ch); |
1047
|
|
|
|
1048
|
|
|
$spammer = false; |
1049
|
|
|
if (isset($result['email']) && isset($result['email']['lastseen'])) { |
1050
|
|
|
$spammer = true; |
1051
|
|
|
} |
1052
|
|
|
|
1053
|
|
|
if (isset($result['ip']) && isset($result['ip']['lastseen'])) { |
1054
|
|
|
$last = strtotime($result['ip']['lastseen']); |
1055
|
|
|
$oneMonth = 60 * 60 * 24 * 31; |
1056
|
|
|
$oneMonthAgo = time() - $oneMonth; |
1057
|
|
|
if ($last > $oneMonthAgo) { |
1058
|
|
|
$spammer = true; |
1059
|
|
|
} |
1060
|
|
|
} |
1061
|
|
|
|
1062
|
|
|
if (!$spammer) { |
1063
|
|
|
return false; |
1064
|
|
|
} |
1065
|
|
|
|
1066
|
|
|
$this->last_error_type = 'SPAMMER POST'; |
1067
|
|
|
|
1068
|
|
|
switch ($this->_conf['stopforumspam_action']) { |
1069
|
|
|
default : |
|
|
|
|
1070
|
|
|
case 'log' : |
|
|
|
|
1071
|
|
|
break; |
1072
|
|
|
case 'san' : |
|
|
|
|
1073
|
|
|
$_POST = array(); |
1074
|
|
|
$this->message .= 'POST deleted for IP:' . $_SERVER['REMOTE_ADDR']; |
1075
|
|
|
break; |
1076
|
|
|
case 'biptime0' : |
|
|
|
|
1077
|
|
|
$_POST = array(); |
1078
|
|
|
$this->message .= 'BAN and POST deleted for IP:' . $_SERVER['REMOTE_ADDR']; |
1079
|
|
|
$this->_should_be_banned_time0 = true; |
1080
|
|
|
break; |
1081
|
|
|
case 'bip' : |
|
|
|
|
1082
|
|
|
$_POST = array(); |
1083
|
|
|
$this->message .= 'Ban and POST deleted for IP:' . $_SERVER['REMOTE_ADDR']; |
1084
|
|
|
$this->_should_be_banned = true; |
1085
|
|
|
break; |
1086
|
|
|
} |
1087
|
|
|
|
1088
|
|
|
$this->output_log($this->last_error_type, $uid, false, 16); |
1089
|
|
|
|
1090
|
|
|
return true; |
1091
|
|
|
} |
1092
|
|
|
|
1093
|
|
|
/** |
1094
|
|
|
* @param int $uid |
1095
|
|
|
* @param bool $can_ban |
1096
|
|
|
* |
1097
|
|
|
* @return bool |
|
|
|
|
1098
|
|
|
*/ |
1099
|
|
|
public function check_dos_attack($uid = 0, $can_ban = false) |
1100
|
|
|
{ |
1101
|
|
|
global $xoopsDB; |
|
|
|
|
1102
|
|
|
|
1103
|
|
|
if ($this->_done_dos) { |
1104
|
|
|
return true; |
1105
|
|
|
} |
1106
|
|
|
|
1107
|
|
|
$ip = \Xmf\IPAddress::fromRequest(); |
1108
|
|
|
if (false === $ip->asReadable()) { |
1109
|
|
|
return true; |
1110
|
|
|
} |
1111
|
|
|
$uri = @$_SERVER['REQUEST_URI']; |
1112
|
|
|
$ip4sql = $xoopsDB->quote($ip->asReadable()); |
1113
|
|
|
$uri4sql = $xoopsDB->quote($uri); |
1114
|
|
|
|
1115
|
|
|
// gargage collection |
1116
|
|
|
$result = $xoopsDB->queryF( |
1117
|
|
|
'DELETE FROM ' . $xoopsDB->prefix($this->mydirname . '_access') |
1118
|
|
|
. ' WHERE expire < UNIX_TIMESTAMP()' |
1119
|
|
|
); |
1120
|
|
|
|
1121
|
|
|
// for older versions before updating this module |
1122
|
|
|
if ($result === false) { |
1123
|
|
|
$this->_done_dos = true; |
1124
|
|
|
|
1125
|
|
|
return true; |
1126
|
|
|
} |
1127
|
|
|
|
1128
|
|
|
// sql for recording access log (INSERT should be placed after SELECT) |
1129
|
|
|
$sql4insertlog = 'INSERT INTO ' . $xoopsDB->prefix($this->mydirname . '_access') |
1130
|
|
|
. " SET ip={$ip4sql}, request_uri={$uri4sql}," |
1131
|
|
|
. " expire=UNIX_TIMESTAMP()+'" . (int)$this->_conf['dos_expire'] . "'"; |
1132
|
|
|
|
1133
|
|
|
// bandwidth limitation |
1134
|
|
|
if (@$this->_conf['bwlimit_count'] >= 10) { |
1135
|
|
|
$result = $xoopsDB->query('SELECT COUNT(*) FROM ' . $xoopsDB->prefix($this->mydirname . '_access')); |
1136
|
|
|
list($bw_count) = $xoopsDB->fetchRow($result); |
1137
|
|
|
if ($bw_count > $this->_conf['bwlimit_count']) { |
1138
|
|
|
$this->write_file_bwlimit(time() + $this->_conf['dos_expire']); |
1139
|
|
|
} |
1140
|
|
|
} |
1141
|
|
|
|
1142
|
|
|
// F5 attack check (High load & same URI) |
1143
|
|
|
$result = $xoopsDB->query( |
1144
|
|
|
'SELECT COUNT(*) FROM ' . $xoopsDB->prefix($this->mydirname . '_access') |
1145
|
|
|
. " WHERE ip={$ip4sql} AND request_uri={$uri4sql}"); |
1146
|
|
|
list($f5_count) = $xoopsDB->fetchRow($result); |
1147
|
|
View Code Duplication |
if ($f5_count > $this->_conf['dos_f5count']) { |
1148
|
|
|
|
1149
|
|
|
// delayed insert |
1150
|
|
|
$xoopsDB->queryF($sql4insertlog); |
1151
|
|
|
|
1152
|
|
|
// extends the expires of the IP with 5 minutes at least (pending) |
1153
|
|
|
// $result = $xoopsDB->queryF( "UPDATE ".$xoopsDB->prefix($this->mydirname.'_access')." SET expire=UNIX_TIMESTAMP()+300 WHERE ip='$ip4sql' AND expire<UNIX_TIMESTAMP()+300" ) ; |
1154
|
|
|
|
1155
|
|
|
// call the filter first |
1156
|
|
|
$ret = $this->call_filter('f5attack_overrun'); |
|
|
|
|
1157
|
|
|
|
1158
|
|
|
// actions for F5 Attack |
1159
|
|
|
$this->_done_dos = true; |
1160
|
|
|
$this->last_error_type = 'DoS'; |
1161
|
|
|
switch ($this->_conf['dos_f5action']) { |
1162
|
|
|
default : |
|
|
|
|
1163
|
|
|
case 'exit' : |
|
|
|
|
1164
|
|
|
$this->output_log($this->last_error_type, $uid, true, 16); |
1165
|
|
|
exit; |
|
|
|
|
1166
|
|
|
case 'none' : |
|
|
|
|
1167
|
|
|
$this->output_log($this->last_error_type, $uid, true, 16); |
1168
|
|
|
|
1169
|
|
|
return true; |
1170
|
|
|
case 'biptime0' : |
|
|
|
|
1171
|
|
|
if ($can_ban) { |
1172
|
|
|
$this->register_bad_ips(time() + $this->_conf['banip_time0']); |
1173
|
|
|
} |
1174
|
|
|
break; |
1175
|
|
|
case 'bip' : |
|
|
|
|
1176
|
|
|
if ($can_ban) { |
1177
|
|
|
$this->register_bad_ips(); |
1178
|
|
|
} |
1179
|
|
|
break; |
1180
|
|
|
case 'hta' : |
|
|
|
|
1181
|
|
|
if ($can_ban) { |
1182
|
|
|
$this->deny_by_htaccess(); |
1183
|
|
|
} |
1184
|
|
|
break; |
1185
|
|
|
case 'sleep' : |
|
|
|
|
1186
|
|
|
sleep(5); |
1187
|
|
|
break; |
1188
|
|
|
} |
1189
|
|
|
|
1190
|
|
|
return false; |
1191
|
|
|
} |
1192
|
|
|
|
1193
|
|
|
// Check its Agent |
1194
|
|
|
if (trim($this->_conf['dos_crsafe']) != '' && preg_match($this->_conf['dos_crsafe'], @$_SERVER['HTTP_USER_AGENT'])) { |
1195
|
|
|
// welcomed crawler |
1196
|
|
|
$this->_done_dos = true; |
1197
|
|
|
|
1198
|
|
|
return true; |
1199
|
|
|
} |
1200
|
|
|
|
1201
|
|
|
// Crawler check (High load & different URI) |
1202
|
|
|
$result = $xoopsDB->query( |
1203
|
|
|
'SELECT COUNT(*) FROM ' . $xoopsDB->prefix($this->mydirname . '_access') . " WHERE ip={$ip4sql}" |
1204
|
|
|
); |
1205
|
|
|
list($crawler_count) = $xoopsDB->fetchRow($result); |
1206
|
|
|
|
1207
|
|
|
// delayed insert |
1208
|
|
|
$xoopsDB->queryF($sql4insertlog); |
1209
|
|
|
|
1210
|
|
View Code Duplication |
if ($crawler_count > $this->_conf['dos_crcount']) { |
1211
|
|
|
|
1212
|
|
|
// call the filter first |
1213
|
|
|
$ret = $this->call_filter('crawler_overrun'); |
|
|
|
|
1214
|
|
|
|
1215
|
|
|
// actions for bad Crawler |
1216
|
|
|
$this->_done_dos = true; |
1217
|
|
|
$this->last_error_type = 'CRAWLER'; |
1218
|
|
|
switch ($this->_conf['dos_craction']) { |
1219
|
|
|
default : |
|
|
|
|
1220
|
|
|
case 'exit' : |
|
|
|
|
1221
|
|
|
$this->output_log($this->last_error_type, $uid, true, 16); |
1222
|
|
|
exit; |
|
|
|
|
1223
|
|
|
case 'none' : |
|
|
|
|
1224
|
|
|
$this->output_log($this->last_error_type, $uid, true, 16); |
1225
|
|
|
|
1226
|
|
|
return true; |
1227
|
|
|
case 'biptime0' : |
|
|
|
|
1228
|
|
|
if ($can_ban) { |
1229
|
|
|
$this->register_bad_ips(time() + $this->_conf['banip_time0']); |
1230
|
|
|
} |
1231
|
|
|
break; |
1232
|
|
|
case 'bip' : |
|
|
|
|
1233
|
|
|
if ($can_ban) { |
1234
|
|
|
$this->register_bad_ips(); |
1235
|
|
|
} |
1236
|
|
|
break; |
1237
|
|
|
case 'hta' : |
|
|
|
|
1238
|
|
|
if ($can_ban) { |
1239
|
|
|
$this->deny_by_htaccess(); |
1240
|
|
|
} |
1241
|
|
|
break; |
1242
|
|
|
case 'sleep' : |
|
|
|
|
1243
|
|
|
sleep(5); |
1244
|
|
|
break; |
1245
|
|
|
} |
1246
|
|
|
|
1247
|
|
|
return false; |
1248
|
|
|
} |
1249
|
|
|
|
1250
|
|
|
return true; |
1251
|
|
|
} |
1252
|
|
|
|
1253
|
|
|
// |
1254
|
|
|
/** |
1255
|
|
|
* @return bool|null |
1256
|
|
|
*/ |
1257
|
|
|
public function check_brute_force() |
1258
|
|
|
{ |
1259
|
|
|
global $xoopsDB; |
|
|
|
|
1260
|
|
|
|
1261
|
|
|
$ip = \Xmf\IPAddress::fromRequest(); |
1262
|
|
|
if (false === $ip->asReadable()) { |
1263
|
|
|
return true; |
1264
|
|
|
} |
1265
|
|
|
$uri = @$_SERVER['REQUEST_URI']; |
1266
|
|
|
$ip4sql = $xoopsDB->quote($ip->asReadable()); |
1267
|
|
|
$uri4sql = $xoopsDB->quote($uri); |
1268
|
|
|
|
1269
|
|
|
$victim_uname = empty($_COOKIE['autologin_uname']) ? $_POST['uname'] : $_COOKIE['autologin_uname']; |
1270
|
|
|
// some UA send 'deleted' as a value of the deleted cookie. |
1271
|
|
|
if ($victim_uname === 'deleted') { |
1272
|
|
|
return null; |
1273
|
|
|
} |
1274
|
|
|
$mal4sql = $xoopsDB->quote("BRUTE FORCE: $victim_uname"); |
1275
|
|
|
|
1276
|
|
|
// gargage collection |
1277
|
|
|
$result = $xoopsDB->queryF( |
|
|
|
|
1278
|
|
|
'DELETE FROM ' . $xoopsDB->prefix($this->mydirname . '_access') . ' WHERE expire < UNIX_TIMESTAMP()' |
1279
|
|
|
); |
1280
|
|
|
|
1281
|
|
|
// sql for recording access log (INSERT should be placed after SELECT) |
1282
|
|
|
$sql4insertlog = 'INSERT INTO ' . $xoopsDB->prefix($this->mydirname . '_access') |
1283
|
|
|
. " SET ip={$ip4sql}, request_uri={$uri4sql}, malicious_actions={$mal4sql}, expire=UNIX_TIMESTAMP()+600"; |
1284
|
|
|
|
1285
|
|
|
// count check |
1286
|
|
|
$result = $xoopsDB->query( |
1287
|
|
|
'SELECT COUNT(*) FROM ' . $xoopsDB->prefix($this->mydirname . '_access') |
1288
|
|
|
. " WHERE ip={$ip4sql} AND malicious_actions like 'BRUTE FORCE:%'" |
1289
|
|
|
); |
1290
|
|
|
list($bf_count) = $xoopsDB->fetchRow($result); |
1291
|
|
|
if ($bf_count > $this->_conf['bf_count']) { |
1292
|
|
|
$this->register_bad_ips(time() + $this->_conf['banip_time0']); |
1293
|
|
|
$this->last_error_type = 'BruteForce'; |
1294
|
|
|
$this->message .= "Trying to login as '" . addslashes($victim_uname) . "' found.\n"; |
1295
|
|
|
$this->output_log('BRUTE FORCE', 0, true, 1); |
1296
|
|
|
$ret = $this->call_filter('bruteforce_overrun'); |
1297
|
|
|
if ($ret == false) { |
1298
|
|
|
exit; |
|
|
|
|
1299
|
|
|
} |
1300
|
|
|
} |
1301
|
|
|
// delayed insert |
1302
|
|
|
$xoopsDB->queryF($sql4insertlog); |
1303
|
|
|
return null; |
1304
|
|
|
} |
1305
|
|
|
|
1306
|
|
|
/** |
1307
|
|
|
* @param $val |
1308
|
|
|
*/ |
1309
|
|
|
protected function _spam_check_point_recursive($val) |
1310
|
|
|
{ |
1311
|
|
|
if (is_array($val)) { |
1312
|
|
|
foreach ($val as $subval) { |
1313
|
|
|
$this->_spam_check_point_recursive($subval); |
1314
|
|
|
} |
1315
|
|
|
} else { |
1316
|
|
|
// http_host |
1317
|
|
|
$path_array = parse_url(XOOPS_URL); |
1318
|
|
|
$http_host = empty($path_array['host']) ? 'www.xoops.org' : $path_array['host']; |
1319
|
|
|
|
1320
|
|
|
// count URI up |
1321
|
|
|
$count = -1; |
1322
|
|
|
foreach (preg_split('#https?\:\/\/#i', $val) as $fragment) { |
1323
|
|
|
if (strncmp($fragment, $http_host, strlen($http_host)) !== 0) { |
1324
|
|
|
++$count; |
1325
|
|
|
} |
1326
|
|
|
} |
1327
|
|
|
if ($count > 0) { |
1328
|
|
|
$this->_spamcount_uri += $count; |
1329
|
|
|
} |
1330
|
|
|
|
1331
|
|
|
// count BBCode likd [url=www....] up (without [url=http://...]) |
1332
|
|
|
$this->_spamcount_uri += count(preg_split('/\[url=(?!http|\\"http|\\\'http|' . $http_host . ')/i', $val)) - 1; |
1333
|
|
|
} |
1334
|
|
|
} |
1335
|
|
|
|
1336
|
|
|
/** |
1337
|
|
|
* @param $points4deny |
1338
|
|
|
* @param $uid |
1339
|
|
|
*/ |
1340
|
|
|
public function spam_check($points4deny, $uid) |
1341
|
|
|
{ |
1342
|
|
|
$this->_spamcount_uri = 0; |
1343
|
|
|
$this->_spam_check_point_recursive($_POST); |
1344
|
|
|
|
1345
|
|
|
if ($this->_spamcount_uri >= $points4deny) { |
1346
|
|
|
$this->message .= @$_SERVER['REQUEST_URI'] . " SPAM POINT: $this->_spamcount_uri\n"; |
1347
|
|
|
$this->output_log('URI SPAM', $uid, false, 128); |
1348
|
|
|
$ret = $this->call_filter('spamcheck_overrun'); |
1349
|
|
|
if ($ret == false) { |
1350
|
|
|
exit; |
|
|
|
|
1351
|
|
|
} |
1352
|
|
|
} |
1353
|
|
|
} |
1354
|
|
|
|
1355
|
|
|
public function disable_features() |
1356
|
|
|
{ |
1357
|
|
|
global $HTTP_POST_VARS, $HTTP_GET_VARS, $HTTP_COOKIE_VARS; |
|
|
|
|
1358
|
|
|
|
1359
|
|
|
// disable "Notice: Undefined index: ..." |
1360
|
|
|
$error_reporting_level = error_reporting(0); |
1361
|
|
|
|
1362
|
|
|
// |
1363
|
|
|
// bit 1 : disable XMLRPC , criteria bug |
1364
|
|
|
// |
1365
|
|
|
if ($this->_conf['disable_features'] & 1) { |
1366
|
|
|
|
1367
|
|
|
// zx 2005/1/5 disable xmlrpc.php in root |
1368
|
|
|
if (/* ! stristr( $_SERVER['SCRIPT_NAME'] , 'modules' ) && */ |
1369
|
|
|
substr(@$_SERVER['SCRIPT_NAME'], -10) === 'xmlrpc.php' |
1370
|
|
|
) { |
1371
|
|
|
$this->output_log('xmlrpc', 0, true, 1); |
1372
|
|
|
exit; |
|
|
|
|
1373
|
|
|
} |
1374
|
|
|
|
1375
|
|
|
// security bug of class/criteria.php 2005/6/27 |
1376
|
|
|
if ($_POST['uname'] === '0' || $_COOKIE['autologin_pass'] === '0') { |
1377
|
|
|
$this->output_log('CRITERIA'); |
1378
|
|
|
exit; |
|
|
|
|
1379
|
|
|
} |
1380
|
|
|
} |
1381
|
|
|
|
1382
|
|
|
// |
1383
|
|
|
// bit 11 : XSS+CSRFs in XOOPS < 2.0.10 |
1384
|
|
|
// |
1385
|
|
|
if ($this->_conf['disable_features'] & 1024) { |
1386
|
|
|
|
1387
|
|
|
// root controllers |
1388
|
|
|
if (false === stripos(@$_SERVER['SCRIPT_NAME'], 'modules')) { |
1389
|
|
|
// zx 2004/12/13 misc.php debug (file check) |
1390
|
|
View Code Duplication |
if (substr(@$_SERVER['SCRIPT_NAME'], -8) === 'misc.php' && ($_GET['type'] === 'debug' || $_POST['type'] === 'debug') && !preg_match('/^dummy_\d+\.html$/', $_GET['file'])) { |
1391
|
|
|
$this->output_log('misc debug'); |
1392
|
|
|
exit; |
|
|
|
|
1393
|
|
|
} |
1394
|
|
|
|
1395
|
|
|
// zx 2004/12/13 misc.php smilies |
1396
|
|
View Code Duplication |
if (substr(@$_SERVER['SCRIPT_NAME'], -8) === 'misc.php' && ($_GET['type'] === 'smilies' || $_POST['type'] === 'smilies') && !preg_match('/^[0-9a-z_]*$/i', $_GET['target'])) { |
1397
|
|
|
$this->output_log('misc smilies'); |
1398
|
|
|
exit; |
|
|
|
|
1399
|
|
|
} |
1400
|
|
|
|
1401
|
|
|
// zx 2005/1/5 edituser.php avatarchoose |
1402
|
|
|
if (substr(@$_SERVER['SCRIPT_NAME'], -12) === 'edituser.php' && $_POST['op'] === 'avatarchoose' && false !== strpos($_POST['user_avatar'], '..')) { |
1403
|
|
|
$this->output_log('edituser avatarchoose'); |
1404
|
|
|
exit; |
|
|
|
|
1405
|
|
|
} |
1406
|
|
|
} |
1407
|
|
|
|
1408
|
|
|
// zx 2005/1/4 findusers |
1409
|
|
|
if (substr(@$_SERVER['SCRIPT_NAME'], -24) === 'modules/system/admin.php' && ($_GET['fct'] === 'findusers' || $_POST['fct'] === 'findusers')) { |
1410
|
|
|
foreach ($_POST as $key => $val) { |
1411
|
|
|
if (false !== strpos($key, "'") || false !== strpos($val, "'")) { |
1412
|
|
|
$this->output_log('findusers'); |
1413
|
|
|
exit; |
|
|
|
|
1414
|
|
|
} |
1415
|
|
|
} |
1416
|
|
|
} |
1417
|
|
|
|
1418
|
|
|
// preview CSRF zx 2004/12/14 |
1419
|
|
|
// news submit.php |
1420
|
|
|
if (substr(@$_SERVER['SCRIPT_NAME'], -23) === 'modules/news/submit.php' && isset($_POST['preview']) && strpos(@$_SERVER['HTTP_REFERER'], XOOPS_URL . '/modules/news/submit.php') !== 0) { |
1421
|
|
|
$HTTP_POST_VARS['nohtml'] = $_POST['nohtml'] = 1; |
1422
|
|
|
} |
1423
|
|
|
// news admin/index.php |
1424
|
|
|
if (substr(@$_SERVER['SCRIPT_NAME'], -28) === 'modules/news/admin/index.php' && ($_POST['op'] === 'preview' || $_GET['op'] === 'preview') && strpos(@$_SERVER['HTTP_REFERER'], XOOPS_URL . '/modules/news/admin/index.php') !== 0) { |
1425
|
|
|
$HTTP_POST_VARS['nohtml'] = $_POST['nohtml'] = 1; |
1426
|
|
|
} |
1427
|
|
|
// comment comment_post.php |
1428
|
|
|
if (isset($_POST['com_dopreview']) && false === strpos(substr(@$_SERVER['HTTP_REFERER'], -16), 'comment_post.php')) { |
1429
|
|
|
$HTTP_POST_VARS['dohtml'] = $_POST['dohtml'] = 0; |
1430
|
|
|
} |
1431
|
|
|
// disable preview of system's blocksadmin |
1432
|
|
|
if (substr(@$_SERVER['SCRIPT_NAME'], -24) === 'modules/system/admin.php' && ($_GET['fct'] === 'blocksadmin' || $_POST['fct'] === 'blocksadmin') && isset($_POST['previewblock']) /* && strpos( $_SERVER['HTTP_REFERER'] , XOOPS_URL.'/modules/system/admin.php' ) !== 0 */) { |
1433
|
|
|
die("Danger! don't use this preview. Use 'altsys module' instead.(by Protector)"); |
|
|
|
|
1434
|
|
|
} |
1435
|
|
|
// tpl preview |
1436
|
|
|
if (substr(@$_SERVER['SCRIPT_NAME'], -24) === 'modules/system/admin.php' && ($_GET['fct'] === 'tplsets' || $_POST['fct'] === 'tplsets')) { |
1437
|
|
|
if ($_POST['op'] === 'previewpopup' || $_GET['op'] === 'previewpopup' || isset($_POST['previewtpl'])) { |
1438
|
|
|
die("Danger! don't use this preview.(by Protector)"); |
|
|
|
|
1439
|
|
|
} |
1440
|
|
|
} |
1441
|
|
|
} |
1442
|
|
|
|
1443
|
|
|
// restore reporting level |
1444
|
|
|
error_reporting($error_reporting_level); |
1445
|
|
|
} |
1446
|
|
|
|
1447
|
|
|
/** |
1448
|
|
|
* @param $type |
1449
|
|
|
* @param string $dying_message |
1450
|
|
|
* |
1451
|
|
|
* @return int|mixed |
1452
|
|
|
*/ |
1453
|
|
|
public function call_filter($type, $dying_message = '') |
1454
|
|
|
{ |
1455
|
|
|
require_once __DIR__ . '/ProtectorFilter.php'; |
1456
|
|
|
$filter_handler = ProtectorFilterHandler::getInstance(); |
1457
|
|
|
$ret = $filter_handler->execute($type); |
1458
|
|
|
if ($ret == false && $dying_message) { |
|
|
|
|
1459
|
|
|
die($dying_message); |
|
|
|
|
1460
|
|
|
} |
1461
|
|
|
|
1462
|
|
|
return $ret; |
1463
|
|
|
} |
1464
|
|
|
} |
1465
|
|
|
|
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.