PluginProbe
The WP Remote WordPress Plugin / 5.72
The WP Remote WordPress Plugin v5.72
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.72, at protect/fw.php

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