Version Description
- Improvement: The scan will now alert for a publicly visible .user.ini file.
- Fix: Fixed status code and human/bot tagging of block hit entries for live traffic and the Wordfence Security Network.
- Fix: Added internal throttling to ensure the daily cron does not run too frequently on some hosts.
Download this release
Release Info
Developer | wfryan |
Plugin | Wordfence Security – Firewall & Malware Scan |
Version | 6.3.20 |
Comparing to | |
See all releases |
Code changes from version 6.3.19 to 6.3.20
- lib/wfScanEngine.php +9 -11
- lib/wordfenceClass.php +72 -15
- readme.txt +6 -1
- waf/wfWAFIPBlocksController.php +1 -1
- wordfence.php +2 -2
lib/wfScanEngine.php
CHANGED
@@ -611,7 +611,7 @@ class wfScanEngine {
|
|
611 |
$status = wfIssues::statusStart("Check for publicly accessible configuration files, backup files and logs");
|
612 |
|
613 |
$backupFileTests = array(
|
614 |
-
|
615 |
// wfCommonBackupFileTest::createFromRootPath('.htaccess'),
|
616 |
wfCommonBackupFileTest::createFromRootPath('wp-config.php.bak'),
|
617 |
wfCommonBackupFileTest::createFromRootPath('wp-config.php.swo'),
|
@@ -637,15 +637,17 @@ class wfScanEngine {
|
|
637 |
)),
|
638 |
);
|
639 |
$backupFileTests = array_merge($backupFileTests, wfCommonBackupFileTest::createAllForFile('searchreplacedb2.php', wfCommonBackupFileTest::MATCH_REGEX, '/<title>Search and replace DB/i'));
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
|
|
644 |
|
645 |
|
646 |
/** @var wfCommonBackupFileTest $test */
|
647 |
foreach ($backupFileTests as $test) {
|
648 |
$pathFromRoot = (strpos($test->getPath(), ABSPATH) === 0) ? substr($test->getPath(), strlen(ABSPATH)) : $test->getPath();
|
|
|
649 |
if ($test->fileExists() && $test->isPubliclyAccessible()) {
|
650 |
$key = "configReadable" . bin2hex($test->getUrl());
|
651 |
$added = $this->addIssue(
|
@@ -654,9 +656,7 @@ class wfScanEngine {
|
|
654 |
$key,
|
655 |
$key,
|
656 |
'Publicly accessible config, backup, or log file found: ' . esc_html($pathFromRoot),
|
657 |
-
'<a href="' . $test->getUrl() . '" target="_blank" rel="noopener noreferrer">' . $test->getUrl() . '</a> is publicly
|
658 |
-
accessible and may expose sensitive information about your site or allow administrative functions to be performed by anyone. Files such as this one are commonly
|
659 |
-
checked for by both attackers and scanners such as WPScan and should be removed or made inaccessible.',
|
660 |
array(
|
661 |
'url' => $test->getUrl(),
|
662 |
'file' => $pathFromRoot,
|
@@ -874,9 +874,7 @@ class wfScanEngine {
|
|
874 |
$key,
|
875 |
$key,
|
876 |
'Publicly accessible quarantined file found: ' . esc_html($file),
|
877 |
-
'<a href="' . $test->getUrl() . '" target="_blank" rel="noopener noreferrer">' . $test->getUrl() . '</a> is publicly
|
878 |
-
accessible and may expose source code or sensitive information about your site. Files such as this one are commonly
|
879 |
-
checked for by scanners and should be removed or made inaccessible.',
|
880 |
array(
|
881 |
'url' => $test->getUrl(),
|
882 |
'file' => $file,
|
611 |
$status = wfIssues::statusStart("Check for publicly accessible configuration files, backup files and logs");
|
612 |
|
613 |
$backupFileTests = array(
|
614 |
+
wfCommonBackupFileTest::createFromRootPath('.user.ini'),
|
615 |
// wfCommonBackupFileTest::createFromRootPath('.htaccess'),
|
616 |
wfCommonBackupFileTest::createFromRootPath('wp-config.php.bak'),
|
617 |
wfCommonBackupFileTest::createFromRootPath('wp-config.php.swo'),
|
637 |
)),
|
638 |
);
|
639 |
$backupFileTests = array_merge($backupFileTests, wfCommonBackupFileTest::createAllForFile('searchreplacedb2.php', wfCommonBackupFileTest::MATCH_REGEX, '/<title>Search and replace DB/i'));
|
640 |
+
|
641 |
+
$userIniFilename = ini_get('user_ini.filename');
|
642 |
+
if ($userIniFilename && $userIniFilename !== '.user.ini') {
|
643 |
+
$backupFileTests[] = wfCommonBackupFileTest::createFromRootPath('.user.ini');
|
644 |
+
}
|
645 |
|
646 |
|
647 |
/** @var wfCommonBackupFileTest $test */
|
648 |
foreach ($backupFileTests as $test) {
|
649 |
$pathFromRoot = (strpos($test->getPath(), ABSPATH) === 0) ? substr($test->getPath(), strlen(ABSPATH)) : $test->getPath();
|
650 |
+
wordfence::status(4, 'info', "Testing {$pathFromRoot}");
|
651 |
if ($test->fileExists() && $test->isPubliclyAccessible()) {
|
652 |
$key = "configReadable" . bin2hex($test->getUrl());
|
653 |
$added = $this->addIssue(
|
656 |
$key,
|
657 |
$key,
|
658 |
'Publicly accessible config, backup, or log file found: ' . esc_html($pathFromRoot),
|
659 |
+
'<a href="' . $test->getUrl() . '" target="_blank" rel="noopener noreferrer">' . $test->getUrl() . '</a> is publicly accessible and may expose source code or sensitive information about your site. Files such as this one are commonly checked for by scanners and should be made inaccessible. Alternately, some can be removed if you are certain your site does not need them. Sites using the nginx web server may need manual configuration changes to protect such files. <a href="https://docs.wordfence.com/en/Understanding_scan_results#Publicly_accessible_config_backup_or_log_file_found" target="_blank" rel="noopener noreferrer">Learn more</a>',
|
|
|
|
|
660 |
array(
|
661 |
'url' => $test->getUrl(),
|
662 |
'file' => $pathFromRoot,
|
874 |
$key,
|
875 |
$key,
|
876 |
'Publicly accessible quarantined file found: ' . esc_html($file),
|
877 |
+
'<a href="' . $test->getUrl() . '" target="_blank" rel="noopener noreferrer">' . $test->getUrl() . '</a> is publicly accessible and may expose source code or sensitive information about your site. Files such as this one are commonly checked for by scanners and should be removed or made inaccessible.',
|
|
|
|
|
878 |
array(
|
879 |
'url' => $test->getUrl(),
|
880 |
'file' => $file,
|
lib/wordfenceClass.php
CHANGED
@@ -165,7 +165,14 @@ class wordfence {
|
|
165 |
private static function keyAlert($msg){
|
166 |
self::alert($msg, $msg . " To ensure uninterrupted Premium Wordfence protection on your site,\nplease renew your API key by visiting http://www.wordfence.com/ Sign in, go to your dashboard,\nselect the key about to expire and click the button to renew that API key.", false);
|
167 |
}
|
168 |
-
public static function dailyCron(){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
$api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
|
170 |
try {
|
171 |
$keyData = $api->call('ping_api_key');
|
@@ -748,6 +755,12 @@ SQL
|
|
748 |
wfConfig::set('fileContentsGSB6315Migration', 1);
|
749 |
}
|
750 |
|
|
|
|
|
|
|
|
|
|
|
|
|
751 |
|
752 |
//Check the How does Wordfence get IPs setting
|
753 |
wfUtils::requestDetectProxyCallback();
|
@@ -818,13 +831,13 @@ SQL
|
|
818 |
if($blog_id == 1 && get_option('wordfenceActivated') != 1){ return; } //Because the plugin is active once installed, even before it's network activated, for site 1 (WordPress team, why?!)
|
819 |
}
|
820 |
//User may be logged in or not, so register both handlers
|
821 |
-
add_action('
|
822 |
add_action('wp_ajax_nopriv_wordfence_doScan', 'wordfence::ajax_doScan_callback');
|
823 |
add_action('wp_ajax_nopriv_wordfence_testAjax', 'wordfence::ajax_testAjax_callback');
|
824 |
add_action('wp_ajax_nopriv_wordfence_perfLog', 'wordfence::ajax_perfLog_callback');
|
825 |
if(wfUtils::hasLoginCookie()){ //may be logged in. Fast way to check. These aren't secure functions, this is just a perf optimization, along with every other use of hasLoginCookie()
|
826 |
add_action('wp_ajax_wordfence_perfLog', 'wordfence::ajax_perfLog_callback');
|
827 |
-
add_action('
|
828 |
add_action('wp_ajax_wordfence_doScan', 'wordfence::ajax_doScan_callback');
|
829 |
add_action('wp_ajax_wordfence_testAjax', 'wordfence::ajax_testAjax_callback');
|
830 |
|
@@ -1069,7 +1082,7 @@ SQL
|
|
1069 |
$wfLog->logPerf(wfUtils::getIP(), $UA, $URL, $data);
|
1070 |
die(json_encode(array('ok' => 1)));
|
1071 |
}
|
1072 |
-
public static function
|
1073 |
self::getLog()->canLogHit = false;
|
1074 |
$UA = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
|
1075 |
$isCrawler = false;
|
@@ -4388,8 +4401,8 @@ HTACCESS;
|
|
4388 |
wfScanEngine::startScan();
|
4389 |
}
|
4390 |
public static function templateRedir(){
|
4391 |
-
if (!empty($_GET['
|
4392 |
-
self::
|
4393 |
exit;
|
4394 |
}
|
4395 |
|
@@ -4557,7 +4570,7 @@ EOL;
|
|
4557 |
|
4558 |
self::$hitID = self::getLog()->logHit();
|
4559 |
if (self::$hitID) {
|
4560 |
-
$URL = home_url('/?
|
4561 |
$URL = addslashes(preg_replace('/^https?:/i', '', $URL));
|
4562 |
#Load as external script async so we don't slow page down.
|
4563 |
echo <<<HTML
|
@@ -6906,13 +6919,47 @@ to your httpd.conf if using Apache, or find documentation on how to disable dire
|
|
6906 |
global $wpdb;
|
6907 |
$p = $wpdb->base_prefix;
|
6908 |
$wfdb = new wfDB();
|
|
|
6909 |
$count = $wfdb->querySingle("select count(*) as cnt from $p"."wfHits");
|
6910 |
$liveTrafficMaxRows = absint(wfConfig::get('liveTraf_maxRows', 2000));
|
6911 |
if ($count > $liveTrafficMaxRows * 10) {
|
|
|
6912 |
$wfdb->truncate($p . "wfHits"); //So we don't slow down sites that have very large wfHits tables
|
6913 |
-
}
|
|
|
|
|
6914 |
$wfdb->queryWrite("delete from $p" . "wfHits order by id asc limit %d", ($count - $liveTrafficMaxRows) + ($liveTrafficMaxRows * .2));
|
6915 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6916 |
}
|
6917 |
|
6918 |
private static function scheduleSendAttackData($timeToSend = null) {
|
@@ -7139,6 +7186,7 @@ LIMIT %d", sprintf('%.6f', $lastSendTime), $limit));
|
|
7139 |
public static function syncAttackData($exit = true) {
|
7140 |
global $wpdb;
|
7141 |
if (!defined('DONOTCACHEDB')) { define('DONOTCACHEDB', true); }
|
|
|
7142 |
$waf = wfWAF::getInstance();
|
7143 |
$lastAttackMicroseconds = $wpdb->get_var("SELECT MAX(attackLogTime) FROM {$wpdb->base_prefix}wfHits");
|
7144 |
if ($waf->getStorageEngine()->hasNewerAttackData($lastAttackMicroseconds)) {
|
@@ -7155,10 +7203,11 @@ LIMIT %d", sprintf('%.6f', $lastSendTime), $limit));
|
|
7155 |
if ($logTimeMicroseconds <= $lastAttackMicroseconds || $learningMode) {
|
7156 |
continue;
|
7157 |
}
|
|
|
|
|
7158 |
|
7159 |
$hit = new wfRequestModel();
|
7160 |
$hit->attackLogTime = $logTimeMicroseconds;
|
7161 |
-
$hit->statusCode = 403;
|
7162 |
$hit->ctime = $requestTime;
|
7163 |
$hit->IP = wfUtils::inet_pton($ip);
|
7164 |
|
@@ -7175,19 +7224,23 @@ LIMIT %d", sprintf('%.6f', $lastSendTime), $limit));
|
|
7175 |
$hit->URL = 'http' . ($ssl ? 's' : '') . '://' . trim($hostMatches[1]) . trim($uriMatches[1]);
|
7176 |
}
|
7177 |
|
|
|
7178 |
if (preg_match('/cookie:(.*?)\n/i', $requestString, $matches)) {
|
7179 |
$hit->newVisit = strpos($matches[1], 'wfvt_' . crc32(site_url())) !== false ? 1 : 0;
|
7180 |
$hasVerifiedHumanCookie = strpos($matches[1], 'wordfence_verifiedHuman') !== false;
|
7181 |
if ($hasVerifiedHumanCookie && preg_match('/wordfence_verifiedHuman=(.*?);/', $matches[1], $cookieMatches)) {
|
7182 |
-
$hit->jsRun = (int)
|
|
|
7183 |
}
|
7184 |
|
7185 |
-
$
|
7186 |
-
|
|
|
7187 |
$authCookie = rawurldecode($cookieMatches[1]);
|
7188 |
-
$
|
7189 |
-
if ($
|
7190 |
-
$hit->userID = $
|
|
|
7191 |
}
|
7192 |
}
|
7193 |
}
|
@@ -7278,9 +7331,11 @@ LIMIT %d", sprintf('%.6f', $lastSendTime), $limit));
|
|
7278 |
//Do nothing
|
7279 |
}
|
7280 |
}
|
|
|
7281 |
$hit->actionDescription = $actionDescription;
|
7282 |
}
|
7283 |
else if ($failedRules == 'logged') {
|
|
|
7284 |
$hit->action = 'logged:waf';
|
7285 |
}
|
7286 |
else { // Blocked by the WAF but would've been blocked anyway by the plugin settings so that message takes priority
|
@@ -7290,6 +7345,7 @@ LIMIT %d", sprintf('%.6f', $lastSendTime), $limit));
|
|
7290 |
}
|
7291 |
else {
|
7292 |
if ($failedRules == 'logged') {
|
|
|
7293 |
$hit->action = 'logged:waf';
|
7294 |
}
|
7295 |
else {
|
@@ -7337,6 +7393,7 @@ LIMIT %d", sprintf('%.6f', $lastSendTime), $limit));
|
|
7337 |
}
|
7338 |
|
7339 |
$hit->actionData = wfRequestModel::serializeActionData($actionData);
|
|
|
7340 |
$hit->save();
|
7341 |
|
7342 |
self::scheduleSendAttackData();
|
165 |
private static function keyAlert($msg){
|
166 |
self::alert($msg, $msg . " To ensure uninterrupted Premium Wordfence protection on your site,\nplease renew your API key by visiting http://www.wordfence.com/ Sign in, go to your dashboard,\nselect the key about to expire and click the button to renew that API key.", false);
|
167 |
}
|
168 |
+
public static function dailyCron() {
|
169 |
+
$lastDailyCron = (int) wfConfig::get('lastDailyCron', 0);
|
170 |
+
if (($lastDailyCron + 43200) > time()) { //Run no more frequently than every 12 hours
|
171 |
+
return;
|
172 |
+
}
|
173 |
+
|
174 |
+
wfConfig::set('lastDailyCron', time());
|
175 |
+
|
176 |
$api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
|
177 |
try {
|
178 |
$keyData = $api->call('ping_api_key');
|
755 |
wfConfig::set('fileContentsGSB6315Migration', 1);
|
756 |
}
|
757 |
|
758 |
+
//6.3.20
|
759 |
+
$lastBlockAggregation = wfConfig::get('lastBlockAggregation', 0);
|
760 |
+
if ($lastBlockAggregation == 0) {
|
761 |
+
wfConfig::set('lastBlockAggregation', time());
|
762 |
+
}
|
763 |
+
|
764 |
|
765 |
//Check the How does Wordfence get IPs setting
|
766 |
wfUtils::requestDetectProxyCallback();
|
831 |
if($blog_id == 1 && get_option('wordfenceActivated') != 1){ return; } //Because the plugin is active once installed, even before it's network activated, for site 1 (WordPress team, why?!)
|
832 |
}
|
833 |
//User may be logged in or not, so register both handlers
|
834 |
+
add_action('wp_ajax_nopriv_wordfence_lh', 'wordfence::ajax_lh_callback');
|
835 |
add_action('wp_ajax_nopriv_wordfence_doScan', 'wordfence::ajax_doScan_callback');
|
836 |
add_action('wp_ajax_nopriv_wordfence_testAjax', 'wordfence::ajax_testAjax_callback');
|
837 |
add_action('wp_ajax_nopriv_wordfence_perfLog', 'wordfence::ajax_perfLog_callback');
|
838 |
if(wfUtils::hasLoginCookie()){ //may be logged in. Fast way to check. These aren't secure functions, this is just a perf optimization, along with every other use of hasLoginCookie()
|
839 |
add_action('wp_ajax_wordfence_perfLog', 'wordfence::ajax_perfLog_callback');
|
840 |
+
add_action('wp_ajax_wordfence_lh', 'wordfence::ajax_lh_callback');
|
841 |
add_action('wp_ajax_wordfence_doScan', 'wordfence::ajax_doScan_callback');
|
842 |
add_action('wp_ajax_wordfence_testAjax', 'wordfence::ajax_testAjax_callback');
|
843 |
|
1082 |
$wfLog->logPerf(wfUtils::getIP(), $UA, $URL, $data);
|
1083 |
die(json_encode(array('ok' => 1)));
|
1084 |
}
|
1085 |
+
public static function ajax_lh_callback(){
|
1086 |
self::getLog()->canLogHit = false;
|
1087 |
$UA = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
|
1088 |
$isCrawler = false;
|
4401 |
wfScanEngine::startScan();
|
4402 |
}
|
4403 |
public static function templateRedir(){
|
4404 |
+
if (!empty($_GET['wordfence_lh'])) {
|
4405 |
+
self::ajax_lh_callback();
|
4406 |
exit;
|
4407 |
}
|
4408 |
|
4570 |
|
4571 |
self::$hitID = self::getLog()->logHit();
|
4572 |
if (self::$hitID) {
|
4573 |
+
$URL = home_url('/?wordfence_lh=1&hid=' . wfUtils::encrypt(self::$hitID));
|
4574 |
$URL = addslashes(preg_replace('/^https?:/i', '', $URL));
|
4575 |
#Load as external script async so we don't slow page down.
|
4576 |
echo <<<HTML
|
6919 |
global $wpdb;
|
6920 |
$p = $wpdb->base_prefix;
|
6921 |
$wfdb = new wfDB();
|
6922 |
+
$lastAggregation = wfConfig::get('lastBlockAggregation', 0);
|
6923 |
$count = $wfdb->querySingle("select count(*) as cnt from $p"."wfHits");
|
6924 |
$liveTrafficMaxRows = absint(wfConfig::get('liveTraf_maxRows', 2000));
|
6925 |
if ($count > $liveTrafficMaxRows * 10) {
|
6926 |
+
self::_aggregateBlockStats($lastAggregation);
|
6927 |
$wfdb->truncate($p . "wfHits"); //So we don't slow down sites that have very large wfHits tables
|
6928 |
+
}
|
6929 |
+
else if ($count > $liveTrafficMaxRows) {
|
6930 |
+
self::_aggregateBlockStats($lastAggregation);
|
6931 |
$wfdb->queryWrite("delete from $p" . "wfHits order by id asc limit %d", ($count - $liveTrafficMaxRows) + ($liveTrafficMaxRows * .2));
|
6932 |
}
|
6933 |
+
else if ($lastAggregation < (time() - 86400)) {
|
6934 |
+
self::_aggregateBlockStats($lastAggregation);
|
6935 |
+
}
|
6936 |
+
}
|
6937 |
+
|
6938 |
+
private static function _aggregateBlockStats($since = false) {
|
6939 |
+
global $wpdb;
|
6940 |
+
|
6941 |
+
if (!wfConfig::get('other_WFNet', true)) {
|
6942 |
+
return;
|
6943 |
+
}
|
6944 |
+
|
6945 |
+
if ($since === false) {
|
6946 |
+
$since = wfConfig::get('lastBlockAggregation', 0);
|
6947 |
+
}
|
6948 |
+
|
6949 |
+
$hitsTable = wfDB::networkPrefix() . 'wfHits';
|
6950 |
+
$query = $wpdb->prepare("SELECT COUNT(*) AS cnt, CASE WHEN (jsRun = 1 OR userID > 0) THEN 1 ELSE 0 END AS isHuman, statusCode FROM {$hitsTable} WHERE ctime > %d GROUP BY isHuman, statusCode", $since);
|
6951 |
+
$rows = $wpdb->get_results($query, ARRAY_A);
|
6952 |
+
if (count($rows)) {
|
6953 |
+
try {
|
6954 |
+
$api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
|
6955 |
+
$api->call('aggregate_stats', array(), array('stats' => json_encode($rows)));
|
6956 |
+
}
|
6957 |
+
catch (Exception $e) {
|
6958 |
+
// Do nothing
|
6959 |
+
}
|
6960 |
+
}
|
6961 |
+
|
6962 |
+
wfConfig::set('lastBlockAggregation', time());
|
6963 |
}
|
6964 |
|
6965 |
private static function scheduleSendAttackData($timeToSend = null) {
|
7186 |
public static function syncAttackData($exit = true) {
|
7187 |
global $wpdb;
|
7188 |
if (!defined('DONOTCACHEDB')) { define('DONOTCACHEDB', true); }
|
7189 |
+
$log = self::getLog();
|
7190 |
$waf = wfWAF::getInstance();
|
7191 |
$lastAttackMicroseconds = $wpdb->get_var("SELECT MAX(attackLogTime) FROM {$wpdb->base_prefix}wfHits");
|
7192 |
if ($waf->getStorageEngine()->hasNewerAttackData($lastAttackMicroseconds)) {
|
7203 |
if ($logTimeMicroseconds <= $lastAttackMicroseconds || $learningMode) {
|
7204 |
continue;
|
7205 |
}
|
7206 |
+
|
7207 |
+
$statusCode = 403;
|
7208 |
|
7209 |
$hit = new wfRequestModel();
|
7210 |
$hit->attackLogTime = $logTimeMicroseconds;
|
|
|
7211 |
$hit->ctime = $requestTime;
|
7212 |
$hit->IP = wfUtils::inet_pton($ip);
|
7213 |
|
7224 |
$hit->URL = 'http' . ($ssl ? 's' : '') . '://' . trim($hostMatches[1]) . trim($uriMatches[1]);
|
7225 |
}
|
7226 |
|
7227 |
+
$isHuman = false;
|
7228 |
if (preg_match('/cookie:(.*?)\n/i', $requestString, $matches)) {
|
7229 |
$hit->newVisit = strpos($matches[1], 'wfvt_' . crc32(site_url())) !== false ? 1 : 0;
|
7230 |
$hasVerifiedHumanCookie = strpos($matches[1], 'wordfence_verifiedHuman') !== false;
|
7231 |
if ($hasVerifiedHumanCookie && preg_match('/wordfence_verifiedHuman=(.*?);/', $matches[1], $cookieMatches)) {
|
7232 |
+
$hit->jsRun = (int) $log->validateVerifiedHumanCookie($cookieMatches[1], $hit->UA, $ip);
|
7233 |
+
$isHuman = !!$hit->jsRun;
|
7234 |
}
|
7235 |
|
7236 |
+
$authCookieName = $waf->getAuthCookieName();
|
7237 |
+
$hasLoginCookie = strpos($matches[1], $authCookieName) !== false;
|
7238 |
+
if ($hasLoginCookie && preg_match('/' . preg_quote($authCookieName) . '=(.*?);/', $matches[1], $cookieMatches)) {
|
7239 |
$authCookie = rawurldecode($cookieMatches[1]);
|
7240 |
+
$decodedAuthCookie = $waf->parseAuthCookie($authCookie);
|
7241 |
+
if ($decodedAuthCookie !== false) {
|
7242 |
+
$hit->userID = $decodedAuthCookie['userID'];
|
7243 |
+
$isHuman = true;
|
7244 |
}
|
7245 |
}
|
7246 |
}
|
7331 |
//Do nothing
|
7332 |
}
|
7333 |
}
|
7334 |
+
$statusCode = 503;
|
7335 |
$hit->actionDescription = $actionDescription;
|
7336 |
}
|
7337 |
else if ($failedRules == 'logged') {
|
7338 |
+
$statusCode = 200;
|
7339 |
$hit->action = 'logged:waf';
|
7340 |
}
|
7341 |
else { // Blocked by the WAF but would've been blocked anyway by the plugin settings so that message takes priority
|
7345 |
}
|
7346 |
else {
|
7347 |
if ($failedRules == 'logged') {
|
7348 |
+
$statusCode = 200;
|
7349 |
$hit->action = 'logged:waf';
|
7350 |
}
|
7351 |
else {
|
7393 |
}
|
7394 |
|
7395 |
$hit->actionData = wfRequestModel::serializeActionData($actionData);
|
7396 |
+
$hit->statusCode = $statusCode;
|
7397 |
$hit->save();
|
7398 |
|
7399 |
self::scheduleSendAttackData();
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
|
|
3 |
Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking
|
4 |
Requires at least: 3.9
|
5 |
Tested up to: 4.8.2
|
6 |
-
Stable tag: 6.3.
|
7 |
|
8 |
Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
|
9 |
|
@@ -160,6 +160,11 @@ Secure your website with Wordfence.
|
|
160 |
|
161 |
== Changelog ==
|
162 |
|
|
|
|
|
|
|
|
|
|
|
163 |
= 6.3.19 =
|
164 |
* Emergency Fix: Updated wpdb::prepare calls using %.6f since it is no longer supported.
|
165 |
|
3 |
Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking
|
4 |
Requires at least: 3.9
|
5 |
Tested up to: 4.8.2
|
6 |
+
Stable tag: 6.3.20
|
7 |
|
8 |
Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
|
9 |
|
160 |
|
161 |
== Changelog ==
|
162 |
|
163 |
+
= 6.3.20 =
|
164 |
+
* Improvement: The scan will now alert for a publicly visible .user.ini file.
|
165 |
+
* Fix: Fixed status code and human/bot tagging of block hit entries for live traffic and the Wordfence Security Network.
|
166 |
+
* Fix: Added internal throttling to ensure the daily cron does not run too frequently on some hosts.
|
167 |
+
|
168 |
= 6.3.19 =
|
169 |
* Emergency Fix: Updated wpdb::prepare calls using %.6f since it is no longer supported.
|
170 |
|
waf/wfWAFIPBlocksController.php
CHANGED
@@ -134,7 +134,7 @@ class wfWAFIPBlocksController
|
|
134 |
return false;
|
135 |
}
|
136 |
|
137 |
-
$logHuman = $request->getQueryString('
|
138 |
if ($logHuman !== null) {
|
139 |
return false;
|
140 |
}
|
134 |
return false;
|
135 |
}
|
136 |
|
137 |
+
$logHuman = $request->getQueryString('wordfence_lh');
|
138 |
if ($logHuman !== null) {
|
139 |
return false;
|
140 |
}
|
wordfence.php
CHANGED
@@ -4,14 +4,14 @@ Plugin Name: Wordfence Security
|
|
4 |
Plugin URI: http://www.wordfence.com/
|
5 |
Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
|
6 |
Author: Wordfence
|
7 |
-
Version: 6.3.
|
8 |
Author URI: http://www.wordfence.com/
|
9 |
Network: true
|
10 |
*/
|
11 |
if(defined('WP_INSTALLING') && WP_INSTALLING){
|
12 |
return;
|
13 |
}
|
14 |
-
define('WORDFENCE_VERSION', '6.3.
|
15 |
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
|
16 |
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
|
17 |
|
4 |
Plugin URI: http://www.wordfence.com/
|
5 |
Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
|
6 |
Author: Wordfence
|
7 |
+
Version: 6.3.20
|
8 |
Author URI: http://www.wordfence.com/
|
9 |
Network: true
|
10 |
*/
|
11 |
if(defined('WP_INSTALLING') && WP_INSTALLING){
|
12 |
return;
|
13 |
}
|
14 |
+
define('WORDFENCE_VERSION', '6.3.20');
|
15 |
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
|
16 |
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
|
17 |
|