PluginProbe
The WP Remote WordPress Plugin / 5.53
The WP Remote WordPress Plugin v5.53
6.72 6.69 6.65 6.62 6.48 6.47 4.87 4.97 5.05 5.09 5.16 5.22 5.24 5.25 5.38 5.41 5.42 5.45 5.47 5.53 5.56 5.65 5.68 5.72 5.73 All 53 releases
wpremote / protect / fw.php

fw.php in The WP Remote WordPress Plugin 5.53, at protect/fw.php

1,521 lines 47.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH') && !defined('MCDATAPATH')) exit;
3
4 if (!class_exists('WPRProtectFW_V553')) :
5 require_once dirname( __FILE__ ) . '/fw/rule/errors.php';
6 require_once dirname( __FILE__ ) . '/fw/rule/engine.php';
7 require_once dirname( __FILE__ ) . '/fw/rule.php';
8
9 class WPRProtectFW_V553 {
10 private $brand_name;
11 private $protect_mode;
12 private $request;
13 private $ipstore;
14 private $logger;
15
16 private $is_shutdown_cb_set = false;
17 private $is_rule_initialized = false;
18 private $is_wpf_rule_initialized = false;
19 private $is_ip_cookie_set = false;
20 private $is_request_profiled = false;
21 private $is_on_boot_rules_executed = false;
22 private $is_ip_checked_for_blacklisted = false;
23 private $has_valid_bypass_cookie;
24
25 private $mode = WPRProtectFW_V553::MODE_DISABLED;
26 private $ip_cookie_mode = WPRProtectFW_V553::IP_COOKIE_MODE_DISABLED;
27 private $admin_cookie_mode = WPRProtectFW_V553::ADMIN_COOKIE_MODE_DISABLED;
28 private $bypass_level = WPRProtectFW_V553::WP_USER_ROLE_LEVEL_CONTRIBUTOR;
29 private $wpf_rule_init_mode = WPRProtectFW_V553::WPF_RULE_INIT_MODE_WP;
30 private $custom_roles = array();
31 private $cookie_key = "";
32 private $cookie_path = "";
33 private $cookie_domain = "";
34 private $can_set_cache_prevention_cookie = false;
35 private $rules_mode = WPRProtectFW_V553::RULES_MODE_DISABLED;
36 private $is_geo_blocking = false;
37 private $is_wp_user_cookie_enabled = false;
38 private $log_config = array();
39 private $request_profiling_mode = WPRProtectFW_V553::REQ_PROFILING_MODE_DISABLED;
40 private $logging_mode = WPRProtectFW_V553::LOGGING_MODE_VISITOR;
41 private $skip_log_config = array();
42 private $skip_log_cookies = array();
43 private $skip_log_headers = array();
44 private $skip_log_post_params = array();
45 private $skip_log_json_params = array();
46 private $wp_user_caps_to_consider = array();
47
48 private $request_profiled_data = array();
49 private $rules = array();
50 private $wpf_rules = array();
51 private $rule_log = array();
52 private $matched_rules = array();
53 private $break_rule_matching = false;
54 private $can_log_raw_body = false;
55 private $log_slice_size = WPRProtectFW_V553::LOG_SLICE_SIZE;
56
57 private static $instance = null;
58
59 const MODE_DISABLED = 1;
60 const MODE_AUDIT = 2;
61 const MODE_PROTECT = 3;
62
63 const RULES_MODE_DISABLED = 1;
64 const RULES_MODE_AUDIT = 2;
65 const RULES_MODE_PROTECT = 3;
66
67 const REQ_PROFILING_MODE_DISABLED = 1;
68 const REQ_PROFILING_MODE_NORMAL = 2;
69 const REQ_PROFILING_MODE_DEBUG = 3;
70
71 const IP_COOKIE_MODE_ENABLED = 1;
72 const IP_COOKIE_MODE_DISABLED = 2;
73
74 const WPF_RULE_INIT_MODE_PREPEND = 1;
75 const WPF_RULE_INIT_MODE_WP = 2;
76
77 const ADMIN_COOKIE_MODE_ENABLED = 1;
78 const ADMIN_COOKIE_MODE_DISABLED = 2;
79
80 const WP_USER_ROLE_LEVEL_UNKNOWN = 0;
81 const WP_USER_ROLE_LEVEL_SUBSCRIBER = 1;
82 const WP_USER_ROLE_LEVEL_CONTRIBUTOR = 2;
83 const WP_USER_ROLE_LEVEL_AUTHOR = 3;
84 const WP_USER_ROLE_LEVEL_EDITOR = 4;
85 const WP_USER_ROLE_LEVEL_ADMIN = 5;
86 const WP_USER_ROLE_LEVEL_CUSTOM = 6;
87
88 #XNOTE: Need clarity.
89 const WS_CONF_MODE_APACHEMODPHP = 1;
90 const WS_CONF_MODE_APACHESUPHP = 2;
91 const WS_CONF_MODE_CGI_FASTCGI = 3;
92 const WS_CONF_MODE_NGINX = 4;
93 const WS_CONF_MODE_LITESPEED = 5;
94 const WS_CONF_MODE_IIS = 6;
95
96 const LOGGING_MODE_VISITOR = 1;
97 const LOGGING_MODE_COMPLETE = 2;
98 const LOGGING_MODE_DISABLED = 3;
99
100 const DEFAULT_WP_USER_ROLE_LEVELS = array(
101 'administrator' => WPRProtectFW_V553::WP_USER_ROLE_LEVEL_ADMIN,
102 'editor' => WPRProtectFW_V553::WP_USER_ROLE_LEVEL_EDITOR,
103 'author' => WPRProtectFW_V553::WP_USER_ROLE_LEVEL_AUTHOR,
104 'contributor' => WPRProtectFW_V553::WP_USER_ROLE_LEVEL_CONTRIBUTOR,
105 'subscriber' => WPRProtectFW_V553::WP_USER_ROLE_LEVEL_SUBSCRIBER
106 );
107
108 const EXTRA_WP_USER_ROLE_LEVELS = array(
109 'custom' => WPRProtectFW_V553::WP_USER_ROLE_LEVEL_CUSTOM,
110 'unknown' => WPRProtectFW_V553::WP_USER_ROLE_LEVEL_UNKNOWN
111 );
112
113 const TABLE_NAME = "fw_requests";
114 const IP_COOKIE_NAME = "mcfw-ip-cookie";
115 const BYPASS_COOKIE_NAME = "mcfw-bypass-cookie";
116 const PREVENT_CACHE_COOKIE_NAME = "wp-mcfw-prevent-cache-cookie";
117
118 const LOG_SLICE_SIZE = 1024;
119
120 private function __construct($protect_mode, $request, $config, $brand_name) {
121 $this->request = $request;
122 $this->brand_name = $brand_name;
123 $this->protect_mode = $protect_mode;
124
125 if (array_key_exists('mode', $config) && is_int($config['mode'])) {
126 $this->mode = $config['mode'];
127 }
128
129 if (array_key_exists('ipcookiemode', $config) && is_int($config['ipcookiemode'])) {
130 $this->ip_cookie_mode = $config['ipcookiemode'];
131 }
132
133 if (array_key_exists('admincookiemode', $config) && is_int($config['admincookiemode'])) {
134 $this->admin_cookie_mode = $config['admincookiemode'];
135 }
136
137 if (array_key_exists('iswpusercookieenabled', $config) &&
138 is_bool($config['iswpusercookieenabled'])) {
139
140 $this->is_wp_user_cookie_enabled = $config['iswpusercookieenabled'];
141 }
142
143 if (array_key_exists('bypasslevel', $config) && is_int($config['bypasslevel'])) {
144 $this->bypass_level = $config['bypasslevel'];
145 }
146
147 if (array_key_exists('wpfruleinitmode', $config) && is_int($config['wpfruleinitmode'])) {
148 $this->wpf_rule_init_mode = $config['wpfruleinitmode'];
149 }
150
151 if (array_key_exists('customroles', $config) && is_array($config['customroles'])) {
152 $this->custom_roles = $config['customroles'];
153 }
154
155 if (array_key_exists('wpusercapstoconsider', $config) &&
156 is_array($config['wpusercapstoconsider'])) {
157
158 $this->wp_user_caps_to_consider = $config['wpusercapstoconsider'];
159 }
160
161 if (array_key_exists('cookiekey', $config) && is_string($config['cookiekey'])) {
162 $this->cookie_key = $config['cookiekey'];
163 }
164
165 if (array_key_exists('cookiepath', $config) && is_string($config['cookiepath'])) {
166 $this->cookie_path = $config['cookiepath'];
167 }
168
169 if (array_key_exists('cookiedomain', $config) && is_string($config['cookiedomain'])) {
170 $this->cookie_domain = $config['cookiedomain'];
171 }
172
173 if (array_key_exists('cansetcachepreventioncookie', $config) &&
174 is_bool($config['cansetcachepreventioncookie'])) {
175
176 $this->can_set_cache_prevention_cookie = $config['cansetcachepreventioncookie'];
177 }
178
179 if (array_key_exists('rulesmode', $config) && is_int($config['rulesmode'])) {
180 $this->rules_mode = $config['rulesmode'];
181 }
182
183 if (array_key_exists('isgeoblocking', $config) && is_bool($config['isgeoblocking'])) {
184 $this->is_geo_blocking = $config['isgeoblocking'];
185 }
186
187 if (array_key_exists('logconfig', $config) && is_array($config['logconfig'])) {
188 $this->log_config = $config['logconfig'];
189 }
190
191 if (array_key_exists('canlograwbody', $this->log_config) &&
192 is_bool($this->log_config['canlograwbody'])) {
193
194 $this->can_log_raw_body = $this->log_config['canlograwbody'];
195 }
196
197 if (array_key_exists('logslicesize', $this->log_config) &&
198 is_int($this->log_config['logslicesize'])) {
199
200 $this->log_slice_size = $this->log_config['logslicesize'];
201 }
202
203 if (array_key_exists('reqprofilingmode', $this->log_config) &&
204 is_int($this->log_config['reqprofilingmode'])) {
205
206 $this->request_profiling_mode = $this->log_config['reqprofilingmode'];
207 }
208
209 if (array_key_exists('loggingmode', $this->log_config) &&
210 is_int($this->log_config['loggingmode'])) {
211
212 $this->logging_mode = $this->log_config['loggingmode'];
213 }
214
215 if (array_key_exists('except', $this->log_config) && is_array($this->log_config['except'])) {
216 $this->skip_log_config = $this->log_config['except'];
217 }
218
219 if (array_key_exists('cookies', $this->skip_log_config) &&
220 is_array($this->skip_log_config['cookies'])) {
221
222 $this->skip_log_cookies = $this->skip_log_config['cookies'];
223 }
224
225 if (array_key_exists('headers', $this->skip_log_config) &&
226 is_array($this->skip_log_config['headers'])) {
227
228 $this->skip_log_headers = $this->skip_log_config['headers'];
229 }
230
231 if (array_key_exists('post', $this->skip_log_config) &&
232 is_array($this->skip_log_config['post'])) {
233
234 $this->skip_log_post_params = $this->skip_log_config['post'];
235 }
236
237 if (array_key_exists('json', $this->skip_log_config) &&
238 is_array($this->skip_log_config['json'])) {
239
240 $this->skip_log_json_params = $this->skip_log_config['json'];
241 }
242
243 if ($this->isPrependMode()) {
244 $log_file = MCDATAPATH . MCCONFKEY . '-mc.log';
245 $this->ipstore = new WPRProtectIpstore_V553(WPRProtectIpstore_V553::STORAGE_TYPE_FS);
246 $this->logger = new WPRProtectLogger_V553($log_file, WPRProtectLogger_V553::TYPE_FS);
247 } else {
248 $this->ipstore = new WPRProtectIpstore_V553(WPRProtectIpstore_V553::STORAGE_TYPE_DB);
249 $this->logger = new WPRProtectLogger_V553(WPRProtectFW_V553::TABLE_NAME, WPRProtectLogger_V553::TYPE_DB);
250 }
251
252 if ($this->is_wp_user_cookie_enabled) {
253 $this->loadWPUser();
254 }
255
256 $this->initRules();
257 }
258
259 public static function getInstance($protect_mode, $request, $config, $brand_name) {
260 if (!isset(self::$instance)) {
261 self::$instance = new self($protect_mode, $request, $config, $brand_name);
262 } elseif (self::$instance->protect_mode != $protect_mode && $protect_mode == WPRProtect_V553::MODE_WP) {
263 self::$instance->protect_mode = $protect_mode;
264 self::$instance->brand_name = $brand_name;
265 self::$instance->ipstore = new WPRProtectIpstore_V553(WPRProtectIpstore_V553::STORAGE_TYPE_DB);
266 self::$instance->initRules();
267 }
268
269 return self::$instance;
270 }
271
272 public static function uninstall() {
273 WPRProtect_V553::$db->dropBVTable(WPRProtectFW_V553::TABLE_NAME);
274 }
275
276 public function init() {
277 if (!$this->isModeDisabled()) {
278 $this->setShutdownCallback();
279 $this->profileRequest();
280 $this->setAdminCookie();
281 $this->setWPUserCookie();
282 $this->setIPCookie();
283 $this->blockRequestForBlacklistedIP();
284 if (!$this->is_on_boot_rules_executed) {
285 $this->handleRequestOnRuleMatch($this->rules);
286
287 $this->is_on_boot_rules_executed = true;
288 }
289 }
290 }
291
292 private function isPrependMode() {
293 return ($this->protect_mode === WPRProtect_V553::MODE_PREPEND);
294 }
295
296 private function isWPMode() {
297 return ($this->protect_mode === WPRProtect_V553::MODE_WP);
298 }
299
300 private function isModeDisabled() {
301 return ($this->mode === WPRProtectFW_V553::MODE_DISABLED);
302 }
303
304 private function isModeProtect() {
305 return ($this->mode === WPRProtectFW_V553::MODE_PROTECT);
306 }
307
308 private function isAdminCookieEnabled() {
309 return ($this->admin_cookie_mode === WPRProtectFW_V553::ADMIN_COOKIE_MODE_ENABLED);
310 }
311
312 private function isIPCookieEnabled() {
313 return ($this->ip_cookie_mode === WPRProtectFW_V553::IP_COOKIE_MODE_ENABLED);
314 }
315
316 private function isRequestProfilingDisabled() {
317 return ($this->request_profiling_mode === WPRProtectFW_V553::REQ_PROFILING_MODE_DISABLED);
318 }
319
320 private function isRequestProfilingModeDebug() {
321 return ($this->request_profiling_mode === WPRProtectFW_V553::REQ_PROFILING_MODE_DEBUG);
322 }
323
324 private function isRequestHasValidBypassCookie() {
325 if (!isset($this->has_valid_bypass_cookie)) {
326 $cookie = (string) $this->request->getCookies(WPRProtectFW_V553::BYPASS_COOKIE_NAME);
327 $new_cookie = $this->generateBypassCookie();
328 $is_valid = ($this->isAdminCookieEnabled() && $new_cookie && ($cookie === $new_cookie));
329 $this->has_valid_bypass_cookie = $is_valid;
330 }
331
332 return $this->has_valid_bypass_cookie;
333 }
334
335 private function isRulesModeProtect() {
336 return ($this->rules_mode === WPRProtectFW_V553::RULES_MODE_PROTECT);
337 }
338
339 public function isLoggingModeComplete() {
340 return ($this->logging_mode === WPRProtectFW_V553::LOGGING_MODE_COMPLETE);
341 }
342
343 public function isLoggingModeVisitor() {
344 return ($this->logging_mode === WPRProtectFW_V553::LOGGING_MODE_VISITOR);
345 }
346
347 public function isGeoBlockingEnabled() {
348 return ($this->is_geo_blocking === true);
349 }
350
351 private function isWPFRuleInitModePrepend() {
352 return ($this->wpf_rule_init_mode === WPRProtectFW_V553::WPF_RULE_INIT_MODE_PREPEND);
353 }
354
355 private function isWPFRuleInitModeWP() {
356 return ($this->wpf_rule_init_mode === WPRProtectFW_V553::WPF_RULE_INIT_MODE_WP);
357 }
358
359 private function canInitWPFRules() {
360 if (!$this->isWPFRuleInitModePrepend() && $this->isPrependMode()) {
361 return false;
362 }
363
364 return true;
365 }
366
367 private function generateBypassCookie() {
368 $time = floor(time() / 43200);
369
370 return hash('sha256', $this->bypass_level . $time . $this->cookie_key);
371 }
372
373 private function getWPFRules($action_name) {
374 if (!array_key_exists($action_name, $this->wpf_rules)) {
375 return array();
376 }
377 return $this->wpf_rules[$action_name];
378 }
379
380 public function setWPUserCookieHandler() {
381 if (function_exists('is_user_logged_in') && is_user_logged_in()) {
382 $current_wp_user = $this->getCurrentWPUser();
383
384 if (!$current_wp_user->isIdentical($this->request->wp_user)) {
385 $serialized_wp_user = WPRProtectWPUser_V553::_serialize($current_wp_user);
386 $cookie_val = $serialized_wp_user . '_' .
387 WPRProtectUtils_V553::signMessage($serialized_wp_user, $this->cookie_key);
388 $cookie_val = base64_encode($cookie_val);
389
390 $this->setcookie(WPRProtectWPUser_V553::COOKIE_NAME, $cookie_val, time() + 43200);
391 }
392 } elseif ($this->request->wp_user->isLoggedIn()) {
393 $this->request->wp_user = WPRProtectWPUser_V553::defaultUser();
394 $this->unsetCookie(WPRProtectWPUser_V553::COOKIE_NAME);
395 }
396 }
397
398 private function getCurrentWPUser() {
399 $id = 0;
400 $role_level = 0;
401 $capabilities = array();
402 $time = (int) floor(time() / 43200);
403
404 if (function_exists('wp_get_current_user')) {
405 $user = wp_get_current_user();
406 $id = $user->ID;
407 $role_level = $this->getCurrentWPUserRoleLevel();
408 $capabilities = $this->getCurrentWPUserCapabilities();
409 }
410
411 return (new WPRProtectWPUser_V553($id, $role_level, $capabilities, $time));
412 }
413
414 private function getCurrentWPUserCapabilities() {
415 $capabilities = array();
416
417 if (function_exists('current_user_can')) {
418 foreach ($this->wp_user_caps_to_consider as $capability => $id) {
419 if (current_user_can($capability)) {
420 $capabilities[] = $id;
421 }
422 }
423 sort($capabilities);
424 }
425
426 return $capabilities;
427 }
428
429 private function loadWPUser() {
430 $this->request->wp_user = WPRProtectWPUser_V553::defaultUser();
431
432 $cookie_val = $this->request->getCookies(WPRProtectWPUser_V553::COOKIE_NAME);
433 if (!is_string($cookie_val)) {
434 return;
435 }
436
437 $cookie_val = base64_decode($cookie_val, true);
438 if ($cookie_val === false) {
439 return;
440 }
441
442 $cookie_val_array = explode('_', $cookie_val);
443 if (count($cookie_val_array) !== 2) {
444 return;
445 }
446 list($serialized_user, $signature) = $cookie_val_array;
447
448 if (WPRProtectUtils_V553::verifyMessage($serialized_user, $signature, $this->cookie_key) === true) {
449 $wp_user = WPRProtectWPUser_V553::_unserialize($serialized_user);
450
451 if (!isset($wp_user) || $wp_user->time !== (int) floor(time() / 43200)) {
452 return;
453 }
454
455 $this->request->wp_user = $wp_user;
456
457 $capability_names = array_flip($this->wp_user_caps_to_consider);
458 foreach ($this->request->wp_user->capabilities as $capability) {
459 if (array_key_exists($capability, $capability_names)) {
460 $this->request->wp_user->capability_names[] = $capability_names[$capability];
461 }
462 }
463
464 $role_by_level = array_flip(array_merge(WPRProtectFW_V553::DEFAULT_WP_USER_ROLE_LEVELS,
465 WPRProtectFW_V553::EXTRA_WP_USER_ROLE_LEVELS));
466 $this->request->wp_user->role = $role_by_level[$this->request->wp_user->role_level];
467 }
468 }
469
470 private function pushWPFRule($action_name, $rule) {
471 if (!array_key_exists($action_name, $this->wpf_rules)) {
472 $this->wpf_rules[$action_name] = array();
473 }
474
475 $this->wpf_rules[$action_name][] = $rule;
476 }
477
478 private function initRules() {
479 if (!$this->isRulesModeProtect() || $this->isRequestIPWhitelisted()) {
480 return;
481 }
482
483 if ($this->is_rule_initialized && $this->is_wpf_rule_initialized) {
484 return;
485 }
486
487 if ($this->isPrependMode()) {
488 $rules_file = MCDATAPATH . MCCONFKEY . '-' . 'mc_rules.json';
489 $rule_arrays = WPRProtectUtils_V553::parseFile($rules_file);
490 } else {
491 $rule_arrays = WPRProtect_V553::$settings->getOption('bvruleset');
492 if(!is_array($rule_arrays)) {
493 $rule_arrays = array();
494 }
495 }
496
497 if (empty($rule_arrays)) {
498 $this->updateRuleLog('errors', 'ruleset', 'Invalid RuleSet');
499 return;
500 }
501
502 foreach($rule_arrays as $rule_array) {
503 $rule = WPRProtectFWRule_V553::init($rule_array);
504
505 if ($rule) {
506 if (!$this->is_rule_initialized && $rule->isExeOnBoot()) {
507 if (!$this->isRequestHasValidBypassCookie()) {
508 $this->initRule($rule);
509 }
510 } elseif (!$this->is_wpf_rule_initialized && $this->canInitWPFRules()) {
511 $this->initWPFRule($rule);
512 }
513 }
514 }
515
516 $this->is_rule_initialized = true;
517 if ($this->canInitWPFRules()) {
518 $this->is_wpf_rule_initialized = true;
519 }
520 }
521
522 private function initRule($rule) {
523 $this->rules[] = $rule;
524 }
525
526 private function initWPFRule($rule) {
527 if ($rule->isExeOnPreUpdateOption()) {
528 $this->addWPHook($rule, 'pre_update_option', 'handleRequestOnPreUpdateOption', 3);
529 } elseif ($rule->isExeOnPreDeletePost()) {
530 $this->addWPHook($rule, 'pre_delete_post', 'handleRequestOnPreDeletePost', 3);
531 } elseif ($rule->isExeOnWPInsertPostEmptyContent()) {
532 $this->addWPHook($rule, 'wp_insert_post_empty_content', 'handleRequestOnWPInsertPostEmptyContent', 2);
533 } elseif ($rule->isExeOnInsertUserMeta()) {
534 $this->addWPHook($rule, 'insert_user_meta', 'handleRequestOnInsertUserMeta', 4);
535 } elseif ($rule->isExeOnDeleteOption()) {
536 $this->addWPHook($rule, 'delete_option', 'handleRequestOnDeleteOption', 1, 'action');
537 } elseif ($rule->isExeOnDeleteUser()) {
538 $this->addWPHook($rule, 'delete_user', 'handleRequestOnDeleteUser', 3, 'action');
539 } elseif ($rule->isExeOnPasswordReset()) {
540 $this->addWPHook($rule, 'password_reset', 'handleRequestOnPasswordReset', 2, 'action');
541 } elseif ($rule->isExeOnSendAuthCookies()) {
542 $this->addWPHook($rule, 'send_auth_cookies', 'handleRequestOnSendAuthCookies', 6);
543 } elseif ($rule->isExeOnSetAuthCookie()) {
544 $this->addWPHook($rule, 'set_auth_cookie', 'handleRequestOnSetAuthCookie', 6, 'action');
545 } elseif ($rule->isExeOnInit()) {
546 $this->addWPHook($rule, 'init', 'handleRequestOnInit', 0, 'action');
547 } elseif ($rule->isExeOnUserRegister()) {
548 $this->addWPHook($rule, 'user_register', 'handleRequestOnUserRegister', 2, 'action');
549 } elseif ($rule->isExeOnAddUserMeta()) {
550 $this->addWPHook($rule, 'add_user_meta', 'handleRequestOnAddUserMeta', 3, 'action');
551 } elseif ($rule->isExeOnUpdateUserMetadata()) {
552 $this->addWPHook($rule, 'update_user_metadata', 'handleRequestOnUpdateUserMetadata', 5);
553 } elseif ($rule->isExeOnUpdateUserMeta()) {
554 $this->addWPHook($rule, 'update_user_meta', 'handleRequestOnUpdateUserMeta', 4, 'action');
555 } elseif ($rule->isExeOnAddOption()) {
556 $this->addWPHook($rule, 'add_option', 'handleRequestOnAddOption', 2, 'action');
557 } elseif ($rule->isExeOnWPPreInsertUserData()) {
558 $this->addWPHook($rule, 'wp_pre_insert_user_data', 'handleRequestOnWPPreInsertUserData', 4);
559 }
560 }
561
562 private function addWPHook($rule, $hook_name, $function_name, $accepted_args, $hook_type = 'filter') {
563 //Initialize the hook once for all rule of the same type.
564 if (empty($this->getWPFRules($function_name))) {
565 $callback = array($this, $function_name);
566
567 if ($this->isWPMode()) {
568 if ($hook_type == 'action') {
569 add_action($hook_name, $callback, -9999999, $accepted_args);
570 } else {
571 add_filter($hook_name, $callback, -9999999, $accepted_args);
572 }
573 } else {
574 WPRProtectUtils_V553::preInitWPHook($hook_name, $callback, -9999999, $accepted_args);
575 }
576 }
577
578 $this->pushWPFRule($function_name, $rule);
579 }
580
581 public function handleRequestOnPreUpdateOption($value, $option, $old_value) {
582 $rules = $this->getWPFRules('handleRequestOnPreUpdateOption');
583
584 if (!empty($rules)) {
585 $variables = array('value' => $value, 'option' => $option, 'old_value' => $old_value);
586 $log_data = $variables;
587 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
588 }
589
590 return $value;
591 }
592
593 public function handleRequestOnPreDeletePost($delete, $post, $force_delete) {
594 $rules = $this->getWPFRules('handleRequestOnPreDeletePost');
595
596 if (!empty($rules)) {
597 $variables = array('delete' => $delete, 'post' => $post, 'force_delete' => $force_delete);
598
599 $log_data = array(
600 'id' => $post->ID,
601 'post_type' => $post->post_type,
602 'post_status' => $post->post_status
603 );
604
605 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
606 }
607
608 return $delete;
609 }
610
611 public function handleRequestOnWPInsertPostEmptyContent($maybe_empty, $postarr) {
612 $rules = $this->getWPFRules('handleRequestOnWPInsertPostEmptyContent');
613
614 if (!empty($rules)) {
615 $variables = array('maybe_empty' => $maybe_empty, 'postarr' => $postarr);
616
617 $log_data = array();
618 if (isset($postarr['post_type'])) {
619 $log_data['post_type'] = $postarr['post_type'];
620 }
621 if (isset($postarr['ID'])) {
622 $log_data['id'] = $postarr['ID'];
623 }
624
625 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
626 }
627
628 return $maybe_empty;
629 }
630
631 public function handleRequestOnInsertUserMeta($meta, $user, $update, $userdata = null) {
632 $rules = $this->getWPFRules('handleRequestOnInsertUserMeta');
633
634 if (!empty($rules)) {
635 $variables = array(
636 'meta' => $meta,
637 'update' => $update
638 );
639 $log_data = $variables;
640
641 $variables['userdata'] = $userdata;
642 if (isset($userdata['user_login']) && is_string($userdata['user_login'])) {
643 $log_data['username'] = sanitize_user($userdata['user_login'], true);
644 }
645 if (isset($userdata['role'])) {
646 $log_data['role'] = $userdata['role'];
647 }
648
649 $variables['user'] = $user;
650 $log_data['user'] = $this->getUserLogData($user);
651
652 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
653 }
654
655 return $meta;
656 }
657
658 public function handleRequestOnDeleteOption($option) {
659 $rules = $this->getWPFRules('handleRequestOnDeleteOption');
660
661 if (!empty($rules)) {
662 $variables = array('option' => $option);
663 $log_data = $variables;
664 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
665 }
666 }
667
668 public function handleRequestOnDeleteUser($id, $reassign, $user = null) {
669 $rules = $this->getWPFRules('handleRequestOnDeleteUser');
670
671 if (!empty($rules)) {
672 if(is_null($user)) {
673 $user = $this->getUserBy('id', $id);
674 }
675
676 $variables = array('id' => $id, 'reassign' => $reassign);
677 $log_data = $variables;
678
679 $variables['user'] = $user;
680 $log_data['user'] = $this->getUserLogData($user);
681
682 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
683 }
684 }
685
686 public function handleRequestOnPasswordReset($user, $new_pass) {
687 $rules = $this->getWPFRules('handleRequestOnPasswordReset');
688
689 if (!empty($rules)) {
690 $variables = array('user' => $user, 'new_pass' => $new_pass);
691 $log_data = array(
692 'new_pass' => "MD5: " . md5($new_pass),
693 'user' => $this->getUserLogData($user)
694 );
695 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
696 }
697 }
698
699 public function handleRequestOnSendAuthCookies($send, $expire = null,
700 $expiration = null, $user_id = null, $scheme = null, $token = null) {
701 $rules = $this->getWPFRules('handleRequestOnSendAuthCookies');
702
703 if (!empty($rules)) {
704 $user = $this->getUserBy('id', $user_id);
705
706 $variables = array(
707 'user_id' => $user_id,
708 'send' => $send,
709 'expire' => $expire,
710 'expiration' => $expiration,
711 'scheme' => $scheme
712 );
713
714 $log_data = $variables;
715 $variables['token'] = $token;
716 $log_data['token'] = "MD5: " . md5($token);
717
718 $variables['user'] = $user;
719 $log_data['user'] = $this->getUserLogData($user);
720
721 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
722 }
723
724 return $send;
725 }
726
727 public function handleRequestOnSetAuthCookie($auth_cookie, $expire, $expiration, $user_id, $scheme, $token = null) {
728 $rules = $this->getWPFRules('handleRequestOnSetAuthCookie');
729
730 if (!empty($rules)) {
731 $user = $this->getUserBy('id', $user_id);
732
733 $variables = array(
734 'user_id' => $user_id,
735 'auth_cookie' => md5($auth_cookie),
736 'expire' => $expire,
737 'expiration' => $expiration,
738 'scheme' => $scheme
739 );
740
741 $log_data = $variables;
742
743 $variables['token'] = $token;
744 $log_data['token'] = "MD5: " . md5($token);
745
746 $variables['user'] = $user;
747 $log_data['user'] = $this->getUserLogData($user);
748
749 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
750 }
751 }
752
753 public function handleRequestOnInit() {
754 $rules = $this->getWPFRules('handleRequestOnInit');
755
756 if (!empty($rules)) {
757 $variables = array();
758 $this->handleRequestOnRuleMatch($rules, $variables);
759 }
760 }
761
762 public function handleRequestOnUserRegister($user_id, $userdata = null) {
763 $rules = $this->getWPFRules('handleRequestOnUserRegister');
764
765 if (!empty($rules)) {
766 $user = $this->getUserBy('id', $user_id);
767
768 $variables = array(
769 'user_id' => $user_id,
770 );
771
772 $log_data = $variables;
773
774 $variables['userdata'] = $userdata;
775 $log_data['user'] = $this->getUserLogData($user);
776
777 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
778 }
779 }
780
781 public function handleRequestOnAddUserMeta($object_id, $meta_key, $meta_value) {
782 $rules = $this->getWPFRules('handleRequestOnAddUserMeta');
783
784 if (!empty($rules)) {
785 $user = $this->getUserBy('id', $object_id);
786
787 $variables = array(
788 'object_id' => $object_id,
789 'meta_key' => $meta_key,
790 'meta_value' => $meta_value
791 );
792 $log_data = $variables;
793
794 $variables['user'] = $user;
795 $log_data['user'] = $this->getUserLogData($user);
796
797 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
798 }
799 }
800
801 public function handleRequestOnUpdateUserMetadata($check, $object_id, $meta_key, $meta_value, $prev_value) {
802 $rules = $this->getWPFRules('handleRequestOnUpdateUserMetadata');
803
804 if (!empty($rules)) {
805 $user = $this->getUserBy('id', $object_id);
806
807 $variables = array(
808 'check' => $check,
809 'object_id' => $object_id,
810 'meta_key' => $meta_key,
811 'meta_value' => $meta_value,
812 'prev_value' => $prev_value
813 );
814
815 $log_data = $variables;
816
817 $variables['user'] = $user;
818 $log_data['user'] = $this->getUserLogData($user);
819
820 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
821 }
822
823 return $check;
824 }
825
826 public function handleRequestOnUpdateUserMeta($meta_id, $object_id, $meta_key, $meta_value) {
827 $rules = $this->getWPFRules('handleRequestOnUpdateUserMeta');
828
829 if (!empty($rules)) {
830 $user = $this->getUserBy('id', $object_id);
831
832 $variables = array(
833 'meta_id' => $meta_id,
834 'object_id' => $object_id,
835 'meta_key' => $meta_key,
836 'meta_value' => $meta_value
837 );
838
839 $log_data = $variables;
840
841 $variables['user'] = $user;
842 $log_data['user'] = $this->getUserLogData($user);
843
844 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
845 }
846 }
847
848 public function handleRequestOnWPPreInsertUserData($data, $update, $user_id, $userdata = null) {
849 $rules = $this->getWPFRules('handleRequestOnWPPreInsertUserData');
850
851 if (!empty($rules)) {
852 $user = $this->getUserBy('id', $user_id);
853
854 $variables = array(
855 'update' => $update,
856 'user_id' => $user_id,
857 );
858 $log_data = $variables;
859
860 $variables['data'] = $data;
861 $variables['userdata'] = $userdata;
862
863 $log_data['data'] = array();
864 if (isset($data['user_login'])) {
865 $log_data['data']['user_login'] = $data['user_login'];
866 }
867 if (isset($data['user_email'])) {
868 $log_data['data']['user_email'] = $data['user_email'];
869 }
870
871 $log_data['userdata'] = array();
872 if (isset($userdata['role'])) {
873 $log_data['userdata']['role'] = $userdata['role'];
874 }
875
876 $variables['user'] = $user;
877 $log_data['user'] = $this->getUserLogData($user);
878
879 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
880 }
881
882 return $data;
883 }
884
885 public function handleRequestOnAddOption($option, $value) {
886 $rules = $this->getWPFRules('handleRequestOnAddOption');
887
888 if (!empty($rules)) {
889 $variables = array(
890 'option' => $option,
891 'value' => $value
892 );
893 $log_data = $variables;
894
895 $this->handleRequestOnRuleMatch($rules, $variables, $log_data);
896 }
897 }
898
899 private function setShutdownCallback() {
900 if (!$this->is_shutdown_cb_set) {
901 register_shutdown_function(array($this, 'log'));
902 $this->is_shutdown_cb_set = true;
903 }
904 }
905
906 private function setCookie($name, $value, $expire) {
907 $path = $this->cookie_path;
908 $cookie_domain = $this->cookie_domain;
909
910 if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
911 $secure = function_exists('is_ssl') ? is_ssl() : false;
912 @setcookie($name, $value, $expire, $path, $cookie_domain, $secure, true);
913 } else {
914 @setcookie($name, $value, $expire, $path);
915 }
916 }
917
918 private function unsetCookie($name) {
919 $pastTime = time() - 3600;
920 $this->setCookie($name, '', $pastTime);
921 }
922
923 private function setAdminCookie() {
924 if ($this->isWPMode() && $this->isAdminCookieEnabled()) {
925 add_action('init', array($this, 'setBypassCookie'));
926 }
927 }
928
929 private function setWPUserCookie() {
930 if ($this->isWPMode() && $this->is_wp_user_cookie_enabled) {
931 add_action('init', array($this, 'setWPUserCookieHandler'), -9999999);
932 }
933 }
934
935 private function setIPCookie() {
936 if (!$this->is_ip_cookie_set && $this->isIPCookieEnabled() &&
937 !$this->request->getCookies(WPRProtectFW_V553::IP_COOKIE_NAME)) {
938
939 $time = floor(time() / 86400);
940 $cookie = hash('sha256', $this->request->ip . $time . $this->cookie_key);
941 if ($cookie) {
942 $this->setCookie(WPRProtectFW_V553::IP_COOKIE_NAME, $cookie, time() + 86400);
943 }
944 }
945 }
946
947 private function getCurrentWPUserRoleLevel() {
948 if (function_exists('current_user_can')) {
949 if (function_exists('is_super_admin') && is_super_admin()) {
950 return WPRProtectFW_V553::WP_USER_ROLE_LEVEL_ADMIN;
951 }
952
953 foreach ($this->custom_roles as $role) {
954 if (current_user_can($role)) {
955 return WPRProtectFW_V553::WP_USER_ROLE_LEVEL_CUSTOM;
956 }
957 }
958
959 foreach (WPRProtectFW_V553::DEFAULT_WP_USER_ROLE_LEVELS as $role => $level) {
960 if (current_user_can($role)) {
961 return $level;
962 }
963 }
964 }
965
966 return 0;
967 }
968
969 public function canLogRequest() {
970 $can_log = false;
971
972 if ($this->isLoggingModeComplete()) {
973 $can_log = true;
974 } elseif ($this->isLoggingModeVisitor()) {
975 $can_log = (!empty($this->matched_rules) || !$this->isRequestHasValidBypassCookie());
976 }
977
978 return $can_log;
979 }
980
981 public function log() {
982 if ($this->canLogRequest()) {
983 $this->logger->log($this->getRequestDataToLog());
984 }
985 }
986
987 private function canLogValue($key, $prefix) {
988 switch ($prefix) {
989 case 'BODY[':
990 return $this->canLogPostValue($key);
991 case 'COOKIES[':
992 return $this->canLogCookieValue($key);
993 case 'JSON[':
994 return $this->canLogJsonValue($key);
995 case 'HEADERS[':
996 return $this->canLogHeaderValue($key);
997 }
998
999 return true;
1000 }
1001
1002 private function canLogPostValue($key) {
1003 if (is_string($key) && in_array($key, $this->skip_log_post_params)) {
1004 return false;
1005 }
1006
1007 return true;
1008 }
1009
1010 private function canLogCookieValue($key) {
1011 if (is_string($key) && in_array($key, $this->skip_log_cookies)) {
1012 return false;
1013 }
1014
1015 return true;
1016 }
1017
1018 private function canLogHeaderValue($key) {
1019 if (is_string($key) && in_array($key, $this->skip_log_headers)) {
1020 return false;
1021 }
1022
1023 return true;
1024 }
1025
1026 private function canLogJsonValue($key) {
1027 return $this->canLogKeyValue($key, $this->skip_log_json_params);
1028 }
1029
1030 private function canLogKeyValue($key, $skip_params) {
1031 if (is_string($key) && in_array($key, $skip_params)) {
1032 return false;
1033 }
1034
1035 return true;
1036 }
1037
1038 private function getParamsToLog($params, $type) {
1039 $loggable_params = array();
1040
1041 if (is_array($params)) {
1042 foreach ($params as $key => $value) {
1043 if (is_array($value)) {
1044 $loggable_params[$key] = $this->getParamsToLog($value, $type);
1045 } else {
1046 if ($type == "POST" && !$this->canLogPostValue($key)) {
1047 $loggable_params[$key] = "Sensitive Data";
1048 } else if ($type == "JSON" && !$this->canLogJsonValue($key)) {
1049 $loggable_params[$key] = "Sensitive Data";
1050 } else {
1051 $loggable_params[$key] = $this->getSlicedValueToLog($value);
1052 }
1053 }
1054 }
1055 }
1056
1057 return $loggable_params;
1058 }
1059
1060 private function getRawBodyToLog($content) {
1061 return $this->getSlicedValueToLog($content);
1062 }
1063
1064 private function getBVCookies() {
1065 $cookies = array();
1066
1067 if ($this->request->getCookies(WPRProtectFW_V553::IP_COOKIE_NAME) !== NULL) {
1068 $cookie_val = (string) $this->request->getCookies(WPRProtectFW_V553::IP_COOKIE_NAME);
1069 $cookies[WPRProtectFW_V553::IP_COOKIE_NAME] = $cookie_val;
1070 }
1071
1072 return $cookies;
1073 }
1074
1075 private function getCookiesToLog($cookies) {
1076 $loggable_cookies = array();
1077
1078 if (is_array($cookies)) {
1079 foreach ($cookies as $key => $value) {
1080 if (!$this->canLogCookieValue($key)) {
1081 $loggable_cookies[$key] = "SensitiveData:" . md5($value);
1082 } else {
1083 $loggable_cookies[$key] = $value;
1084 }
1085 }
1086 }
1087
1088 return $loggable_cookies;
1089 }
1090
1091 private function getHeadersToLog($headers) {
1092 $loggable_headers = array();
1093
1094 if (is_array($headers)) {
1095 foreach ($headers as $key => $value) {
1096 if (!$this->canLogHeaderValue($key)) {
1097 $loggable_headers[$key] = "SensitiveData:" . md5($value);
1098 } else {
1099 $loggable_headers[$key] = $value;
1100 }
1101 }
1102 }
1103
1104 return $loggable_headers;
1105 }
1106
1107 private function getSlicedValueToLog($value, $size = null) {
1108 if (!is_scalar($value)) {
1109 return "Logging of " . gettype($value) . " is not supported.";
1110 }
1111
1112 if ($size === null) {
1113 $size = $this->log_slice_size;
1114 }
1115
1116 $loggable_value = '';
1117
1118 $valsize = $this->getLength($value);
1119 if ($valsize > $size) {
1120 $value = substr((string) $value, 0, $size);
1121 $loggable_value = "Data too long: {$valsize} : {$value}";
1122 } else {
1123 $loggable_value = $value;
1124 }
1125
1126 return $loggable_value;
1127 }
1128
1129 private function getRequestDataToLog() {
1130 $referer = $this->request->getHeader('Referer') ? $this->request->getHeader('Referer') : '';
1131 $user_agent = $this->request->getHeader('User-Agent')
1132 ? $this->request->getHeader('User-Agent') : '';
1133
1134 $rule_log = serialize($this->rule_log);
1135 if (strlen($rule_log) > 64000) {
1136 $rule_log = substr($rule_log, 0, 64000);
1137 }
1138
1139 $request_profiled_data = serialize($this->request_profiled_data);
1140 if (strlen($request_profiled_data) > 16000) {
1141 $request_profiled_data = serialize(array("keys" => array_keys($this->request_profiled_data)));
1142 if (strlen($request_profiled_data) > 16000) {
1143 $request_profiled_data = serialize(array("bv_over_size" => true));
1144 }
1145 }
1146
1147 $data = array(
1148 "path" => $this->request->path,
1149 "filenames" => serialize($this->request->file_names),
1150 "host" => $this->request->host,
1151 "time" => $this->request->timestamp,
1152 "ip" => $this->request->ip,
1153 "method" => $this->request->method,
1154 "query_string" => $request_profiled_data,
1155 "user_agent" => $user_agent,
1156 "resp_code" => $this->request->getRespCode(),
1157 "referer" => $referer,
1158 "status" => $this->request->status,
1159 "category" => $this->request->category,
1160 "rules_info" => $rule_log,
1161 "request_id" => $this->request->getRequestID(),
1162 "matched_rules"=> serialize($this->matched_rules)
1163 );
1164
1165 return $data;
1166 }
1167
1168 private function getLength($val) {
1169 $length = 0;
1170
1171 if (is_array($val)) {
1172 foreach ($val as $e) {
1173 $length += $this->getLength($e);
1174 }
1175
1176 return $length;
1177 } else {
1178 return strlen((string) $val);
1179 }
1180 }
1181
1182 private function matchCount($pattern, $subject) {
1183 $count = 0;
1184 if (is_array($subject)) {
1185 foreach ($subject as $val) {
1186 $count += $this->matchCount($pattern, $val);
1187 }
1188 return $count;
1189 } else {
1190 $count = preg_match_all((string) $pattern, (string) $subject, $matches);
1191 return ($count === false ? 0 : $count);
1192 }
1193 }
1194
1195 private function updateRuleLog($category, $sub_category, $value) {
1196 $category_data = array();
1197 $sub_category_data = array();
1198
1199 if (array_key_exists($category, $this->rule_log)) {
1200 $category_data = $this->rule_log[$category];
1201 }
1202
1203 if (array_key_exists($sub_category, $category_data)) {
1204 $sub_category_data = $category_data[$sub_category];
1205 }
1206
1207 $sub_category_data[] = $value;
1208 $category_data[$sub_category] = $sub_category_data;
1209
1210 $this->rule_log[$category] = $category_data;
1211 }
1212
1213 private function inspectRequest() {
1214 if (isset($this->request->wp_user)) {
1215 $this->updateRuleLog('inspect', "wpUserInfo", $this->request->wp_user->getInfo());
1216 }
1217
1218 $this->updateRuleLog('inspect', "headers", $this->getHeadersToLog($this->request->getHeaders()));
1219 $this->updateRuleLog('inspect', "cookies", $this->getCookiesToLog($this->request->getCookies()));
1220 $this->updateRuleLog('inspect', "getParams", $this->request->getGetParams());
1221 $this->updateRuleLog('inspect', "postParams", $this->getParamsToLog($this->request->getPostParams(), "POST"));
1222 $this->updateRuleLog('inspect', "jsonParams", $this->getParamsToLog($this->request->getJsonParams(), "JSON"));
1223 $this->updateRuleLog('inspect', "rawBody", $this->getRawBodyToLog($this->request->getRawBody()));
1224 }
1225
1226 private function getUserBy($attribute, $value) {
1227 if (isset($value) && function_exists('get_user_by') && WPRProtectUtils_V553::havePluginsLoaded()) {
1228 return get_user_by($attribute, $value);
1229 }
1230 }
1231
1232 private function getUserLogData($user) {
1233 $user_data = array();
1234
1235 if (is_a($user, "WP_User")) {
1236 $user_data = array(
1237 'id' => $user->ID,
1238 'user_login' => $user->user_login,
1239 'user_email' => $user->user_email,
1240 'allcaps' => $user->allcaps,
1241 'roles' => $user->roles
1242 );
1243 }
1244
1245 return $user_data;
1246 }
1247
1248 private function profileRequestData($params, $debug = false, $prefix = '', $obraces = 1) {
1249 $profiled_data = array();
1250
1251 if (is_array($params)) {
1252 foreach ($params as $key => $value) {
1253 $original_key = $key;
1254 $key = $prefix . $key;
1255 if (is_array($value)) {
1256 $profiled_data = $profiled_data + $this->profileRequestData($value, $debug, $key . '[', $obraces + 1);
1257 } else {
1258 $key = $key . str_repeat(']', $obraces);
1259 $profiled_data[$key] = array();
1260 $valsize = $this->getLength($value);
1261 $profiled_data[$key]["size"] = $valsize;
1262 if ($debug === true && $valsize < 256 && $this->canLogValue($original_key, $prefix)) {
1263 $profiled_data[$key]["value"] = $value;
1264 continue;
1265 }
1266
1267 if (WPRHelper::safePregMatch('/^\d+$/', $value)) {
1268 $profiled_data[$key]["numeric"] = true;
1269 } elseif (WPRHelper::safePregMatch('/^\w+$/', $value)) {
1270 $profiled_data[$key]["regular_word"] = true;
1271 } elseif (WPRHelper::safePregMatch('/^\S+$/', $value)) {
1272 $profiled_data[$key]["special_word"] = true;
1273 } elseif (WPRHelper::safePregMatch('/^[\w\s]+$/', $value)) {
1274 $profiled_data[$key]["regular_sentence"] = true;
1275 } elseif (WPRHelper::safePregMatch('/^[\w\W]+$/', $value)) {
1276 $profiled_data[$key]["special_chars_sentence"] = true;
1277 }
1278
1279 if (WPRHelper::safePregMatch('/^\b((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}
1280 (25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b$/x', $value)) {
1281 $profiled_data[$key]["ipv4"] = true;
1282 } elseif (WPRHelper::safePregMatch('/\b((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}
1283 (25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b/x', $value)) {
1284 $profiled_data[$key]["embeded_ipv4"] = true;
1285 } elseif (WPRHelper::safePregMatch('/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|
1286 ([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|
1287 ([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}
1288 (:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|
1289 ([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|
1290 :((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|
1291 ::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}
1292 (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|
1293 (2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/x', $value)) {
1294 $profiled_data[$key]["ipv6"] = true;
1295 } elseif (WPRHelper::safePregMatch('/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|
1296 ([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|
1297 ([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}
1298 (:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|
1299 ([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|
1300 :((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|
1301 ::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}
1302 (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|
1303 (2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/x', $value)) {
1304 $profiled_data[$key]["embeded_ipv6"] = true;
1305 }
1306
1307 if (WPRHelper::safePregMatch('/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/', $value)) {
1308 $profiled_data[$key]["email"] = true;
1309 } elseif (WPRHelper::safePregMatch('/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}/', $value)) {
1310 $profiled_data[$key]["embeded_email"] = true;
1311 }
1312
1313 if (WPRHelper::safePregMatch('/^(http|ftp)s?:\/\/\S+$/i', $value)) {
1314 $profiled_data[$key]["link"] = true;
1315 } elseif (WPRHelper::safePregMatch('/(http|ftp)s?:\/\/\S+$/i', $value)) {
1316 $profiled_data[$key]["embeded_link"] = true;
1317 }
1318
1319 if (WPRHelper::safePregMatch('/<(html|head|title|base|link|meta|style|picture|source|img|
1320 iframe|embed|object|param|video|audio|track|map|area|form|label|input|button|
1321 select|datalist|optgroup|option|textarea|output|progress|meter|fieldset|legend|
1322 script|noscript|template|slot|canvas)/ix', $value)) {
1323 $profiled_data[$key]["embeded_html"] = true;
1324 }
1325
1326 if (WPRHelper::safePregMatch('/\.(jpg|jpeg|png|gif|ico|pdf|doc|docx|ppt|pptx|pps|ppsx|odt|xls|zip|gzip|
1327 xlsx|psd|mp3|m4a|ogg|wav|mp4|m4v|mov|wmv|avi|mpg|ogv|3gp|3g2|php|html|phtml|js|css)/ix', $value)) {
1328 $profiled_data[$key]["file"] = true;
1329 }
1330
1331 if ($this->matchCount(WPRProtectFWRule_V553::SQLIREGEX, $value) > 2) {
1332 $profiled_data[$key]["sql"] = true;
1333 }
1334
1335 if (WPRHelper::safePregMatch('/(?:\.{2}[\/]+)/', $value)) {
1336 $profiled_data[$key]["path_traversal"] = true;
1337 }
1338
1339 if (WPRHelper::safePregMatch('/\\b(?i:eval)\\s*\\(\\s*(?i:base64_decode|exec|file_get_contents|gzinflate|passthru|shell_exec|stripslashes|system)\\s*\\(/', $value)) {
1340 $profiled_data[$key]["php_eval"] = true;
1341 }
1342 }
1343 }
1344 }
1345
1346 return $profiled_data;
1347 }
1348
1349 private function profileRequest() {
1350 if (!$this->is_request_profiled && !$this->isRequestProfilingDisabled()) {
1351 $profiled_data = array();
1352 $log_raw_body = true;
1353
1354 $is_debug_mode = $this->isRequestProfilingModeDebug();
1355
1356 $content_type = $this->request->getContentType();
1357 if (is_string($content_type)) {
1358 $profiled_data += array("CONTENT_TYPE" => $this->getSlicedValueToLog($content_type));
1359 }
1360
1361 $content_length = $this->request->getContentLength();
1362 if (is_string($content_length)) {
1363 $profiled_data += array("CONTENT_LENGTH" => $this->getSlicedValueToLog($content_length));
1364 }
1365
1366 $action = $this->request->getAction();
1367 if (isset($action)) {
1368 $profiled_data += $this->profileRequestData(array("action" => $action), true, 'ACTION[');
1369 }
1370
1371 if (isset($this->request->wp_user)) {
1372 $wp_user_info = array(
1373 'id' => $this->request->wp_user->id
1374 );
1375 $profiled_data += $this->profileRequestData($wp_user_info, true, 'WP_USER[');
1376 }
1377
1378 $profiled_data += $this->profileRequestData($this->request->getGetParams(), true, 'GET[');
1379 $profiled_data += $this->profileRequestData($this->request->getFiles(), true, 'FILES[');
1380
1381 $cookies = $is_debug_mode ? $this->request->getCookies() : $this->getBVCookies();
1382 $profiled_data += $this->profileRequestData($cookies, true, 'COOKIES[');
1383
1384 if (!empty($this->request->getPostParams())) {
1385 $profiled_data += $this->profileRequestData($this->request->getPostParams(), $is_debug_mode, 'BODY[');
1386 $log_raw_body = false;
1387 }
1388
1389 $json_params = $this->request->getJsonParams();
1390 if (!empty($json_params) && !empty($json_params['JSON'])) {
1391 $profiled_data += $this->profileRequestData($json_params, $is_debug_mode, 'JSON[');
1392 $log_raw_body = false;
1393 }
1394
1395 if ($this->can_log_raw_body && $is_debug_mode && $log_raw_body && !empty($this->request->getRawBody())) {
1396 $profiled_data += array("RAW_BODY" => $this->getRawBodyToLog($this->request->getRawBody()));
1397 }
1398
1399 $this->request_profiled_data = $profiled_data;
1400 $this->is_request_profiled = true;
1401 }
1402 }
1403
1404 private function isRequestIPWhitelisted() {
1405 return $this->ipstore->isFWIPWhitelisted($this->request->ip);
1406 }
1407
1408 private function canRequestBypassFirewall() {
1409 if ($this->isRequestIPWhitelisted() || $this->isRequestHasValidBypassCookie()) {
1410 $this->request->category = WPRProtectRequest_V553::CATEGORY_WHITELISTED;
1411 $this->request->status = WPRProtectRequest_V553::STATUS_BYPASSED;
1412
1413 return true;
1414 } elseif (WPRProtectUtils_V553::isPrivateIP($this->request->ip)) {
1415 $this->request->category = WPRProtectRequest_V553::CATEGORY_PRIVATEIP;
1416 $this->request->status = WPRProtectRequest_V553::STATUS_BYPASSED;
1417
1418 return true;
1419 }
1420
1421 return false;
1422 }
1423
1424 private function blockRequestForBlacklistedIP() {
1425 if (!$this->canRequestBypassFirewall() && $this->isModeProtect()) {
1426 if (!$this->is_ip_checked_for_blacklisted ||
1427 ($this->isWPMode() && $this->isGeoBlockingEnabled())) {
1428
1429 $ip_category = $this->ipstore->getTypeIfBlacklistedIP($this->request->ip);
1430 if ($ip_category) {
1431 $this->terminateRequest($ip_category);
1432 }
1433
1434 $this->is_ip_checked_for_blacklisted = true;
1435 }
1436 }
1437 }
1438
1439 private function handleRequestOnRuleMatch($rules, $engine_vars = array(), $log_data = array()) {
1440 foreach ($rules as $rule) {
1441 if ($this->break_rule_matching) {
1442 break;
1443 }
1444
1445 $_engine_vars = $engine_vars;
1446 if (array_key_exists('variables', $rule->opts)) {
1447 $_engine_vars = array_merge($_engine_vars, $rule->opts['variables']);
1448 }
1449
1450 $rule_engine = new WPRProtectFWRuleEngine_V553($this->request, $_engine_vars);
1451
1452 if ($rule_engine->evaluate($rule) && !$rule_engine->hasError()) {
1453 if (!empty($log_data)) {
1454 $this->updateRuleLog("info", (string) $rule->id, $log_data);
1455 }
1456
1457 $this->matched_rules[] = $rule->id;
1458
1459 foreach($rule->actions as $action) {
1460 switch ($action["type"]) {
1461 case "ALLOW":
1462 $this->break_rule_matching = true;
1463 $this->request->category = WPRProtectRequest_V553::CATEGORY_RULE_ALLOWED;
1464 return;
1465 case "BLOCK":
1466 if ($this->isModeProtect()) {
1467 $this->terminateRequest(WPRProtectRequest_V553::CATEGORY_RULE_BLOCKED);
1468 }
1469 return;
1470 case "INSPECT":
1471 $this->inspectRequest();
1472 break;
1473 }
1474 }
1475 } elseif ($rule_engine->hasError()) {
1476 $this->updateRuleLog("errors", (string) $rule->id, $rule_engine->getErrorMessage());
1477 }
1478 }
1479 }
1480
1481 private function terminateRequest($category) {
1482 $this->request->category = $category;
1483 $this->request->status = WPRProtectRequest_V553::STATUS_BLOCKED;
1484 $this->request->setRespCode(403);
1485
1486 if ($this->can_set_cache_prevention_cookie &&
1487 !$this->request->getCookies(WPRProtectFW_V553::PREVENT_CACHE_COOKIE_NAME)) {
1488 $value = "Prevent Caching Response.";
1489 $this->setCookie(WPRProtectFW_V553::PREVENT_CACHE_COOKIE_NAME, $value, time() + 43200);
1490 }
1491
1492 header("Cache-Control: no-cache, no-store, must-revalidate");
1493 header("Pragma: no-cache");
1494 header("Expires: 0");
1495 header('HTTP/1.0 403 Forbidden');
1496 die("
1497 <div style='height: 98vh;'>
1498 <div style='text-align: center; padding: 10% 0; font-family: Arial, Helvetica, sans-serif;'>
1499 <div><p>" . $this->brand_name . " Firewall</p></div>
1500 <p>Blocked because of Malicious Activities</p>
1501 <p>Reference ID: " . $this->request->getRequestID() . "</p>
1502 </div>
1503 </div>
1504 ");
1505 }
1506
1507 public function setBypassCookie() {
1508 if (function_exists('is_user_logged_in') && is_user_logged_in() &&
1509 !$this->isRequestHasValidBypassCookie()) {
1510
1511 $role_level = $this->getCurrentWPUserRoleLevel();
1512 if ($role_level >= $this->bypass_level) {
1513 $cookie = $this->generateBypassCookie();
1514 if ($cookie) {
1515 $this->setCookie(WPRProtectFW_V553::BYPASS_COOKIE_NAME, $cookie, time() + 43200);
1516 }
1517 }
1518 }
1519 }
1520 }
1521 endif;