.htaccess
7 years ago
bootstrap.php
6 years ago
wfWAFGeoIP2.php
7 years ago
wfWAFIPBlocksController.php
6 years ago
wfWAFUserIPRange.php
7 years ago
wfWAFIPBlocksController.php
530 lines
| 1 | <?php |
| 2 | if (!defined('WFWAF_RUN_COMPLETE')) { |
| 3 | |
| 4 | class wfWAFIPBlocksController |
| 5 | { |
| 6 | const WFWAF_BLOCK_UAREFIPRANGE = 'UA/Referrer/IP Range not allowed'; |
| 7 | const WFWAF_BLOCK_COUNTRY = 'blocked access via country blocking'; |
| 8 | const WFWAF_BLOCK_COUNTRY_REDIR = 'blocked access via country blocking and redirected to URL'; |
| 9 | const WFWAF_BLOCK_COUNTRY_BYPASS_REDIR = 'redirected to bypass URL'; |
| 10 | const WFWAF_BLOCK_WFSN = 'Blocked by Wordfence Security Network'; |
| 11 | const WFWAF_BLOCK_BADPOST = 'POST received with blank user-agent and referer'; |
| 12 | const WFWAF_BLOCK_BANNEDURL = 'Accessed a banned URL.'; |
| 13 | const WFWAF_BLOCK_FAKEGOOGLE = 'Fake Google crawler automatically blocked'; |
| 14 | const WFWAF_BLOCK_LOGINSEC = 'Blocked by login security setting.'; |
| 15 | const WFWAF_BLOCK_LOGINSEC_FORGOTPASSWD = 'Exceeded the maximum number of tries to recover their password'; //substring search |
| 16 | const WFWAF_BLOCK_LOGINSEC_FAILURES = 'Exceeded the maximum number of login failures'; //substring search |
| 17 | const WFWAF_BLOCK_THROTTLEGLOBAL = 'Exceeded the maximum global requests per minute for crawlers or humans.'; |
| 18 | const WFWAF_BLOCK_THROTTLESCAN = 'Exceeded the maximum number of 404 requests per minute for a known security vulnerability.'; |
| 19 | const WFWAF_BLOCK_THROTTLECRAWLER = 'Exceeded the maximum number of requests per minute for crawlers.'; |
| 20 | const WFWAF_BLOCK_THROTTLECRAWLERNOTFOUND = 'Exceeded the maximum number of page not found errors per minute for a crawler.'; |
| 21 | const WFWAF_BLOCK_THROTTLEHUMAN = 'Exceeded the maximum number of page requests per minute for humans.'; |
| 22 | const WFWAF_BLOCK_THROTTLEHUMANNOTFOUND = 'Exceeded the maximum number of page not found errors per minute for humans.'; |
| 23 | |
| 24 | protected static $_currentController = null; |
| 25 | |
| 26 | public static function currentController() { |
| 27 | if (self::$_currentController === null) { |
| 28 | self::$_currentController = new wfWAFIPBlocksController(); |
| 29 | } |
| 30 | return self::$_currentController; |
| 31 | } |
| 32 | |
| 33 | public static function setCurrentController($currentController) { |
| 34 | self::$_currentController = $currentController; |
| 35 | } |
| 36 | |
| 37 | /** |
| 38 | * Schedules a config sync to happen at the end of the current process's execution. |
| 39 | */ |
| 40 | public static function setNeedsSynchronizeConfigSettings() { |
| 41 | static $willSynchronize = false; |
| 42 | if (!$willSynchronize) { |
| 43 | $willSynchronize = true; |
| 44 | register_shutdown_function('wfWAFIPBlocksController::synchronizeConfigSettings'); |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | public static function synchronizeConfigSettings() { |
| 49 | if (!class_exists('wfConfig') || !wfConfig::tableExists() || !wfWAF::getInstance()) { // Ensure this is only called when WordPress and the plugin are fully loaded |
| 50 | return; |
| 51 | } |
| 52 | |
| 53 | static $isSynchronizing = false; |
| 54 | if ($isSynchronizing) { |
| 55 | return; |
| 56 | } |
| 57 | $isSynchronizing = true; |
| 58 | |
| 59 | // Pattern Blocks |
| 60 | $blocks = wfBlock::patternBlocks(true); |
| 61 | $patternBlocks = array(); |
| 62 | foreach ($blocks as $b) { |
| 63 | $patternBlocks[] = array('id' => $b->id, 'ipRange' => $b->ipRange, 'hostnamePattern' => $b->hostname, 'uaPattern' => $b->userAgent, 'refPattern' => $b->referrer, 'expiration' => $b->expiration); |
| 64 | } |
| 65 | |
| 66 | // Country Blocks |
| 67 | $countryBlocks = array(); |
| 68 | $countryBlockEntries = wfBlock::countryBlocks(true); |
| 69 | $countryBlocks['blocks'] = array(); |
| 70 | foreach ($countryBlockEntries as $b) { |
| 71 | $reason = __('Access from your area has been temporarily limited for security reasons', 'wordfence'); |
| 72 | |
| 73 | $countryBlocks['blocks'][] = array( |
| 74 | 'id' => $b->id, |
| 75 | 'countries' => $b->countries, |
| 76 | 'blockLogin' => $b->blockLogin, |
| 77 | 'blockSite' => $b->blockSite, |
| 78 | 'reason' => $reason, |
| 79 | 'expiration' => $b->expiration, |
| 80 | ); |
| 81 | } |
| 82 | $countryBlocks['action'] = wfConfig::get('cbl_action', false); |
| 83 | $countryBlocks['loggedInBlocked'] = wfConfig::get('cbl_loggedInBlocked', false); |
| 84 | $countryBlocks['bypassRedirURL'] = wfConfig::get('cbl_bypassRedirURL', ''); |
| 85 | $countryBlocks['bypassRedirDest'] = wfConfig::get('cbl_bypassRedirDest', ''); |
| 86 | $countryBlocks['bypassViewURL'] = wfConfig::get('cbl_bypassViewURL', ''); |
| 87 | $countryBlocks['redirURL'] = wfConfig::get('cbl_redirURL', ''); |
| 88 | $countryBlocks['cookieVal'] = wfBlock::countryBlockingBypassCookieValue(); |
| 89 | |
| 90 | //Other Blocks |
| 91 | $otherBlocks = array('blockedTime' => wfConfig::get('blockedTime', 0)); |
| 92 | $otherBlockEntries = wfBlock::ipBlocks(true); |
| 93 | $otherBlocks['blocks'] = array(); |
| 94 | foreach ($otherBlockEntries as $b) { |
| 95 | $reason = $b->reason; |
| 96 | if ($b->type == wfBlock::TYPE_IP_MANUAL || $b->type == wfBlock::TYPE_IP_AUTOMATIC_PERMANENT) { |
| 97 | $reason = __('Manual block by administrator', 'wordfence'); |
| 98 | } |
| 99 | |
| 100 | $otherBlocks['blocks'][] = array( |
| 101 | 'id' => $b->id, |
| 102 | 'IP' => base64_encode(wfUtils::inet_pton($b->ip)), |
| 103 | 'reason' => $reason, |
| 104 | 'expiration' => $b->expiration, |
| 105 | ); |
| 106 | } |
| 107 | |
| 108 | //Lockouts |
| 109 | $lockoutEntries = wfBlock::lockouts(true); |
| 110 | $lockoutSecs = wfConfig::get('loginSec_lockoutMins') * 60; |
| 111 | $lockouts = array('lockedOutTime' => $lockoutSecs, 'lockouts' => array()); |
| 112 | foreach ($lockoutEntries as $l) { |
| 113 | $lockouts['lockouts'][] = array( |
| 114 | 'id' => $l->id, |
| 115 | 'IP' => base64_encode(wfUtils::inet_pton($l->ip)), |
| 116 | 'reason' => $l->reason, |
| 117 | 'expiration' => $l->expiration, |
| 118 | ); |
| 119 | } |
| 120 | |
| 121 | // Save it |
| 122 | try { |
| 123 | $patternBlocksJSON = wfWAFUtils::json_encode($patternBlocks); |
| 124 | wfWAF::getInstance()->getStorageEngine()->setConfig('patternBlocks', $patternBlocksJSON, 'synced'); |
| 125 | $countryBlocksJSON = wfWAFUtils::json_encode($countryBlocks); |
| 126 | wfWAF::getInstance()->getStorageEngine()->setConfig('countryBlocks', $countryBlocksJSON, 'synced'); |
| 127 | $otherBlocksJSON = wfWAFUtils::json_encode($otherBlocks); |
| 128 | wfWAF::getInstance()->getStorageEngine()->setConfig('otherBlocks', $otherBlocksJSON, 'synced'); |
| 129 | $lockoutsJSON = wfWAFUtils::json_encode($lockouts); |
| 130 | wfWAF::getInstance()->getStorageEngine()->setConfig('lockouts', $lockoutsJSON, 'synced'); |
| 131 | |
| 132 | wfWAF::getInstance()->getStorageEngine()->setConfig('advancedBlockingEnabled', wfConfig::get('firewallEnabled'), 'synced'); |
| 133 | wfWAF::getInstance()->getStorageEngine()->setConfig('disableWAFIPBlocking', wfConfig::get('disableWAFIPBlocking'), 'synced'); |
| 134 | } |
| 135 | catch (Exception $e) { |
| 136 | // Do nothing |
| 137 | } |
| 138 | $isSynchronizing = false; |
| 139 | } |
| 140 | |
| 141 | /** |
| 142 | * @param wfWAFRequest $request |
| 143 | * @return bool|string If not blocked, returns false. Otherwise a string of the reason it was blocked or true. |
| 144 | */ |
| 145 | public function shouldBlockRequest($request) { |
| 146 | // Checking the user whitelist is done before reaching this call |
| 147 | |
| 148 | $ip = $request->getIP(); |
| 149 | |
| 150 | //Check the system whitelist |
| 151 | if ($this->checkForWhitelisted($ip)) { |
| 152 | return false; |
| 153 | } |
| 154 | |
| 155 | //Let the plugin handle these |
| 156 | $wfFunc = $request->getQueryString('_wfsf'); |
| 157 | if ($wfFunc == 'unlockEmail' || $wfFunc == 'unlockAccess') { // Can't check validity here, let it pass through to plugin level where it can |
| 158 | return false; |
| 159 | } |
| 160 | |
| 161 | $logHuman = $request->getQueryString('wordfence_lh'); |
| 162 | if ($logHuman !== null) { |
| 163 | return false; |
| 164 | } |
| 165 | |
| 166 | //Start block checks |
| 167 | $ipNum = wfWAFUtils::inet_pton($ip); |
| 168 | $hostname = null; |
| 169 | $ua = $request->getHeaders('User-Agent'); if ($ua === null) { $ua = ''; } |
| 170 | $referer = $request->getHeaders('Referer'); if ($referer === null) { $referer = ''; } |
| 171 | |
| 172 | $isPaid = false; |
| 173 | try { |
| 174 | $isPaid = wfWAF::getInstance()->getStorageEngine()->getConfig('isPaid', null, 'synced'); |
| 175 | $pluginABSPATH = wfWAF::getInstance()->getStorageEngine()->getConfig('pluginABSPATH', null, 'synced'); |
| 176 | |
| 177 | $patternBlocksJSON = wfWAF::getInstance()->getStorageEngine()->getConfig('patternBlocks', null, 'synced'); |
| 178 | $countryBlocksJSON = wfWAF::getInstance()->getStorageEngine()->getConfig('countryBlocks', null, 'synced'); |
| 179 | $otherBlocksJSON = wfWAF::getInstance()->getStorageEngine()->getConfig('otherBlocks', null, 'synced'); |
| 180 | $lockoutsJSON = wfWAF::getInstance()->getStorageEngine()->getConfig('lockouts', null, 'synced'); |
| 181 | } |
| 182 | catch (Exception $e) { |
| 183 | // Do nothing |
| 184 | } |
| 185 | |
| 186 | if (isset($_SERVER['SCRIPT_FILENAME']) && (strpos($_SERVER['SCRIPT_FILENAME'], $pluginABSPATH . "wp-admin/") === 0 || strpos($_SERVER['SCRIPT_FILENAME'], $pluginABSPATH . "wp-content/") === 0 || strpos($_SERVER['SCRIPT_FILENAME'], $pluginABSPATH . "wp-includes/") === 0)) { |
| 187 | return false; //Rely on WordPress's own access control and blocking at the plugin level |
| 188 | } |
| 189 | |
| 190 | // Pattern Blocks from the Advanced Blocking page (IP Range, UA, Referer) |
| 191 | $patternBlocks = @wfWAFUtils::json_decode($patternBlocksJSON, true); |
| 192 | if (is_array($patternBlocks)) { |
| 193 | // Instead of a long block of if/else statements, using bitshifting to generate an expected value and a found value |
| 194 | $ipRangeOffset = 1; |
| 195 | $uaPatternOffset = 2; |
| 196 | $refPatternOffset = 3; |
| 197 | |
| 198 | foreach ($patternBlocks as $b) { |
| 199 | $expectedBits = 0; |
| 200 | $foundBits = 0; |
| 201 | |
| 202 | if (isset($b['expiration']) && $b['expiration'] < time() && $b['expiration'] != 0) { |
| 203 | continue; |
| 204 | } |
| 205 | |
| 206 | if (!empty($b['ipRange'])) { |
| 207 | $expectedBits |= (1 << $ipRangeOffset); |
| 208 | |
| 209 | $range = new wfWAFUserIPRange($b['ipRange']); |
| 210 | if ($range->isIPInRange($ip)) { |
| 211 | $foundBits |= (1 << $ipRangeOffset); |
| 212 | } |
| 213 | } |
| 214 | |
| 215 | if (!empty($b['hostnamePattern'])) { |
| 216 | $expectedBits |= (1 << $ipRangeOffset); |
| 217 | if ($hostname === null) { |
| 218 | $hostname = wfWAFUtils::reverseLookup($ip); |
| 219 | } |
| 220 | if (preg_match(wfWAFUtils::patternToRegex($b['hostnamePattern']), $hostname)) { |
| 221 | $foundBits |= (1 << $ipRangeOffset); |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | if (!empty($b['uaPattern'])) { |
| 226 | $expectedBits |= (1 << $uaPatternOffset); |
| 227 | if (wfWAFUtils::isUABlocked($b['uaPattern'], $ua)) { |
| 228 | $foundBits |= (1 << $uaPatternOffset); |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | if (!empty($b['refPattern'])) { |
| 233 | $expectedBits |= (1 << $refPatternOffset); |
| 234 | if (wfWAFUtils::isRefererBlocked($b['refPattern'], $referer)) { |
| 235 | $foundBits |= (1 << $refPatternOffset); |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | if ($foundBits === $expectedBits && $expectedBits > 0) { |
| 240 | return array('action' => self::WFWAF_BLOCK_UAREFIPRANGE, 'id' => $b['id']); |
| 241 | } |
| 242 | } |
| 243 | } |
| 244 | // End Pattern Blocks |
| 245 | |
| 246 | // Country Blocking |
| 247 | if ($isPaid) { |
| 248 | $countryBlocks = @wfWAFUtils::json_decode($countryBlocksJSON, true); |
| 249 | if (is_array($countryBlocks) && isset($countryBlocks['blocks'])) { |
| 250 | $blocks = $countryBlocks['blocks']; |
| 251 | foreach ($blocks as $b) { |
| 252 | $blockedCountries = $b['countries']; |
| 253 | $bareRequestURI = wfWAFUtils::extractBareURI($request->getURI()); |
| 254 | $bareBypassRedirURI = wfWAFUtils::extractBareURI($countryBlocks['bypassRedirURL']); |
| 255 | $skipCountryBlocking = false; |
| 256 | |
| 257 | if ($bareBypassRedirURI && $bareRequestURI == $bareBypassRedirURI) { // Run this before country blocking because even if the user isn't blocked we need to set the bypass cookie so they can bypass future blocks. |
| 258 | if ($countryBlocks['bypassRedirDest']) { |
| 259 | setcookie('wfCBLBypass', $countryBlocks['cookieVal'], time() + (86400 * 365), '/', null, $this->isFullSSL(), true); |
| 260 | return array('action' => self::WFWAF_BLOCK_COUNTRY_BYPASS_REDIR, 'id' => $b['id']); |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | $bareBypassViewURI = wfWAFUtils::extractBareURI($countryBlocks['bypassViewURL']); |
| 265 | if ($bareBypassViewURI && $bareBypassViewURI == $bareRequestURI) { |
| 266 | setcookie('wfCBLBypass', $countryBlocks['cookieVal'], time() + (86400 * 365), '/', null, $this->isFullSSL(), true); |
| 267 | $skipCountryBlocking = true; |
| 268 | } |
| 269 | |
| 270 | $bypassCookieSet = false; |
| 271 | $bypassCookie = $request->getCookies('wfCBLBypass'); |
| 272 | if (isset($bypassCookie) && $bypassCookie == $countryBlocks['cookieVal']) { |
| 273 | $bypassCookieSet = true; |
| 274 | } |
| 275 | |
| 276 | if (!$skipCountryBlocking && $blockedCountries && !$bypassCookieSet) { |
| 277 | $isAuthRequest = (strpos($bareRequestURI, '/wp-login.php') !== false); |
| 278 | $isXMLRPC = (strpos($bareRequestURI, '/xmlrpc.php') !== false); |
| 279 | $isUserLoggedIn = wfWAF::getInstance()->parseAuthCookie() !== false; |
| 280 | |
| 281 | // If everything is checked, make sure this always runs. |
| 282 | if ($countryBlocks['loggedInBlocked'] && $b['blockLogin'] && $b['blockSite']) { |
| 283 | if ($blocked = $this->checkForBlockedCountry($countryBlocks, $ip, $bareRequestURI)) { $blocked['id'] = $b['id']; return $blocked; } |
| 284 | } |
| 285 | // Block logged in users. |
| 286 | if ($countryBlocks['loggedInBlocked'] && $isUserLoggedIn) { |
| 287 | if ($blocked = $this->checkForBlockedCountry($countryBlocks, $ip, $bareRequestURI)) { $blocked['id'] = $b['id']; return $blocked; } |
| 288 | } |
| 289 | // Block the login form itself and any attempt to authenticate. |
| 290 | if ($b['blockLogin'] && $isAuthRequest) { |
| 291 | if ($blocked = $this->checkForBlockedCountry($countryBlocks, $ip, $bareRequestURI)) { $blocked['id'] = $b['id']; return $blocked; } |
| 292 | } |
| 293 | // Block requests that aren't to the login page, xmlrpc.php, or a user already logged in. |
| 294 | if ($b['blockSite'] && !$isAuthRequest && !$isXMLRPC && !$isUserLoggedIn) { |
| 295 | if ($blocked = $this->checkForBlockedCountry($countryBlocks, $ip, $bareRequestURI)) { $blocked['id'] = $b['id']; return $blocked; } |
| 296 | } |
| 297 | // XMLRPC is inaccesible when public portion of the site and auth is disabled. |
| 298 | if ($b['blockLogin'] && $b['blockSite'] && $isXMLRPC) { |
| 299 | if ($blocked = $this->checkForBlockedCountry($countryBlocks, $ip, $bareRequestURI)) { $blocked['id'] = $b['id']; return $blocked; } |
| 300 | } |
| 301 | |
| 302 | // Any bypasses and other block possibilities will be checked at the plugin level once WordPress loads |
| 303 | } |
| 304 | } |
| 305 | } |
| 306 | } |
| 307 | // End Country Blocking |
| 308 | |
| 309 | // Other Blocks |
| 310 | $otherBlocks = @wfWAFUtils::json_decode($otherBlocksJSON, true); |
| 311 | if (is_array($otherBlocks)) { |
| 312 | $blocks = $otherBlocks['blocks']; |
| 313 | $bareRequestURI = wfWAFUtils::extractBareURI($request->getURI()); |
| 314 | $isAuthRequest = (stripos($bareRequestURI, '/wp-login.php') !== false); |
| 315 | foreach ($blocks as $b) { |
| 316 | if (isset($b['expiration']) && $b['expiration'] < time() && $b['expiration'] != 0) { |
| 317 | continue; |
| 318 | } |
| 319 | |
| 320 | if (base64_decode($b['IP']) != $ipNum) { |
| 321 | continue; |
| 322 | } |
| 323 | |
| 324 | if ($isAuthRequest && isset($b['wfsn']) && $b['wfsn']) { |
| 325 | return array('action' => self::WFWAF_BLOCK_WFSN, 'id' => $b['id']); |
| 326 | } |
| 327 | |
| 328 | return array('action' => (empty($b['reason']) ? '' : $b['reason']), 'id' => $b['id'], 'block' => true); |
| 329 | } |
| 330 | } |
| 331 | // End Other Blocks |
| 332 | |
| 333 | // Lockouts |
| 334 | $lockouts = @wfWAFUtils::json_decode($lockoutsJSON, true); |
| 335 | if (is_array($lockouts)) { |
| 336 | $lockouts = $lockouts['lockouts']; |
| 337 | $isAuthRequest = (stripos($bareRequestURI, '/wp-login.php') !== false) || (stripos($bareRequestURI, '/xmlrpc.php') !== false); |
| 338 | if ($isAuthRequest) { |
| 339 | foreach ($lockouts as $l) { |
| 340 | if (isset($l['expiration']) && $l['expiration'] < time()) { |
| 341 | continue; |
| 342 | } |
| 343 | |
| 344 | if (base64_decode($l['IP']) != $ipNum) { |
| 345 | continue; |
| 346 | } |
| 347 | |
| 348 | return array('action' => (empty($l['reason']) ? '' : $l['reason']), 'id' => $l['id'], 'lockout' => true); |
| 349 | } |
| 350 | } |
| 351 | } |
| 352 | // End Lockouts |
| 353 | |
| 354 | return false; |
| 355 | } |
| 356 | |
| 357 | public function countryRedirURL($countryBlocks = null) { |
| 358 | if (!isset($countryBlocks)) { |
| 359 | try { |
| 360 | $countryBlocksJSON = wfWAF::getInstance()->getStorageEngine()->getConfig('countryBlocks', null, 'synced'); |
| 361 | } |
| 362 | catch (Exception $e) { |
| 363 | return false; |
| 364 | } |
| 365 | } |
| 366 | |
| 367 | $countryBlocks = @wfWAFUtils::json_decode($countryBlocksJSON, true); |
| 368 | if (is_array($countryBlocks)) { |
| 369 | if ($countryBlocks['action'] == 'redir') { |
| 370 | return $countryBlocks['redirURL']; |
| 371 | } |
| 372 | } |
| 373 | return false; |
| 374 | } |
| 375 | |
| 376 | public function countryBypassRedirURL($countryBlocks = null) { |
| 377 | if (!isset($countryBlocks)) { |
| 378 | try { |
| 379 | $countryBlocksJSON = wfWAF::getInstance()->getStorageEngine()->getConfig('countryBlocks', null, 'synced'); |
| 380 | } |
| 381 | catch (Exception $e) { |
| 382 | return false; |
| 383 | } |
| 384 | } |
| 385 | |
| 386 | $countryBlocks = @wfWAFUtils::json_decode($countryBlocksJSON, true); |
| 387 | if (is_array($countryBlocks)) { |
| 388 | return $countryBlocks['bypassRedirDest']; |
| 389 | } |
| 390 | return false; |
| 391 | } |
| 392 | |
| 393 | protected function checkForBlockedCountry($countryBlock, $ip, $bareRequestURI) { |
| 394 | try { |
| 395 | $homeURL = wfWAF::getInstance()->getStorageEngine()->getConfig('homeURL', null, 'synced'); |
| 396 | } |
| 397 | catch (Exception $e) { |
| 398 | //Do nothing |
| 399 | } |
| 400 | |
| 401 | $bareRequestURI = rtrim($bareRequestURI, '/\\'); |
| 402 | if ($country = $this->ip2Country($ip)) { |
| 403 | $blocks = $countryBlock['blocks']; |
| 404 | foreach ($blocks as $b) { |
| 405 | foreach ($b['countries'] as $blocked) { |
| 406 | if (strtoupper($blocked) == strtoupper($country)) { |
| 407 | if ($countryBlock['action'] == 'redir') { |
| 408 | $redirURL = $countryBlock['redirURL']; |
| 409 | $eRedirHost = wfWAFUtils::extractHostname($redirURL); |
| 410 | $isExternalRedir = false; |
| 411 | if ($eRedirHost && $homeURL && $eRedirHost != wfWAFUtils::extractHostname($homeURL)) { |
| 412 | $isExternalRedir = true; |
| 413 | } |
| 414 | |
| 415 | if ((!$isExternalRedir) && rtrim(wfWAFUtils::extractBareURI($redirURL), '/\\') == $bareRequestURI){ //Is this the URI we want to redirect to, then don't block it |
| 416 | //Do nothing |
| 417 | } |
| 418 | else { |
| 419 | return array('action' => self::WFWAF_BLOCK_COUNTRY_REDIR); |
| 420 | } |
| 421 | } |
| 422 | else { |
| 423 | return array('action' => self::WFWAF_BLOCK_COUNTRY); |
| 424 | } |
| 425 | } |
| 426 | } |
| 427 | } |
| 428 | } |
| 429 | |
| 430 | return false; |
| 431 | } |
| 432 | |
| 433 | protected function checkForWhitelisted($ip) { |
| 434 | try { |
| 435 | $pluginABSPATH = wfWAF::getInstance()->getStorageEngine()->getConfig('pluginABSPATH', null, 'synced'); |
| 436 | $serverIPsJSON = wfWAF::getInstance()->getStorageEngine()->getConfig('serverIPs', null, 'synced'); |
| 437 | $whitelistedServiceIPsJSON = wfWAF::getInstance()->getStorageEngine()->getConfig('whitelistedServiceIPs', null, 'synced'); |
| 438 | } |
| 439 | catch (Exception $e) { |
| 440 | // Do nothing |
| 441 | } |
| 442 | |
| 443 | $serverIPs = @wfWAFUtils::json_decode($serverIPsJSON, true); |
| 444 | if (is_array($serverIPs)) { |
| 445 | if ( |
| 446 | (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == realpath($pluginABSPATH . DIRECTORY_SEPARATOR . 'wp-cron.php')) || //Safe -- plugin will do a final check to make sure the cron constant is defined |
| 447 | (!empty($_GET['wordfence_syncAttackData'])) //Safe but plugin will do a final check to make sure it runs |
| 448 | ) { |
| 449 | foreach ($serverIPs as $testIP) { |
| 450 | if (wfWAFUtils::inet_pton($ip) == wfWAFUtils::inet_pton($testIP)) { |
| 451 | return true; |
| 452 | } |
| 453 | } |
| 454 | } |
| 455 | } |
| 456 | |
| 457 | $whitelistedServiceIPs = @wfWAFUtils::json_decode($whitelistedServiceIPsJSON, true); |
| 458 | if (is_array($whitelistedServiceIPs)) { |
| 459 | $wfIPWhitelist = $whitelistedServiceIPs; |
| 460 | } |
| 461 | else { |
| 462 | $wordfenceLib = realpath(dirname(__FILE__) . '/../lib'); |
| 463 | include($wordfenceLib . '/wfIPWhitelist.php'); /** @var array $wfIPWhitelist */ |
| 464 | } |
| 465 | |
| 466 | foreach ($wfIPWhitelist as $group) { |
| 467 | foreach ($group as $subnet) { |
| 468 | if ($subnet instanceof wfWAFUserIPRange) { //Not currently reached |
| 469 | if ($subnet->isIPInRange($ip)) { |
| 470 | return true; |
| 471 | } |
| 472 | } elseif (wfWAFUtils::subnetContainsIP($subnet, $ip)) { |
| 473 | return true; |
| 474 | } |
| 475 | } |
| 476 | } |
| 477 | return false; |
| 478 | } |
| 479 | |
| 480 | protected function ip2Country($ip) { |
| 481 | if (version_compare(phpversion(), '5.4.0', '<')) { |
| 482 | return ''; |
| 483 | } |
| 484 | |
| 485 | require_once(dirname(__FILE__) . '/wfWAFGeoIP2.php'); |
| 486 | |
| 487 | try { |
| 488 | $geoip = @wfWAFGeoIP2::shared(); |
| 489 | $code = @$geoip->countryCode($ip); |
| 490 | return is_string($code) ? $code : ''; |
| 491 | } |
| 492 | catch (Exception $e) { |
| 493 | //Ignore |
| 494 | } |
| 495 | |
| 496 | return ''; |
| 497 | } |
| 498 | |
| 499 | /** |
| 500 | * Returns whether or not the site should be treated as if it's full-time SSL. |
| 501 | * |
| 502 | * @return bool |
| 503 | */ |
| 504 | protected function isFullSSL() { |
| 505 | try { |
| 506 | $is_ssl = false; //This is the same code from WP modified so we can use it here |
| 507 | if ( isset( $_SERVER['HTTPS'] ) ) { |
| 508 | if ( 'on' == strtolower( $_SERVER['HTTPS'] ) ) { |
| 509 | $is_ssl = true; |
| 510 | } |
| 511 | |
| 512 | if ( '1' == $_SERVER['HTTPS'] ) { |
| 513 | $is_ssl = true; |
| 514 | } |
| 515 | } elseif ( isset($_SERVER['SERVER_PORT'] ) && ( '443' == $_SERVER['SERVER_PORT'] ) ) { |
| 516 | $is_ssl = true; |
| 517 | } |
| 518 | |
| 519 | $homeURL = wfWAF::getInstance()->getStorageEngine()->getConfig('homeURL', null, 'synced'); |
| 520 | return $is_ssl && parse_url($homeURL, PHP_URL_SCHEME) === 'https'; |
| 521 | } |
| 522 | catch (Exception $e) { |
| 523 | //Do nothing |
| 524 | } |
| 525 | |
| 526 | return false; |
| 527 | } |
| 528 | } |
| 529 | } |
| 530 |