PluginProbe
The WP Remote WordPress Plugin / 4.86
The WP Remote WordPress Plugin v4.86
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 / fw.php

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

545 lines 22.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (! (defined('ABSPATH') || defined('MCDATAPATH')) ) exit;
4 if (!class_exists('BVFW')) :
5
6 require_once dirname( __FILE__ ) . '/rule_evaluator.php';
7
8 class BVFW {
9 public $bvinfo;
10 public $request;
11 public $config;
12 public $ipstore;
13 public $category;
14 public $logger;
15 public $generic_rule_set = array();
16 public $wpf_rule_set = array();
17 public $ruleEvaluator;
18 public $break_rule_evaluation;
19 public $ruleActions = array();
20 private static $instance = null;
21
22 #RuleLevels
23 const GENERIC = 1;
24 const WPF = 2;
25
26 const SQLIREGEX = '/(?:[^\\w<]|\\/\\*\\![0-9]*|^)(?:
27 @@HOSTNAME|
28 ALTER|ANALYZE|ASENSITIVE|
29 BEFORE|BENCHMARK|BETWEEN|BIGINT|BINARY|BLOB|
30 CALL|CASE|CHANGE|CHAR|CHARACTER|CHAR_LENGTH|COLLATE|COLUMN|CONCAT|CONDITION|CONSTRAINT|CONTINUE|CONVERT|CREATE|CROSS|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|
31 DATABASE|DATABASES|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DECIMAL|DECLARE|DEFAULT|DELAYED|DELETE|DESCRIBE|DETERMINISTIC|DISTINCT|DISTINCTROW|DOUBLE|DROP|DUAL|DUMPFILE|
32 EACH|ELSE|ELSEIF|ELT|ENCLOSED|ESCAPED|EXISTS|EXIT|EXPLAIN|EXTRACTVALUE|
33 FETCH|FLOAT|FLOAT4|FLOAT8|FORCE|FOREIGN|FROM|FULLTEXT|
34 GRANT|GROUP|HAVING|HEX|HIGH_PRIORITY|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|
35 IFNULL|IGNORE|INDEX|INFILE|INNER|INOUT|INSENSITIVE|INSERT|INTERVAL|ISNULL|ITERATE|
36 JOIN|KILL|LEADING|LEAVE|LIMIT|LINEAR|LINES|LOAD|LOAD_FILE|LOCALTIME|LOCALTIMESTAMP|LOCK|LONG|LONGBLOB|LONGTEXT|LOOP|LOW_PRIORITY|
37 MASTER_SSL_VERIFY_SERVER_CERT|MATCH|MAXVALUE|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MID|MIDDLEINT|MINUTE_MICROSECOND|MINUTE_SECOND|MODIFIES|
38 NATURAL|NO_WRITE_TO_BINLOG|NULL|NUMERIC|OPTION|ORD|ORDER|OUTER|OUTFILE|
39 PRECISION|PRIMARY|PRIVILEGES|PROCEDURE|PROCESSLIST|PURGE|
40 RANGE|READ_WRITE|REGEXP|RELEASE|REPEAT|REQUIRE|RESIGNAL|RESTRICT|RETURN|REVOKE|RLIKE|ROLLBACK|
41 SCHEMA|SCHEMAS|SECOND_MICROSECOND|SELECT|SENSITIVE|SEPARATOR|SHOW|SIGNAL|SLEEP|SMALLINT|SPATIAL|SPECIFIC|SQLEXCEPTION|SQLSTATE|SQLWARNING|SQL_BIG_RESULT|SQL_CALC_FOUND_ROWS|SQL_SMALL_RESULT|STARTING|STRAIGHT_JOIN|SUBSTR|
42 TABLE|TERMINATED|TINYBLOB|TINYINT|TINYTEXT|TRAILING|TRANSACTION|TRIGGER|
43 UNDO|UNHEX|UNION|UNLOCK|UNSIGNED|UPDATE|UPDATEXML|USAGE|USING|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|
44 VALUES|VARBINARY|VARCHAR|VARCHARACTER|VARYING|WHEN|WHERE|WHILE|WRITE|YEAR_MONTH|ZEROFILL)(?=[^\\w]|$)/ix';
45
46 const XSSREGEX = '/(?:
47 #tags
48 (?:\\<|\\+ADw\\-|\\xC2\\xBC)(script|iframe|svg|object|embed|applet|link|style|meta|\\/\\/|\\?xml\\-stylesheet)(?:[^\\w]|\\xC2\\xBE)|
49 #protocols
50 (?:^|[^\\w])(?:(?:\\s*(?:&\\#(?:x0*6a|0*106)|j)\\s*(?:&\\#(?:x0*61|0*97)|a)\\s*(?:&\\#(?:x0*76|0*118)|v)\\s*(?:&\\#(?:x0*61|0*97)|a)|\\s*(?:&\\#(?:x0*76|0*118)|v)\\s*(?:&\\#(?:x0*62|0*98)|b)|\\s*(?:&\\#(?:x0*65|0*101)|e)\\s*(?:&\\#(?:x0*63|0*99)|c)\\s*(?:&\\#(?:x0*6d|0*109)|m)\\s*(?:&\\#(?:x0*61|0*97)|a)|\\s*(?:&\\#(?:x0*6c|0*108)|l)\\s*(?:&\\#(?:x0*69|0*105)|i)\\s*(?:&\\#(?:x0*76|0*118)|v)\\s*(?:&\\#(?:x0*65|0*101)|e))\\s*(?:&\\#(?:x0*73|0*115)|s)\\s*(?:&\\#(?:x0*63|0*99)|c)\\s*(?:&\\#(?:x0*72|0*114)|r)\\s*(?:&\\#(?:x0*69|0*105)|i)\\s*(?:&\\#(?:x0*70|0*112)|p)\\s*(?:&\\#(?:x0*74|0*116)|t)|\\s*(?:&\\#(?:x0*6d|0*109)|m)\\s*(?:&\\#(?:x0*68|0*104)|h)\\s*(?:&\\#(?:x0*74|0*116)|t)\\s*(?:&\\#(?:x0*6d|0*109)|m)\\s*(?:&\\#(?:x0*6c|0*108)|l)|\\s*(?:&\\#(?:x0*6d|0*109)|m)\\s*(?:&\\#(?:x0*6f|0*111)|o)\\s*(?:&\\#(?:x0*63|0*99)|c)\\s*(?:&\\#(?:x0*68|0*104)|h)\\s*(?:&\\#(?:x0*61|0*97)|a)|\\s*(?:&\\#(?:x0*64|0*100)|d)\\s*(?:&\\#(?:x0*61|0*97)|a)\\s*(?:&\\#(?:x0*74|0*116)|t)\\s*(?:&\\#(?:x0*61|0*97)|a)(?!(?:&\\#(?:x0*3a|0*58)|\\:)(?:&\\#(?:x0*69|0*105)|i)(?:&\\#(?:x0*6d|0*109)|m)(?:&\\#(?:x0*61|0*97)|a)(?:&\\#(?:x0*67|0*103)|g)(?:&\\#(?:x0*65|0*101)|e)(?:&\\#(?:x0*2f|0*47)|\\/)(?:(?:&\\#(?:x0*70|0*112)|p)(?:&\\#(?:x0*6e|0*110)|n)(?:&\\#(?:x0*67|0*103)|g)|(?:&\\#(?:x0*62|0*98)|b)(?:&\\#(?:x0*6d|0*109)|m)(?:&\\#(?:x0*70|0*112)|p)|(?:&\\#(?:x0*67|0*103)|g)(?:&\\#(?:x0*69|0*105)|i)(?:&\\#(?:x0*66|0*102)|f)|(?:&\\#(?:x0*70|0*112)|p)?(?:&\\#(?:x0*6a|0*106)|j)(?:&\\#(?:x0*70|0*112)|p)(?:&\\#(?:x0*65|0*101)|e)(?:&\\#(?:x0*67|0*103)|g)|(?:&\\#(?:x0*74|0*116)|t)(?:&\\#(?:x0*69|0*105)|i)(?:&\\#(?:x0*66|0*102)|f)(?:&\\#(?:x0*66|0*102)|f)|(?:&\\#(?:x0*73|0*115)|s)(?:&\\#(?:x0*76|0*118)|v)(?:&\\#(?:x0*67|0*103)|g)(?:&\\#(?:x0*2b|0*43)|\\+)(?:&\\#(?:x0*78|0*120)|x)(?:&\\#(?:x0*6d|0*109)|m)(?:&\\#(?:x0*6c|0*108)|l))(?:(?:&\\#(?:x0*3b|0*59)|;)(?:&\\#(?:x0*63|0*99)|c)(?:&\\#(?:x0*68|0*104)|h)(?:&\\#(?:x0*61|0*97)|a)(?:&\\#(?:x0*72|0*114)|r)(?:&\\#(?:x0*73|0*115)|s)(?:&\\#(?:x0*65|0*101)|e)(?:&\\#(?:x0*74|0*116)|t)(?:&\\#(?:x0*3d|0*61)|=)[\\-a-z0-9]+)?(?:(?:&\\#(?:x0*3b|0*59)|;)(?:&\\#(?:x0*62|0*98)|b)(?:&\\#(?:x0*61|0*97)|a)(?:&\\#(?:x0*73|0*115)|s)(?:&\\#(?:x0*65|0*101)|e)(?:&\\#(?:x0*36|0*54)|6)(?:&\\#(?:x0*34|0*52)|4))?(?:&\\#(?:x0*2c|0*44)|,)))\\s*(?:&\\#(?:x0*3a|0*58)|&colon|\\:)|
51 #css expression
52 (?:^|[^\\w])(?:(?:\\\\0*65|\\\\0*45|e)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*78|\\\\0*58|x)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*70|\\\\0*50|p)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*72|\\\\0*52|r)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*65|\\\\0*45|e)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*73|\\\\0*53|s)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*73|\\\\0*53|s)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*69|\\\\0*49|i)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*6f|\\\\0*4f|o)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*6e|\\\\0*4e|n))[^\\w]*?(?:\\\\0*28|\\()|
53 #css properties
54 (?:^|[^\\w])(?:(?:(?:\\\\0*62|\\\\0*42|b)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*65|\\\\0*45|e)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*68|\\\\0*48|h)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*61|\\\\0*41|a)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*76|\\\\0*56|v)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*69|\\\\0*49|i)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*6f|\\\\0*4f|o)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*72|\\\\0*52|r)(?:\\/\\*.*?\\*\\/)*)|(?:(?:\\\\0*2d|\\\\0*2d|-)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*6d|\\\\0*4d|m)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*6f|\\\\0*4f|o)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*7a|\\\\0*5a|z)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*2d|\\\\0*2d|-)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*62|\\\\0*42|b)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*69|\\\\0*49|i)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*6e|\\\\0*4e|n)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*64|\\\\0*44|d)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*69|\\\\0*49|i)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*6e|\\\\0*4e|n)(?:\\/\\*.*?\\*\\/)*(?:\\\\0*67|\\\\0*47|g)(?:\\/\\*.*?\\*\\/)*))[^\\w]*(?:\\\\0*3a|\\\\0*3a|:)[^\\w]*(?:\\\\0*75|\\\\0*55|u)(?:\\\\0*72|\\\\0*52|r)(?:\\\\0*6c|\\\\0*4c|l)|
55 #properties
56 (?:^|[^\\w])(?:on(?:abort|activate|afterprint|afterupdate|autocomplete|autocompleteerror|beforeactivate|beforecopy|beforecut|beforedeactivate|beforeeditfocus|beforepaste|beforeprint|beforeunload|beforeupdate|blur|bounce|cancel|canplay|canplaythrough|cellchange|change|click|close|contextmenu|controlselect|copy|cuechange|cut|dataavailable|datasetchanged|datasetcomplete|dblclick|deactivate|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|encrypted|ended|error|errorupdate|filterchange|finish|focus|focusin|focusout|formchange|forminput|hashchange|help|input|invalid|keydown|keypress|keyup|languagechange|layoutcomplete|load|loadeddata|loadedmetadata|loadstart|losecapture|message|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|move|moveend|movestart|mozfullscreenchange|mozfullscreenerror|mozpointerlockchange|mozpointerlockerror|offline|online|page|pagehide|pageshow|paste|pause|play|playing|popstate|progress|propertychange|ratechange|readystatechange|reset|resize|resizeend|resizestart|rowenter|rowexit|rowsdelete|rowsinserted|scroll|search|seeked|seeking|select|selectstart|show|stalled|start|storage|submit|suspend|timer|timeupdate|toggle|unload|volumechange|waiting|webkitfullscreenchange|webkitfullscreenerror|wheel)|formaction|data\\-bind|ev:event)[^\\w]
57 )/ix';
58
59 const BYPASS_COOKIE = "bvfw-bypass-cookie";
60 const IP_COOKIE = "bvfw-ip-cookie";
61 const PREVENT_CACHE_COOKIE = "wp-bvfw-prevent-cache-cookie";
62
63 #singleton design
64 private function __construct($logger, $confHash, $ip, $bvinfo, $ipstore, $ruleSet) {
65 $this->config = new BVFWConfig($confHash);
66 $this->request = new BVWPRequest($ip);
67 $this->bvinfo = $bvinfo;
68 $this->ipstore = $ipstore;
69 $this->logger = $logger;
70 $this->initializeLevelWiseRuleSets($ruleSet);
71 $this->ruleEvaluator = new BVFWRuleEvaluator($this);
72 $this->break_rule_evaluation = false;
73 }
74
75 public static function getInstance($logger, $confHash, $ip, $bvinfo, $ipstore, $ruleSet) {
76 if (!isset(self::$instance)) {
77 self::$instance = new BVFW($logger, $confHash, $ip, $bvinfo, $ipstore, $ruleSet);
78 } else {
79 self::$instance->ipstore = $ipstore;
80 }
81 return self::$instance;
82 }
83
84 public function setcookie($name, $value, $expire) {
85 $path = $this->config->cookiePath;
86 $cookie_domain = $this->config->cookieDomain;
87
88 if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
89 $secure = function_exists('is_ssl') ? is_ssl() : false;
90 @setcookie($name, $value, $expire, $path, $cookie_domain, $secure, true);
91 } else {
92 @setcookie($name, $value, $expire, $path);
93 }
94 }
95
96 public function setBypassCookie() {
97 if (function_exists('is_user_logged_in') && is_user_logged_in() && !$this->hasValidBypassCookie()) {
98 $roleLevel = $this->getCurrentRoleLevel();
99 $bypassLevel = $this->config->bypassLevel;
100 if ($roleLevel >= $bypassLevel) {
101 $cookie = $this->generateBypassCookie();
102 $this->setcookie(BVFW::BYPASS_COOKIE, $cookie, time() + 43200);
103 }
104 }
105 }
106
107 public function generateBypassCookie() {
108 $time = floor(time() / 43200);
109 $bypassLevel = $this->config->bypassLevel;
110 $cookiekey = $this->config->cookieKey;
111 return sha1($bypassLevel.$time.$cookiekey);
112 }
113
114 public function hasValidBypassCookie() {
115 $cookie = (string) $this->request->getCookies(BVFW::BYPASS_COOKIE);
116 return ($this->canSetAdminCookie() && ($cookie === $this->generateBypassCookie()));
117 }
118
119 public function setIPCookie() {
120 if (!$this->request->getCookies(BVFW::IP_COOKIE)) {
121 $ip = $this->request->getIP();
122 $cookiekey = $this->config->cookieKey;
123 $time = floor(time() / 86400);
124 $cookie = sha1($ip.$time.$cookiekey);
125 $this->setcookie(BVFW::IP_COOKIE, $cookie, time() + 86400);
126 }
127 }
128
129 public function getBVCookies() {
130 $cookies = array();
131 if ($this->request->getCookies(BVFW::IP_COOKIE) !== NULL) {
132 $cookies[BVFW::IP_COOKIE] = (string) $this->request->getCookies(BVFW::IP_COOKIE);
133 }
134 return $cookies;
135 }
136
137 public function getCurrentRoleLevel() {
138 if (function_exists('current_user_can')) {
139 if (function_exists('is_super_admin') && is_super_admin()) {
140 return BVFWConfig::ROLE_LEVEL_ADMIN;
141 }
142 foreach ($this->config->customRoles as $role) {
143 if (current_user_can($role)) {
144 return BVFWConfig::ROLE_LEVEL_CUSTOM;
145 }
146 }
147 foreach (BVFWConfig::$roleLevels as $role => $level) {
148 if (current_user_can($role)) {
149 return $level;
150 }
151 }
152 }
153 return 0;
154 }
155
156 public function isActive() {
157 return $this->config->isActive();
158 }
159
160 public function isGeoBlocking() {
161 return $this->config->isGeoBlocking;
162 }
163
164 public function canSetAdminCookie() {
165 return ($this->config->adminCookieMode === BVFWConfig::ADMIN_COOKIE_MODE_ENABLED);
166 }
167
168 public function canSetIPCookie() {
169 return ($this->config->ipCookieMode === BVFWConfig::IP_COOKIE_MODE_ENABLED);
170 }
171
172 public function setResponseCode() {
173 if (!function_exists('http_response_code')) {
174 return false;
175 }
176
177 $this->request->setRespCode(http_response_code());
178 return true;
179 }
180
181 public function canLog() {
182 $canlog = false;
183
184 if ($this->config->isCompleteLoggingEnabled()) {
185 $canlog = true;
186 } else if ($this->config->isVisitorLoggingEnabled()) {
187 $canlog = ($this->request->hasMatchedRules()) || (!$this->hasValidBypassCookie() &&
188 (!function_exists('is_user_logged_in') || !is_user_logged_in()));
189 }
190 return $canlog;
191 }
192
193 public function log() {
194 if ($this->canLog()) {
195 $this->setResponseCode();
196 $this->logger->log($this->request->getDataToLog());
197 }
198 }
199
200 public function terminateRequest($category) {
201 $this->request->setCategory($category);
202 $this->request->setStatus(BVWPRequest::BLOCKED);
203 $this->request->setRespCode(403);
204
205 if ($this->config->canSetCachePreventionCookie &&
206 !$this->request->getCookies(BVFW::PREVENT_CACHE_COOKIE)) {
207 $value = "Prevent Caching Response.";
208 $this->setcookie(BVFW::PREVENT_CACHE_COOKIE, $value, time() + 43200);
209 }
210
211 header("Cache-Control: no-cache, no-store, must-revalidate");
212 header("Pragma: no-cache");
213 header("Expires: 0");
214 header('HTTP/1.0 403 Forbidden');
215 $brandname = $this->bvinfo->getBrandName().' Firewall';
216 die("
217 <div style='height: 98vh;'>
218 <div style='text-align: center; padding: 10% 0; font-family: Arial, Helvetica, sans-serif;'>
219 <div><p>$brandname</p></div>
220 <p>Blocked because of Malicious Activities</p>
221 <p>Reference ID: " . $this->request->getRequestID() . "</p>
222 </div>
223 </div>
224 ");
225 }
226
227 public function isBlacklistedIP() {
228 return $this->ipstore->isFWIPBlacklisted($this->request->getIP());
229 }
230
231 public function isWhitelistedIP() {
232 return $this->ipstore->isFWIPWhitelisted($this->request->getIP());
233 }
234
235 public function canBypassFirewall() {
236 if ($this->isWhitelistedIP() || $this->hasValidBypassCookie()) {
237 $this->request->setCategory(BVWPRequest::WHITELISTED);
238 $this->request->setStatus(BVWPRequest::BYPASSED);
239 return true;
240 } else if(BVProtectBase::isPrivateIP($this->request->getIP())) {
241 $this->request->setCategory(BVWPRequest::PRIVATEIP);
242 $this->request->setStatus(BVWPRequest::BYPASSED);
243 return true;
244 }
245 return false;
246 }
247
248 public function canLogValue($key) {
249 $skip_keys = array('password' => true, 'passwd' => true, 'pwd' => true);
250 if (isset($skip_keys[$key])) {
251 return false;
252 }
253 return true;
254 }
255
256 public function blockIfBlacklisted() {
257 if (!$this->canBypassFirewall() && $this->config->isProtecting()) {
258 if ($this->isBlacklistedIP()) {
259 $this->terminateRequest(BVWPRequest::BLACKLISTED);
260 }
261 }
262 }
263
264 public function execute() {
265 if ($this->config->canProfileReqInfo()) {
266 $result = array();
267 $has_debug_mode = $this->config->isReqProfilingModeDebug();
268 $action = $this->request->getAction();
269 if (isset($action)) {
270 $result += $this->profileRequestInfo(array("action" => $action),
271 true, 'ACTION[');
272 }
273 $result += $this->profileRequestInfo($this->request->getPostParams(),
274 $has_debug_mode, 'BODY[');
275 $result += $this->profileRequestInfo($this->request->getGetParams(),
276 true, 'GET[');
277 $result += $this->profileRequestInfo($this->request->getFiles(),
278 true, 'FILES[');
279 $cookies = $has_debug_mode ? $this->request->getCookies() : $this->getBVCookies();
280 $result += $this->profileRequestInfo($cookies, true, 'COOKIES[');
281 $this->request->updateReqInfo($result);
282 }
283 $this->blockIfBlacklisted();
284 }
285
286 public function canExecuteRules() {
287 if (!$this->isWhitelistedIP() && $this->config->isRulesModeEnabled()) {
288 return true;
289 }
290 return false;
291 }
292
293 public function initializeLevelWiseRuleSets($rule_set) {
294 if (!is_array($rule_set)) {
295 $this->request->updateRulesInfo('errors', 'ruleset', 'Invalid RuleSet');
296 return;
297 }
298
299 foreach ($rule_set as $rule) {
300 if (BVFWRuleEvaluator::VERSION >= $rule["min_rule_engine_ver"]) {
301 if (array_key_exists("level", $rule) && $rule["level"] == BVFW::WPF) {
302 array_push($this->wpf_rule_set, $rule);
303 } else {
304 array_push($this->generic_rule_set, $rule);
305 }
306 }
307 }
308 }
309
310 public function ruleSetToExecute() {
311 $rule_set = array();
312 if ($this->isWpLoaded()) {
313 $rule_set = $this->wpf_rule_set;
314 }
315 if (!defined('MCWAFLOADED') && !$this->hasValidBypassCookie()) {
316 $rule_set = array_merge($rule_set, $this->generic_rule_set);
317 }
318 return $rule_set;
319 }
320
321 public function executeRules() {
322 if (!$this->canExecuteRules()) {
323 return;
324 }
325
326 $rule_set = $this->ruleSetToExecute();
327 $this->evaluateRules($rule_set);
328 }
329
330 public function matchCount($pattern, $subject) {
331 $count = 0;
332 if (is_array($subject)) {
333 foreach ($subject as $val) {
334 $count += $this->matchCount($pattern, $val);
335 }
336 return $count;
337 } else {
338 $count = preg_match_all((string) $pattern, (string) $subject, $matches);
339 return ($count === false ? 0 : $count);
340 }
341 }
342
343 public function getLength($val) {
344 $length = 0;
345 if (is_array($val)) {
346 foreach ($val as $v) {
347 $length += $this->getLength($v);
348 }
349 return $length;
350 } else {
351 return strlen((string) $val);
352 }
353 }
354
355 public function profileRequestInfo($params, $debug = false, $prefix = '', $obraces = 1) {
356 $result = array();
357 if (is_array($params)) {
358 foreach ($params as $key => $value) {
359 $original_key = $key;
360 $key = $prefix . $key;
361 if (is_array($value)) {
362 $result = $result + $this->profileRequestInfo($value, $debug, $key . '[', $obraces + 1);
363 } else {
364 $key = $key . str_repeat(']', $obraces);
365 $result[$key] = array();
366 $valsize = $this->getLength($value);
367 $result[$key]["size"] = $valsize;
368 if ($debug === true && $valsize < 256 && $this->canLogValue($original_key)) {
369 $result[$key]["value"] = $value;
370 continue;
371 }
372
373 if (preg_match('/^\d+$/', $value)) {
374 $result[$key]["numeric"] = true;
375 } else if (preg_match('/^\w+$/', $value)) {
376 $result[$key]["regular_word"] = true;
377 } else if (preg_match('/^\S+$/', $value)) {
378 $result[$key]["special_word"] = true;
379 } else if (preg_match('/^[\w\s]+$/', $value)) {
380 $result[$key]["regular_sentence"] = true;
381 } else if (preg_match('/^[\w\W]+$/', $value)) {
382 $result[$key]["special_chars_sentence"] = true;
383 }
384
385 if (preg_match('/^\b((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}
386 (25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b$/x', $value)) {
387 $result[$key]["ipv4"] = true;
388 } else if (preg_match('/\b((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}
389 (25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b/x', $value)) {
390 $result[$key]["embeded_ipv4"] = true;
391 } else if (preg_match('/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|
392 ([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|
393 ([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}
394 (:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|
395 ([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})|
396 :((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|
397 ::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}
398 (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]|
399 (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)) {
400 $result[$key]["ipv6"] = true;
401 } else if (preg_match('/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|
402 ([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|
403 ([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}
404 (:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|
405 ([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})|
406 :((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|
407 ::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}
408 (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]|
409 (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)) {
410 $result[$key]["embeded_ipv6"] = true;
411 }
412
413 if (preg_match('/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/', $value)) {
414 $result[$key]["email"] = true;
415 } else if (preg_match('/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}/', $value)) {
416 $result[$key]["embeded_email"] = true;
417 }
418
419 if (preg_match('/^(http|ftp)s?:\/\/\S+$/i', $value)) {
420 $result[$key]["link"] = true;
421 } else if (preg_match('/(http|ftp)s?:\/\/\S+$/i', $value)) {
422 $result[$key]["embeded_link"] = true;
423 }
424
425 if (preg_match('/<(html|head|title|base|link|meta|style|picture|source|img|
426 iframe|embed|object|param|video|audio|track|map|area|form|label|input|button|
427 select|datalist|optgroup|option|textarea|output|progress|meter|fieldset|legend|
428 script|noscript|template|slot|canvas)/ix', $value)) {
429 $result[$key]["embeded_html"] = true;
430 }
431
432 if (preg_match('/\.(jpg|jpeg|png|gif|ico|pdf|doc|docx|ppt|pptx|pps|ppsx|odt|xls|zip|gzip|
433 xlsx|psd|mp3|m4a|ogg|wav|mp4|m4v|mov|wmv|avi|mpg|ogv|3gp|3g2|php|html|phtml|js|css)/ix', $value)) {
434 $result[$key]["file"] = true;
435 }
436
437 if ($this->matchCount(BVFW::SQLIREGEX, $value) > 2) {
438 $result[$key]["sql"] = true;
439 }
440
441 if (preg_match('/(?:\.{2}[\/]+)/', $value)) {
442 $result[$key]["path_traversal"] = true;
443 }
444
445 if (preg_match('/\\b(?i:eval)\\s*\\(\\s*(?i:base64_decode|exec|file_get_contents|gzinflate|passthru|shell_exec|stripslashes|system)\\s*\\(/', $value)) {
446 $result[$key]["php_eval"] = true;
447 }
448 }
449 }
450 }
451 return $result;
452 }
453
454 public function evaluateRules($ruleSet) {
455 foreach ($ruleSet as $rule) {
456 $id = $rule["id"];
457 $ruleLogic = $rule["rule_logic"];
458 $this->ruleActions[$id] = $rule["actions"];
459 $this->ruleEvaluator->resetErrors();
460
461 if ($this->ruleEvaluator->evaluateRule($ruleLogic) && empty($this->ruleEvaluator->getErrors())) {
462 $this->handleMatchedRule($id);
463 } elseif (!empty($this->ruleEvaluator->getErrors())) {
464 $this->request->updateRulesInfo("errors", (string) $id, $this->ruleEvaluator->getErrors());
465 }
466
467 if ($this->break_rule_evaluation) {
468 return;
469 }
470 }
471 }
472
473 function handleMatchedRule($id) {
474 $this->request->updateMatchedRules($id);
475 $this->executeActions($id);
476 }
477
478 function executeActions($id){
479 foreach($this->ruleActions[$id] as $action) {
480 switch ($action["type"]) {
481 case "ALLOW":
482 $this->break_rule_evaluation = true;
483 $this->request->setCategory(BVWPRequest::RULE_ALLOWED);
484 return;
485 case "BLOCK":
486 if ($this->config->isProtecting()) {
487 $this->terminateRequest(BVWPRequest::RULE_BLOCKED);
488 }
489 return;
490 case "INSPECT":
491 $this->inspectRequest();
492 break;
493 }
494 }
495 }
496
497 function isWPLoaded() {
498 return defined('BVWPLOADED');
499 }
500
501 function getCurrentWPUser() {
502 if (!$this->isWPLoaded()) {
503 return;
504 }
505 if (!function_exists('wp_get_current_user')) {
506 @include_once(ABSPATH . "wp-includes/pluggable.php");
507 }
508 return wp_get_current_user();
509 }
510
511 public function inspectRequest() {
512 $this->request->updateRulesInfo('inspect', "headers", $this->request->getHeaders());
513
514 $wp_user = $this->getCurrentWPUser();
515 if ($wp_user && isset($wp_user->ID)) {
516 $this->request->updateRulesInfo('inspect', "userID", $wp_user->ID);
517 }
518
519 $this->request->updateRulesInfo('inspect', "getParams", $this->request->getGetParams());
520 $this->request->updateRulesInfo('inspect', "postParams", $this->getPostParamsToLog($this->request->getPostParams()));
521 $this->request->updateRulesInfo('inspect', "cookies", $this->request->getCookies());
522 }
523
524 function getPostParamsToLog($params) {
525 $result = array();
526 if (is_array($params)) {
527 foreach ($params as $key => $value) {
528 if (is_array($value)) {
529 $result[$key] = $this->getPostParamsToLog($value);
530 } else {
531 $valsize = $this->getLength($value);
532 if ($valsize > 1024) {
533 $result[$key] = "Data too long: {$valsize}";
534 } elseif (!$this->canLogValue($key)) {
535 $result[$key] = "Sensitive Data";
536 } else {
537 $result[$key] = $value;
538 }
539 }
540 }
541 }
542 return $result;
543 }
544 }
545 endif;