public static function isDisabled($waf = null) { if (!$waf instanceof wfWAF) { $waf = wfWAF::getInstance(); } try { return $waf->getStorageEngine()->isDisabled(); } catch (Exception $e) { if (WFWAF_DEBUG) { error_log("Exception in " . __CLASS__ . "->" . __FUNCTION__ . ": " . $e->getMessage()); } } return true; }
<p> <button type="button" onclick="WFAD.wafUpdateRules()" class="button button-primary"> Manually refresh firewall rules </button> <!-- <em id="waf-rules-last-updated"></em>--> </p> <p><em id="waf-rules-next-update"></em></p> <?php try { $lastUpdated = wfWAF::getInstance()->getStorageEngine()->getConfig('rulesLastUpdated'); $nextUpdate = PHP_INT_MAX; $cron = wfWAF::getInstance()->getStorageEngine()->getConfig('cron'); if (is_array($cron)) { /** @var wfWAFCronEvent $event */ foreach ($cron as $index => $event) { $event->setWaf(wfWAF::getInstance()); if (!$event->isInPast()) { $nextUpdate = min($nextUpdate, $event->getFireTime()); } } } } catch (wfWAFStorageFileException $e) { error_log($e->getMessage()); } if (!empty($lastUpdated)) { ?> <script> var lastUpdated = <?php echo (int) $lastUpdated; ?> ;
$headers['Referer'] = $hit->referer; $request->setHeaders($headers); preg_match('/request\\.([a-z]+)(?:\\[(.*?)\\](.*?))?/i', $hitData->paramKey, $matches); if ($matches) { switch ($matches[1]) { case 'body': $request->setMethod('POST'); parse_str("{$matches['2']}{$matches['3']}", $body); $request->setBody($body); break; } } } $request->setIP(wfUtils::inet_ntop($hit->IP)); $request->setTimestamp($hit->ctime); $waf = wfWAF::getInstance(); $waf->setRequest($request); $result = '<strong class="ok">Passed</strong>'; $failedRules = array(); try { $waf->runRules(); } catch (wfWAFAllowException $e) { $result = '<strong class="ok">Whitelisted</strong>'; } catch (wfWAFBlockException $e) { $result = '<strong class="error">Blocked</strong>'; $failedRules = $waf->getFailedRules(); } catch (wfWAFBlockSQLiException $e) { $result = '<strong class="error">Blocked For SQLi</strong>'; $failedRules = $waf->getFailedRules(); } catch (wfWAFBlockXSSException $e) { $result = '<strong class="error">Blocked For XSS</strong>';
public function uninstall() { parent::uninstall(); @unlink(rtrim(WFWAF_LOG_PATH . '/') . '/.htaccess'); @rmdir(WFWAF_LOG_PATH); }
public static function syncAttackData($exit = true) { global $wpdb; $waf = wfWAF::getInstance(); $lastAttackMicroseconds = $wpdb->get_var("SELECT MAX(attackLogTime) FROM {$wpdb->base_prefix}wfHits"); if ($waf->getStorageEngine()->hasNewerAttackData($lastAttackMicroseconds)) { $attackData = $waf->getStorageEngine()->getNewestAttackDataArray($lastAttackMicroseconds); if ($attackData) { foreach ($attackData as $request) { if (count($request) !== 9) { continue; } list($logTimeMicroseconds, $requestTime, $ip, $learningMode, $paramKey, $paramValue, $failedRules, $ssl, $requestString) = $request; // Skip old entries and hits in learning mode, since they'll get picked up anyways. if ($logTimeMicroseconds <= $lastAttackMicroseconds || $learningMode) { continue; } $hit = new wfRequestModel(); $hit->attackLogTime = $logTimeMicroseconds; $hit->statusCode = 403; $hit->ctime = $requestTime; $hit->IP = wfUtils::inet_pton($ip); if (preg_match('/user\\-agent:(.*?)\\n/i', $requestString, $matches)) { $hit->UA = trim($matches[1]); $hit->isGoogle = wfCrawl::isGoogleCrawler($hit->UA); } if (preg_match('/Referer:(.*?)\\n/i', $requestString, $matches)) { $hit->referer = trim($matches[1]); } if (preg_match('/^[a-z]+\\s+(.*?)\\s+/i', $requestString, $uriMatches) && preg_match('/Host:(.*?)\\n/i', $requestString, $hostMatches)) { $hit->URL = 'http' . ($ssl ? 's' : '') . '://' . trim($hostMatches[1]) . trim($uriMatches[1]); } if (preg_match('/cookie:(.*?)\\n/i', $requestString, $matches)) { $hit->newVisit = strpos($matches[1], 'wfvt_' . crc32(site_url())) !== false ? 1 : 0; $hasVerifiedHumanCookie = strpos($matches[1], 'wordfence_verifiedHuman') !== false; if ($hasVerifiedHumanCookie && preg_match('/wordfence_verifiedHuman=(.*?);/', $matches[1], $cookieMatches)) { $hit->jsRun = (int) wp_verify_nonce($cookieMatches[1], 'wordfence_verifiedHuman' . $hit->UA . $ip); } $hasLoginCookie = strpos($matches[1], $ssl ? SECURE_AUTH_COOKIE : AUTH_COOKIE) !== false; if ($hasLoginCookie && preg_match('/' . ($ssl ? SECURE_AUTH_COOKIE : AUTH_COOKIE) . '=(.*?);/', $matches[1], $cookieMatches)) { $authCookie = rawurldecode($cookieMatches[1]); $authID = $ssl ? wp_validate_auth_cookie($authCookie, 'secure_auth') : wp_validate_auth_cookie($authCookie, 'auth'); if ($authID) { $hit->userID = $authID; } } } $path = '/'; if (preg_match('/^[A-Z]+ (.*?) HTTP\\/1\\.1/', $requestString, $matches)) { if (($pos = strpos($matches[1], '?')) !== false) { $path = substr($matches[1], 0, $pos); } else { $path = $matches[1]; } } $hit->action = 'blocked:waf'; /** @var wfWAFRule $rule */ $ruleIDs = explode('|', $failedRules); $actionData = array('learningMode' => $learningMode, 'failedRules' => $failedRules, 'paramKey' => $paramKey, 'paramValue' => $paramValue, 'path' => $path); if ($ruleIDs && $ruleIDs[0]) { $rule = $waf->getRule($ruleIDs[0]); if ($rule) { $hit->actionDescription = $rule->getDescription(); $actionData['category'] = $rule->getCategory(); $actionData['ssl'] = $ssl; $actionData['fullRequest'] = base64_encode($requestString); } } $hit->actionData = wfRequestModel::serializeActionData($actionData); $hit->save(); self::scheduleSendAttackData(); } } $waf->getStorageEngine()->truncateAttackData(); } update_site_option('wordfence_syncingAttackData', 0); update_site_option('wordfence_syncAttackDataAttempts', 0); if ($exit) { exit; } }
if (get_option('wordfenceActivated') != 1) { add_action('activated_plugin', 'wordfence_save_activation_error'); function wordfence_save_activation_error() { update_option('wf_plugin_act_error', ob_get_contents()); } } if (!defined('WORDFENCE_VERSIONONLY_MODE')) { //Used to get version from file. if ((int) @ini_get('memory_limit') < 128) { if (strpos(ini_get('disable_functions'), 'ini_set') === false) { @ini_set('memory_limit', '128M'); //Some hosts have ini set at as little as 32 megs. 64 is the min sane amount of memory. } } /** * Constant to determine if Wordfence is installed on another WordPress site one or more directories up in * auto_prepend_file mode. */ define('WFWAF_SUBDIRECTORY_INSTALL', class_exists('wfWAF') && !in_array(realpath(dirname(__FILE__) . '/vendor/wordfence/wf-waf/src/init.php'), get_included_files())); if (!WFWAF_SUBDIRECTORY_INSTALL) { require_once 'vendor/wordfence/wf-waf/src/init.php'; if (!wfWAF::getInstance()) { define('WFWAF_AUTO_PREPEND', false); require_once 'waf/bootstrap.php'; } } require_once 'lib/wordfenceConstants.php'; require_once 'lib/wordfenceClass.php'; wordfence::install_actions(); }
public static function licenseStatusChanged() { //Update the WAF cron $cron = wfWAF::getInstance()->getStorageEngine()->getConfig('cron'); if (is_array($cron)) { /** @var wfWAFCronEvent $event */ foreach ($cron as $index => $event) { $event->setWaf(wfWAF::getInstance()); if (!$event->isInPast()) { $newEvent = $event->reschedule(); if ($newEvent instanceof wfWAFCronEvent && $newEvent !== $event) { $cron[$index] = $newEvent; } else { unset($cron[$index]); } } } } wfWAF::getInstance()->getStorageEngine()->setConfig('cron', $cron); }
/** * @param wfWAF $instance */ public static function setInstance($instance) { self::$instance = $instance; }
/** * Get scan regexes from noc1 and add any user defined regexes, including descriptions, ID's and time added. * @todo add caching to this. * @throws Exception */ protected function setupSigs() { $this->api = new wfAPI($this->apiKey, $this->wordpressVersion); $sigData = $this->api->call('get_patterns', array(), array()); if (!(is_array($sigData) && isset($sigData['rules']))) { throw new Exception("Wordfence could not get the attack signature patterns from the scanning server."); } if (wfWAF::getInstance() && method_exists(wfWAF::getInstance(), 'setMalwareSignatures')) { try { wfWAF::getInstance()->setMalwareSignatures(array()); } catch (Exception $e) { /* Ignore */ } } if (is_array($sigData['rules'])) { $wafPatterns = array(); foreach ($sigData['rules'] as $key => $signatureRow) { list(, , $pattern) = $signatureRow; $logOnly = isset($signatureRow[5]) && !empty($signatureRow[5]) ? $signatureRow[5] : false; if (@preg_match('/' . $pattern . '/i', null) === false) { wordfence::status(1, 'error', "A regex Wordfence received from it's servers is invalid. The pattern is: " . esc_html($pattern)); unset($sigData['rules'][$key]); } else { if (!$logOnly) { $wafPatterns[] = $pattern; } } } if (wfWAF::getInstance() && method_exists(wfWAF::getInstance(), 'setMalwareSignatures')) { try { wfWAF::getInstance()->setMalwareSignatures($wafPatterns); } catch (Exception $e) { /* Ignore */ } } } $extra = wfConfig::get('scan_include_extra'); if (!empty($extra)) { $regexs = explode("\n", $extra); $id = 1000001; foreach ($regexs as $r) { $r = rtrim($r, "\r"); try { preg_match('/' . $r . '/i', ""); } catch (Exception $e) { throw new Exception("The following user defined scan pattern has an error: {$r}"); } $sigData['rules'][] = array($id++, time(), $r, "User defined scan pattern"); } } $this->patterns = $sigData; if (isset($this->patterns['signatureUpdateTime'])) { wfConfig::set('signatureUpdateTime', $this->patterns['signatureUpdateTime']); } }
public static function set($key, $val) { if ($key == 'disableConfigCaching') { self::getDB()->queryWrite("insert into " . self::table() . " (name, val) values ('%s', '%s') ON DUPLICATE KEY UPDATE val='%s'", $key, $val, $val); return; } if (is_array($val)) { $msg = "wfConfig::set() got an array as second param with key: {$key} and value: " . var_export($val, true); wordfence::status(1, 'error', $msg); return; } if (($key == 'apiKey' || $key == 'isPaid') && wfWAF::getInstance() && !WFWAF_SUBDIRECTORY_INSTALL) { try { wfWAF::getInstance()->getStorageEngine()->setConfig($key, $val); } catch (wfWAFStorageFileException $e) { error_log($e->getMessage()); } } self::getDB()->queryWrite("insert into " . self::table() . " (name, val) values ('%s', '%s') ON DUPLICATE KEY UPDATE val='%s'", $key, $val, $val); self::$cache[$key] = $val; self::clearDiskCache(); }
wfWAF::getInstance()->getEventBus()->attach(new wfWAFBaseObserver()); $rulesFiles = array(WFWAF_PATH . 'rules.php', WFWAF_LOG_PATH . 'rules.php'); foreach ($rulesFiles as $rulesFile) { if (!file_exists($rulesFile)) { @touch($rulesFile); } if (is_writable($rulesFile)) { wfWAF::getInstance()->setCompiledRulesFile($rulesFile); break; } } try { if (!file_exists(wfWAF::getInstance()->getCompiledRulesFile()) || !filesize(wfWAF::getInstance()->getCompiledRulesFile())) { try { wfWAF::getInstance()->updateRuleSet(file_get_contents(WFWAF_PATH . 'baseRules.rules')); } catch (wfWAFBuildRulesException $e) { error_log($e->getMessage()); } catch (Exception $e) { error_log($e->getMessage()); } } try { wfWAF::getInstance()->run(); } catch (wfWAFBuildRulesException $e) { error_log($e->getMessage()); } catch (Exception $e) { error_log($e->getMessage()); } } catch (wfWAFStorageFileException $e) { // Choose another storage engine here. }
/** * @param wfWAFBlockXSSException $e * @param int $httpCode */ public function blockXSSAction($e, $httpCode = 403) { if ($this->isInLearningMode()) { register_shutdown_function(array($this, 'whitelistFailedRulesIfNot404')); $this->getStorageEngine()->logAttack($e->getFailedRules(), $e->getParamKey(), $e->getParamValue(), $e->getRequest()); $this->setLearningModeAttackException($e); } else { parent::blockXSSAction($e, $httpCode); } }
public static function set($key, $val, $autoload = self::AUTOLOAD) { global $wpdb; if (is_array($val)) { $msg = "wfConfig::set() got an array as second param with key: {$key} and value: " . var_export($val, true); wordfence::status(1, 'error', $msg); return; } if (($key == 'apiKey' || $key == 'isPaid') && wfWAF::getInstance() && !WFWAF_SUBDIRECTORY_INSTALL) { try { wfWAF::getInstance()->getStorageEngine()->setConfig($key, $val); } catch (wfWAFStorageFileException $e) { error_log($e->getMessage()); } } if (!self::$tableExists) { return; } $table = self::table(); if ($wpdb->query($wpdb->prepare("INSERT INTO {$table} (name, val, autoload) values (%s, %s, %s) ON DUPLICATE KEY UPDATE val = %s, autoload = %s", $key, $val, $autoload, $val, $autoload)) !== false && $autoload != self::DONT_AUTOLOAD) { self::updateCachedOption($key, $val); } }
/** * @return string */ public function getUnavailableMessage($reason = '') { try { $homeURL = wfWAF::getInstance()->getStorageEngine()->getConfig('homeURL'); } catch (Exception $e) { //Do nothing } return wfWAFView::create('503', array('waf' => $this, 'reason' => $reason, 'homeURL' => $homeURL))->render(); }
<?php if (!WFWAF_SUBDIRECTORY_INSTALL) { ?> <div id="updateWAFRules"> <h3>Firewall Rules</h3> <p> <button type="button" onclick="WFAD.wafUpdateRules()" class="button button-primary"> Manually refresh firewall rules </button> <!-- <em id="waf-rules-last-updated"></em>--> </p> <?php try { $lastUpdated = wfWAF::getInstance()->getStorageEngine()->getConfig('rulesLastUpdated'); } catch (wfWAFStorageFileException $e) { error_log($e->getMessage()); } if (!empty($lastUpdated)) { ?> <script> var lastUpdated = <?php echo (int) $lastUpdated; ?> ; WFAD.renderWAFRulesLastUpdated(new Date(lastUpdated * 1000)); </script> <?php } ?>
protected function checkForBlockedCountry($countryBlock, $ip, $bareRequestURI) { try { $homeURL = wfWAF::getInstance()->getStorageEngine()->getConfig('homeURL'); } catch (Exception $e) { //Do nothing } $bareRequestURI = rtrim($bareRequestURI, '/\\'); if ($country = $this->ip2Country($ip)) { foreach ($countryBlock['countries'] as $blocked) { if (strtoupper($blocked) == strtoupper($country)) { if ($countryBlock['action'] == 'redir') { $redirURL = $countryBlock['redirURL']; $eRedirHost = wfWAFUtils::extractHostname($redirURL); $isExternalRedir = false; if ($eRedirHost && $homeURL && $eRedirHost != wfWAFUtils::extractHostname($homeURL)) { $isExternalRedir = true; } if (!$isExternalRedir && rtrim(wfWAFUtils::extractBareURI($redirURL), '/\\') == $bareRequestURI) { //Is this the URI we want to redirect to, then don't block it //Do nothing } else { return array('action' => self::WFWAF_BLOCK_COUNTRY_REDIR); } } else { return array('action' => self::WFWAF_BLOCK_COUNTRY); } } } } return false; }