PluginProbe
The WP Remote WordPress Plugin / 6.48
The WP Remote WordPress Plugin v6.48
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 6.48, at protect/fw.php

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