PluginProbe
The WP Remote WordPress Plugin / 4.76
The WP Remote WordPress Plugin v4.76
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.76, at protect/fw/fw.php

464 lines 20.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 $ruleSet;
16 public $ruleEvaluator;
17 public $break_rule_evaluation;
18
19 const SQLIREGEX = '/(?:[^\\w<]|\\/\\*\\![0-9]*|^)(?:
20 @@HOSTNAME|
21 ALTER|ANALYZE|ASENSITIVE|
22 BEFORE|BENCHMARK|BETWEEN|BIGINT|BINARY|BLOB|
23 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|
24 DATABASE|DATABASES|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DECIMAL|DECLARE|DEFAULT|DELAYED|DELETE|DESCRIBE|DETERMINISTIC|DISTINCT|DISTINCTROW|DOUBLE|DROP|DUAL|DUMPFILE|
25 EACH|ELSE|ELSEIF|ELT|ENCLOSED|ESCAPED|EXISTS|EXIT|EXPLAIN|EXTRACTVALUE|
26 FETCH|FLOAT|FLOAT4|FLOAT8|FORCE|FOREIGN|FROM|FULLTEXT|
27 GRANT|GROUP|HAVING|HEX|HIGH_PRIORITY|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|
28 IFNULL|IGNORE|INDEX|INFILE|INNER|INOUT|INSENSITIVE|INSERT|INTERVAL|ISNULL|ITERATE|
29 JOIN|KILL|LEADING|LEAVE|LIMIT|LINEAR|LINES|LOAD|LOAD_FILE|LOCALTIME|LOCALTIMESTAMP|LOCK|LONG|LONGBLOB|LONGTEXT|LOOP|LOW_PRIORITY|
30 MASTER_SSL_VERIFY_SERVER_CERT|MATCH|MAXVALUE|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MID|MIDDLEINT|MINUTE_MICROSECOND|MINUTE_SECOND|MODIFIES|
31 NATURAL|NO_WRITE_TO_BINLOG|NULL|NUMERIC|OPTION|ORD|ORDER|OUTER|OUTFILE|
32 PRECISION|PRIMARY|PRIVILEGES|PROCEDURE|PROCESSLIST|PURGE|
33 RANGE|READ_WRITE|REGEXP|RELEASE|REPEAT|REQUIRE|RESIGNAL|RESTRICT|RETURN|REVOKE|RLIKE|ROLLBACK|
34 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|
35 TABLE|TERMINATED|TINYBLOB|TINYINT|TINYTEXT|TRAILING|TRANSACTION|TRIGGER|
36 UNDO|UNHEX|UNION|UNLOCK|UNSIGNED|UPDATE|UPDATEXML|USAGE|USING|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|
37 VALUES|VARBINARY|VARCHAR|VARCHARACTER|VARYING|WHEN|WHERE|WHILE|WRITE|YEAR_MONTH|ZEROFILL)(?=[^\\w]|$)/ix';
38
39 const XSSREGEX = '/(?:
40 #tags
41 (?:\\<|\\+ADw\\-|\\xC2\\xBC)(script|iframe|svg|object|embed|applet|link|style|meta|\\/\\/|\\?xml\\-stylesheet)(?:[^\\w]|\\xC2\\xBE)|
42 #protocols
43 (?:^|[^\\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|\\:)|
44 #css expression
45 (?:^|[^\\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|\\()|
46 #css properties
47 (?:^|[^\\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)|
48 #properties
49 (?:^|[^\\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]
50 )/ix';
51
52 const BYPASS_COOKIE = "bvfw-bypass-cookie";
53 const IP_COOKIE = "bvfw-ip-cookie";
54 const PREVENT_CACHE_COOKIE = "wp-bvfw-prevent-cache-cookie";
55
56 public function __construct($logger, $confHash, $ip, $bvinfo, $ipstore, $ruleSet) {
57 $this->config = new BVFWConfig($confHash);
58 $this->request = new BVWPRequest($ip);
59 $this->bvinfo = $bvinfo;
60 $this->ipstore = $ipstore;
61 $this->logger = $logger;
62 $this->ruleSet = $ruleSet;
63 $this->ruleEvaluator = new BVFWRuleEvaluator($this->request);
64 $this->break_rule_evaluation = false;
65 }
66
67 public function setcookie($name, $value, $expire) {
68 $path = $this->config->cookiePath;
69 $cookie_domain = $this->config->cookieDomain;
70
71 if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
72 $secure = function_exists('is_ssl') ? is_ssl() : false;
73 @setcookie($name, $value, $expire, $path, $cookie_domain, $secure, true);
74 } else {
75 @setcookie($name, $value, $expire, $path);
76 }
77 }
78
79 public function setBypassCookie() {
80 if (function_exists('is_user_logged_in') && is_user_logged_in() && !$this->hasValidBypassCookie()) {
81 $roleLevel = $this->getCurrentRoleLevel();
82 $bypassLevel = $this->config->bypassLevel;
83 if ($roleLevel >= $bypassLevel) {
84 $cookie = $this->generateBypassCookie();
85 $this->setcookie(BVFW::BYPASS_COOKIE, $cookie, time() + 43200);
86 }
87 }
88 }
89
90 public function generateBypassCookie() {
91 $time = floor(time() / 43200);
92 $bypassLevel = $this->config->bypassLevel;
93 $cookiekey = $this->config->cookieKey;
94 return sha1($bypassLevel.$time.$cookiekey);
95 }
96
97 public function hasValidBypassCookie() {
98 $cookie = (string) $this->request->getCookies(BVFW::BYPASS_COOKIE);
99 return ($this->canSetAdminCookie() && ($cookie === $this->generateBypassCookie()));
100 }
101
102 public function setIPCookie() {
103 if (!$this->request->getCookies(BVFW::IP_COOKIE)) {
104 $ip = $this->request->getIP();
105 $cookiekey = $this->config->cookieKey;
106 $time = floor(time() / 86400);
107 $cookie = sha1($ip.$time.$cookiekey);
108 $this->setcookie(BVFW::IP_COOKIE, $cookie, time() + 86400);
109 }
110 }
111
112 public function getBVCookies() {
113 $cookies = array();
114 if ($this->request->getCookies(BVFW::IP_COOKIE) !== NULL) {
115 $cookies[BVFW::IP_COOKIE] = (string) $this->request->getCookies(BVFW::IP_COOKIE);
116 }
117 return $cookies;
118 }
119
120 public function getCurrentRoleLevel() {
121 if (function_exists('current_user_can')) {
122 if (function_exists('is_super_admin') && is_super_admin()) {
123 return BVFWConfig::ROLE_LEVEL_ADMIN;
124 }
125 foreach ($this->config->customRoles as $role) {
126 if (current_user_can($role)) {
127 return BVFWConfig::ROLE_LEVEL_CUSTOM;
128 }
129 }
130 foreach (BVFWConfig::$roleLevels as $role => $level) {
131 if (current_user_can($role)) {
132 return $level;
133 }
134 }
135 }
136 return 0;
137 }
138
139 public function isActive() {
140 return $this->config->isActive();
141 }
142 public function canSetAdminCookie() {
143 return ($this->config->adminCookieMode === BVFWConfig::ADMIN_COOKIE_MODE_ENABLED);
144 }
145
146 public function canSetIPCookie() {
147 return ($this->config->ipCookieMode === BVFWConfig::IP_COOKIE_MODE_ENABLED);
148 }
149
150 public function setResponseCode() {
151 if (!function_exists('http_response_code')) {
152 return false;
153 }
154
155 $this->request->setRespCode(http_response_code());
156 return true;
157 }
158
159 public function canLog() {
160 $canlog = false;
161
162 if ($this->config->isCompleteLoggingEnabled()) {
163 $canlog = true;
164 } else if ($this->config->isVisitorLoggingEnabled()) {
165 $canlog = !$this->hasValidBypassCookie() &&
166 (!function_exists('is_user_logged_in') || !is_user_logged_in());
167 }
168 return $canlog;
169 }
170
171 public function log() {
172 if ($this->canLog()) {
173 $this->setResponseCode();
174 $this->logger->log($this->request->getDataToLog());
175 }
176 }
177
178 public function terminateRequest($category) {
179 $this->request->setCategory($category);
180 $this->request->setStatus(BVWPRequest::BLOCKED);
181 $this->request->setRespCode(403);
182
183 if ($this->config->canSetCachePreventionCookie &&
184 !$this->request->getCookies(BVFW::PREVENT_CACHE_COOKIE)) {
185 $value = "Prevent Caching Response.";
186 $this->setcookie(BVFW::PREVENT_CACHE_COOKIE, $value, time() + 43200);
187 }
188
189 header("Cache-Control: no-cache, no-store, must-revalidate");
190 header("Pragma: no-cache");
191 header("Expires: 0");
192 header('HTTP/1.0 403 Forbidden');
193 $brandname = $this->bvinfo->getBrandName().' Firewall';
194 die("
195 <div style='height: 98vh;'>
196 <div style='text-align: center; padding: 10% 0; font-family: Arial, Helvetica, sans-serif;'>
197 <div><p>$brandname</p></div>
198 <p>Blocked because of Malicious Activities</p>
199 <p>Reference ID: " . $this->request->getRequestID() . "</p>
200 </div>
201 </div>
202 ");
203 }
204
205 public function isBlacklistedIP() {
206 return $this->ipstore->isFWIPBlacklisted($this->request->getIP());
207 }
208
209 public function isWhitelistedIP() {
210 return $this->ipstore->isFWIPWhitelisted($this->request->getIP());
211 }
212
213 public function canBypassFirewall() {
214 if ($this->isWhitelistedIP() || $this->hasValidBypassCookie()) {
215 $this->request->setCategory(BVWPRequest::WHITELISTED);
216 $this->request->setStatus(BVWPRequest::BYPASSED);
217 return true;
218 }
219 return false;
220 }
221
222 public function canLogValue($key) {
223 $skip_keys = array('password' => true, 'passwd' => true, 'pwd' => true);
224 if (isset($skip_keys[$key])) {
225 return false;
226 }
227 return true;
228 }
229
230 public function execute() {
231 if ($this->config->canProfileReqInfo()) {
232 $result = array();
233
234 if ($this->request->getMethod() === 'POST' &&
235 preg_match('/(admin-ajax.php|admin-post.php)$/', $this->request->getPath())) {
236 $result += $this->profileRequestInfo(array("action" => $this->request->getPostParams('action')),
237 true, 'BODY[');
238 }
239 $result += $this->profileRequestInfo($this->request->getPostParams(),
240 $this->config->isReqProfilingModeDebug(), 'BODY[');
241 $result += $this->profileRequestInfo($this->request->getGetParams(),
242 true, 'GET[');
243 $result += $this->profileRequestInfo($this->request->getFiles(),
244 true, 'FILES[');
245 $result += $this->profileRequestInfo($this->getBVCookies(),
246 true, 'COOKIES[');
247 $this->request->updateReqInfo($result);
248 }
249
250 if (!$this->canBypassFirewall() && $this->config->isProtecting()) {
251 if ($this->isBlacklistedIP()) {
252 $this->terminateRequest(BVWPRequest::BLACKLISTED);
253 }
254 if ($this->config->isRulesModeEnabled()) {
255 if (is_array($this->ruleSet)) {
256 $this->evaluateRules($this->ruleSet);
257 } else {
258 $this->request->updateRulesInfo('errors', 'ruleset', 'Invalid RuleSet');
259 }
260 }
261 }
262 }
263
264 public function matchCount($pattern, $subject) {
265 $count = 0;
266 if (is_array($subject)) {
267 foreach ($subject as $val) {
268 $count += $this->matchCount($pattern, $val);
269 }
270 return $count;
271 } else {
272 $count = preg_match_all((string) $pattern, (string) $subject, $matches);
273 return ($count === false ? 0 : $count);
274 }
275 }
276
277 public function getLength($val) {
278 $length = 0;
279 if (is_array($val)) {
280 foreach ($val as $v) {
281 $length += $this->getLength($v);
282 }
283 return $length;
284 } else {
285 return strlen((string) $val);
286 }
287 }
288
289 public function profileRequestInfo($params, $debug = false, $prefix = '', $obraces = 1) {
290 $result = array();
291 if (is_array($params)) {
292 foreach ($params as $key => $value) {
293 $original_key = $key;
294 $key = $prefix . $key;
295 if (is_array($value)) {
296 $result = $result + $this->profileRequestInfo($value, $debug, $key . '[', $obraces + 1);
297 } else {
298 $key = $key . str_repeat(']', $obraces);
299 $result[$key] = array();
300 $valsize = $this->getLength($value);
301 $result[$key]["size"] = $valsize;
302 if ($debug === true && $valsize < 256 && $this->canLogValue($original_key)) {
303 $result[$key]["value"] = $value;
304 continue;
305 }
306
307 if (preg_match('/^\d+$/', $value)) {
308 $result[$key]["numeric"] = true;
309 } else if (preg_match('/^\w+$/', $value)) {
310 $result[$key]["regular_word"] = true;
311 } else if (preg_match('/^\S+$/', $value)) {
312 $result[$key]["special_word"] = true;
313 } else if (preg_match('/^[\w\s]+$/', $value)) {
314 $result[$key]["regular_sentence"] = true;
315 } else if (preg_match('/^[\w\W]+$/', $value)) {
316 $result[$key]["special_chars_sentence"] = true;
317 }
318
319 if (preg_match('/^\b((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}
320 (25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b$/x', $value)) {
321 $result[$key]["ipv4"] = true;
322 } else if (preg_match('/\b((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}
323 (25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b/x', $value)) {
324 $result[$key]["embeded_ipv4"] = true;
325 } else if (preg_match('/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|
326 ([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|
327 ([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}
328 (:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|
329 ([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})|
330 :((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|
331 ::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}
332 (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]|
333 (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)) {
334 $result[$key]["ipv6"] = true;
335 } else if (preg_match('/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|
336 ([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|
337 ([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}
338 (:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|
339 ([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})|
340 :((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|
341 ::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}
342 (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]|
343 (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)) {
344 $result[$key]["embeded_ipv6"] = true;
345 }
346
347 if (preg_match('/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/', $value)) {
348 $result[$key]["email"] = true;
349 } else if (preg_match('/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}/', $value)) {
350 $result[$key]["embeded_email"] = true;
351 }
352
353 if (preg_match('/^(http|ftp)s?:\/\/\S+$/i', $value)) {
354 $result[$key]["link"] = true;
355 } else if (preg_match('/(http|ftp)s?:\/\/\S+$/i', $value)) {
356 $result[$key]["embeded_link"] = true;
357 }
358
359 if (preg_match('/<(html|head|title|base|link|meta|style|picture|source|img|
360 iframe|embed|object|param|video|audio|track|map|area|form|label|input|button|
361 select|datalist|optgroup|option|textarea|output|progress|meter|fieldset|legend|
362 script|noscript|template|slot|canvas)/ix', $value)) {
363 $result[$key]["embeded_html"] = true;
364 }
365
366 if (preg_match('/\.(jpg|jpeg|png|gif|ico|pdf|doc|docx|ppt|pptx|pps|ppsx|odt|xls|zip|gzip|
367 xlsx|psd|mp3|m4a|ogg|wav|mp4|m4v|mov|wmv|avi|mpg|ogv|3gp|3g2|php|html|phtml|js|css)/ix', $value)) {
368 $result[$key]["file"] = true;
369 }
370
371 if ($this->matchCount(BVFW::SQLIREGEX, $value) > 2) {
372 $result[$key]["sql"] = true;
373 }
374
375 if (preg_match('/(?:\.{2}[\/]+)/', $value)) {
376 $result[$key]["path_traversal"] = true;
377 }
378
379 if (preg_match('/\\b(?i:eval)\\s*\\(\\s*(?i:base64_decode|exec|file_get_contents|gzinflate|passthru|shell_exec|stripslashes|system)\\s*\\(/', $value)) {
380 $result[$key]["php_eval"] = true;
381 }
382 }
383 }
384 }
385 return $result;
386 }
387
388 public function evaluateRules($ruleSet) {
389 foreach ($ruleSet as $rule) {
390 $id = $rule["id"];
391 $ruleLogic = $rule["rule_logic"];
392 $actions = $rule["actions"];
393 $min_rule_engine_ver = $rule["min_rule_engine_ver"];
394 $this->ruleEvaluator->resetErrors();
395
396 if (BVFWRuleEvaluator::VERSION >= $min_rule_engine_ver) {
397 if ($this->ruleEvaluator->evaluateRule($ruleLogic) && empty($this->ruleEvaluator->getErrors())) {
398 $this->request->updateMatchedRules($id);
399 $this->executeActions($actions);
400 } elseif (!empty($this->ruleEvaluator->getErrors())) {
401 $this->request->updateRulesInfo("errors", (string) $id, $this->ruleEvaluator->getErrors());
402 }
403 }
404 if ($this->break_rule_evaluation) {
405 return;
406 }
407 }
408 }
409
410 function executeActions($actions){
411 foreach($actions as $action) {
412 switch ($action["type"]) {
413 case "ALLOW":
414 $this->break_rule_evaluation = true;
415 $this->request->setCategory(BVWPRequest::RULE_ALLOWED);
416 return;
417 case "BLOCK":
418 $this->terminateRequest(BVWPRequest::RULE_BLOCKED);
419 return;
420 case "INSPECT":
421 $this->inspectRequest();
422 break;
423 case "DEBUG":
424 //TODO
425 break;
426 case "SCRUB":
427 //TODO
428 break;
429 case "FILTER":
430 //TODO
431 break;
432 }
433 }
434 }
435
436 public function inspectRequest() {
437 $this->request->updateRulesInfo('inspect', "headers", $this->request->getHeaders());
438 $this->request->updateRulesInfo('inspect', "getParams", $this->request->getGetParams());
439 $this->request->updateRulesInfo('inspect', "postParams", $this->getPostParamsToLog($this->request->getPostParams()));
440 $this->request->updateRulesInfo('inspect', "cookies", $this->request->getCookies());
441 }
442
443 function getPostParamsToLog($params) {
444 $result = array();
445 if (is_array($params)) {
446 foreach ($params as $key => $value) {
447 if (is_array($value)) {
448 $result[$key] = $this->getPostParamsToLog($value);
449 } else {
450 $valsize = $this->getLength($value);
451 if ($valsize > 1024) {
452 $result[$key] = "Data too long: {$valsize}";
453 } elseif (!$this->canLogValue($key)) {
454 $result[$key] = "Sensitive Data";
455 } else {
456 $result[$key] = $value;
457 }
458 }
459 }
460 }
461 return $result;
462 }
463 }
464 endif;