Wordfence Security – Firewall & Malware Scan - Version 6.0.17

Version Description

  • Fix: Resolved issue where 301 redirects count as 404s with throttling applied.
  • Fix: Fixed Falcon .htaccess code writing to .htaccess when 'Immediately block IP's that access these URLs' option is modified.
  • Fix: Fixed issue where filtering posts by author in wp-admin no longer works due to change in /?author=N scan prevention logic.
  • Fix: Fixed issue in Live Traffic where 404s display as 200s.
  • Fix: Resolved issue with throttling logins via XMLRPC are not applied.
Download this release

Release Info

Developer wfmatt
Plugin Icon 128x128 Wordfence Security – Firewall & Malware Scan
Version 6.0.17
Comparing to
See all releases

Code changes from version 6.0.16 to 6.0.17

Files changed (4) hide show
  1. lib/wfLog.php +0 -22
  2. lib/wordfenceClass.php +53 -9
  3. readme.txt +9 -2
  4. wordfence.php +2 -2
lib/wfLog.php CHANGED
@@ -123,23 +123,6 @@ class wfLog {
123
 
124
  //Range blocking was here. Moved to wordfenceClass::veryFirstAction
125
 
126
- if(wfConfig::get('blockFakeBots')){
127
- if(wfCrawl::isGooglebot() && (! wfCrawl::verifyCrawlerPTR($this->googlePattern, $IP) )){
128
- $this->blockIP($IP, "Fake Google crawler automatically blocked");
129
- wordfence::status(2, 'info', "Blocking fake Googlebot at IP $IP");
130
- }
131
- }
132
- if(wfConfig::get('bannedURLs', false)){
133
- $URLs = explode(',', wfConfig::get('bannedURLs'));
134
- foreach($URLs as $URL){
135
- if($_SERVER['REQUEST_URI'] == trim($URL)){
136
- $this->blockIP($IP, "Accessed a banned URL.");
137
- $this->do503(3600, "Accessed a banned URL.");
138
- //exits
139
- }
140
- }
141
- }
142
-
143
  if(wfConfig::get('maxGlobalRequests') != 'DISABLED' && $hitsPerMinute > wfConfig::get('maxGlobalRequests')){ //Applies to 404 or pageview
144
  $this->takeBlockingAction('maxGlobalRequests', "Exceeded the maximum global requests per minute for crawlers or humans.");
145
  }
@@ -165,11 +148,6 @@ class wfLog {
165
  }
166
  }
167
  }
168
- if(wfConfig::get('other_blockBadPOST') == '1' && $_SERVER['REQUEST_METHOD'] == 'POST' && empty($_SERVER['HTTP_USER_AGENT']) && empty($_SERVER['HTTP_REFERER'])){
169
- $this->blockIP($IP, "POST received with blank user-agent and referer");
170
- $this->do503(3600, "POST received with blank user-agent and referer");
171
- //exits
172
- }
173
  if(isset($_SERVER['HTTP_USER_AGENT']) && wfCrawl::isCrawler($_SERVER['HTTP_USER_AGENT'])){
174
  if($type == 'hit' && wfConfig::get('maxRequestsCrawlers') != 'DISABLED' && $hitsPerMinute > wfConfig::get('maxRequestsCrawlers')){
175
  $this->takeBlockingAction('maxRequestsCrawlers', "Exceeded the maximum number of requests per minute for crawlers."); //may not exit
123
 
124
  //Range blocking was here. Moved to wordfenceClass::veryFirstAction
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  if(wfConfig::get('maxGlobalRequests') != 'DISABLED' && $hitsPerMinute > wfConfig::get('maxGlobalRequests')){ //Applies to 404 or pageview
127
  $this->takeBlockingAction('maxGlobalRequests', "Exceeded the maximum global requests per minute for crawlers or humans.");
128
  }
148
  }
149
  }
150
  }
 
 
 
 
 
151
  if(isset($_SERVER['HTTP_USER_AGENT']) && wfCrawl::isCrawler($_SERVER['HTTP_USER_AGENT'])){
152
  if($type == 'hit' && wfConfig::get('maxRequestsCrawlers') != 'DISABLED' && $hitsPerMinute > wfConfig::get('maxRequestsCrawlers')){
153
  $this->takeBlockingAction('maxRequestsCrawlers', "Exceeded the maximum number of requests per minute for crawlers."); //may not exit
lib/wordfenceClass.php CHANGED
@@ -486,7 +486,7 @@ class wordfence {
486
  add_action('wordfence_hourly_cron', 'wordfence::hourlyCron');
487
  add_action('plugins_loaded', 'wordfence::veryFirstAction');
488
  add_action('init', 'wordfence::initAction');
489
- add_action('wp_loaded', 'wordfence::templateRedir', 0);
490
  add_action('shutdown', 'wordfence::shutdownAction');
491
 
492
  if(version_compare(PHP_VERSION, '5.4.0') >= 0){
@@ -495,6 +495,9 @@ class wordfence {
495
  add_action('wp_authenticate','wordfence::authActionOld', 1, 2);
496
  }
497
  add_filter('authenticate', 'wordfence::authenticateFilter', 99, 3);
 
 
 
498
 
499
  add_action('login_init','wordfence::loginInitAction');
500
  add_action('wp_login','wordfence::loginAction');
@@ -851,6 +854,41 @@ class wordfence {
851
  if(wfConfig::get('firewallEnabled')){
852
  $wfLog = self::getLog();
853
  $wfLog->firewallBadIPs();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
854
  }
855
  }
856
  public static function loginAction($username){
@@ -988,7 +1026,7 @@ class wordfence {
988
  if($blacklist = wfConfig::get('loginSec_userBlacklist')){
989
  $users = explode(',', $blacklist);
990
  foreach($users as $user){
991
- if(strtolower($_POST['log']) == strtolower($user)){
992
  self::getLog()->blockIP($IP, "Blocked by login security setting.");
993
  $secsToGo = wfConfig::get('blockedTime');
994
  self::getLog()->do503($secsToGo, "Blocked by login security setting.");
@@ -997,8 +1035,8 @@ class wordfence {
997
  }
998
  }
999
  if(wfConfig::get('loginSec_lockInvalidUsers')){
1000
- if(strlen($_POST['log']) > 0 && preg_match('/[^\r\s\n\t]+/', $_POST['log'])){
1001
- self::lockOutIP($IP, "Used an invalid username '" . $_POST['log'] . "' to try to sign in.");
1002
  }
1003
  require('wfLockedOut.php');
1004
  }
@@ -1012,7 +1050,7 @@ class wordfence {
1012
  $tries = 1;
1013
  }
1014
  if($tries >= wfConfig::get('loginSec_maxFailures')){
1015
- self::lockOutIP($IP, "Exceeded the maximum number of login failures which is: " . wfConfig::get('loginSec_maxFailures') . ". The last username they tried to sign in with was: '" . $_POST['log'] . "'");
1016
  require('wfLockedOut.php');
1017
  }
1018
  set_transient($tKey, $tries, wfConfig::get('loginSec_countFailMins') * 60);
@@ -1029,7 +1067,7 @@ class wordfence {
1029
  }
1030
 
1031
  if(is_wp_error($authUser) && ($authUser->get_error_code() == 'invalid_username' || $authUser->get_error_code() == 'incorrect_password') && wfConfig::get('loginSec_maskLoginErrors')){
1032
- return new WP_Error( 'incorrect_password', sprintf( __( '<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%2$s" title="Password Lost and Found">Lost your password</a>?' ), $_POST['log'], wp_lostpassword_url() ) );
1033
  }
1034
  return $authUser;
1035
  }
@@ -1857,7 +1895,7 @@ class wordfence {
1857
  wfConfig::set($key, $val);
1858
  }
1859
  }
1860
- if($regenerateHtaccess){
1861
  wfCache::addHtaccessCode('add');
1862
  }
1863
 
@@ -3505,13 +3543,19 @@ HTML;
3505
 
3506
 
3507
  /**
3508
- * Modify the query to look for scenarios
3509
  *
3510
  * @param array $query_vars
3511
  * @return array
3512
  */
3513
  public static function preventAuthorNScans($query_vars) {
3514
- if (wfConfig::get('loginSec_disableAuthorScan') && !empty($query_vars['author']) && is_numeric(preg_replace('/[^0-9]/', '', $query_vars['author']))) {
 
 
 
 
 
 
3515
  $query_vars['author'] = -1;
3516
  }
3517
  return $query_vars;
486
  add_action('wordfence_hourly_cron', 'wordfence::hourlyCron');
487
  add_action('plugins_loaded', 'wordfence::veryFirstAction');
488
  add_action('init', 'wordfence::initAction');
489
+ add_action('template_redirect', 'wordfence::templateRedir', 1001);
490
  add_action('shutdown', 'wordfence::shutdownAction');
491
 
492
  if(version_compare(PHP_VERSION, '5.4.0') >= 0){
495
  add_action('wp_authenticate','wordfence::authActionOld', 1, 2);
496
  }
497
  add_filter('authenticate', 'wordfence::authenticateFilter', 99, 3);
498
+ if (self::isLockedOut(wfUtils::getIP())) {
499
+ add_filter('xmlrpc_enabled', '__return_false');
500
+ }
501
 
502
  add_action('login_init','wordfence::loginInitAction');
503
  add_action('wp_login','wordfence::loginAction');
854
  if(wfConfig::get('firewallEnabled')){
855
  $wfLog = self::getLog();
856
  $wfLog->firewallBadIPs();
857
+
858
+ $IP = wfUtils::getIP();
859
+ if($wfLog->isWhitelisted($IP)){
860
+ return;
861
+ }
862
+ if (wfConfig::get('neverBlockBG') == 'neverBlockUA' && wfCrawl::isGoogleCrawler()) {
863
+ return;
864
+ }
865
+ if (wfConfig::get('neverBlockBG') == 'neverBlockVerified' && wfCrawl::isVerifiedGoogleCrawler()) {
866
+ return;
867
+ }
868
+
869
+ if(wfConfig::get('blockFakeBots')){
870
+ if(wfCrawl::isGooglebot() && (! wfCrawl::verifyCrawlerPTR($wfLog->getGooglePattern(), $IP) )){
871
+ $wfLog->blockIP($IP, "Fake Google crawler automatically blocked");
872
+ wordfence::status(2, 'info', "Blocking fake Googlebot at IP $IP");
873
+ $wfLog->do503(3600, "Fake Google crawler automatically blocked.");
874
+ }
875
+ }
876
+ if(wfConfig::get('bannedURLs', false)){
877
+ $URLs = explode(',', wfConfig::get('bannedURLs'));
878
+ foreach($URLs as $URL){
879
+ if($_SERVER['REQUEST_URI'] == trim($URL)){
880
+ $wfLog->blockIP($IP, "Accessed a banned URL.");
881
+ $wfLog->do503(3600, "Accessed a banned URL.");
882
+ //exits
883
+ }
884
+ }
885
+ }
886
+
887
+ if(wfConfig::get('other_blockBadPOST') == '1' && $_SERVER['REQUEST_METHOD'] == 'POST' && empty($_SERVER['HTTP_USER_AGENT']) && empty($_SERVER['HTTP_REFERER'])){
888
+ $wfLog->blockIP($IP, "POST received with blank user-agent and referer");
889
+ $wfLog->do503(3600, "POST received with blank user-agent and referer");
890
+ //exits
891
+ }
892
  }
893
  }
894
  public static function loginAction($username){
1026
  if($blacklist = wfConfig::get('loginSec_userBlacklist')){
1027
  $users = explode(',', $blacklist);
1028
  foreach($users as $user){
1029
+ if(strtolower($username) == strtolower($user)){
1030
  self::getLog()->blockIP($IP, "Blocked by login security setting.");
1031
  $secsToGo = wfConfig::get('blockedTime');
1032
  self::getLog()->do503($secsToGo, "Blocked by login security setting.");
1035
  }
1036
  }
1037
  if(wfConfig::get('loginSec_lockInvalidUsers')){
1038
+ if(strlen($username) > 0 && preg_match('/[^\r\s\n\t]+/', $username)){
1039
+ self::lockOutIP($IP, "Used an invalid username '" . $username . "' to try to sign in.");
1040
  }
1041
  require('wfLockedOut.php');
1042
  }
1050
  $tries = 1;
1051
  }
1052
  if($tries >= wfConfig::get('loginSec_maxFailures')){
1053
+ self::lockOutIP($IP, "Exceeded the maximum number of login failures which is: " . wfConfig::get('loginSec_maxFailures') . ". The last username they tried to sign in with was: '" . $username . "'");
1054
  require('wfLockedOut.php');
1055
  }
1056
  set_transient($tKey, $tries, wfConfig::get('loginSec_countFailMins') * 60);
1067
  }
1068
 
1069
  if(is_wp_error($authUser) && ($authUser->get_error_code() == 'invalid_username' || $authUser->get_error_code() == 'incorrect_password') && wfConfig::get('loginSec_maskLoginErrors')){
1070
+ return new WP_Error( 'incorrect_password', sprintf( __( '<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%2$s" title="Password Lost and Found">Lost your password</a>?' ), $username, wp_lostpassword_url() ) );
1071
  }
1072
  return $authUser;
1073
  }
1895
  wfConfig::set($key, $val);
1896
  }
1897
  }
1898
+ if($regenerateHtaccess && wfConfig::get('cacheType') == 'falcon'){
1899
  wfCache::addHtaccessCode('add');
1900
  }
1901
 
3543
 
3544
 
3545
  /**
3546
+ * Modify the query to prevent username enumeration.
3547
  *
3548
  * @param array $query_vars
3549
  * @return array
3550
  */
3551
  public static function preventAuthorNScans($query_vars) {
3552
+ if (wfConfig::get('loginSec_disableAuthorScan') && !is_admin() &&
3553
+ !empty($query_vars['author']) && is_numeric(preg_replace('/[^0-9]/', '', $query_vars['author'])) &&
3554
+ (
3555
+ (isset($_GET['author']) && is_numeric(preg_replace('/[^0-9]/', '', $_GET['author']))) ||
3556
+ (isset($_POST['author']) && is_numeric(preg_replace('/[^0-9]/', '', $_POST['author'])))
3557
+ )
3558
+ ) {
3559
  $query_vars['author'] = -1;
3560
  }
3561
  return $query_vars;
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
3
  Tags: wordpress, security, performance, speed, caching, cache, caching plugin, wordpress cache, wordpress caching, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure, two factor, cellphone sign-in, cellphone signin, cellphone, twofactor, security, secure, htaccess, login, log, users, login alerts, lock, chmod, maintenance, plugin, private, privacy, protection, permissions, 503, base64, injection, code, encode, script, attack, hack, hackers, block, blocked, prevent, prevention, RFI, XSS, CRLF, CSRF, SQL Injection, vulnerability, website security, WordPress security, security log, logging, HTTP log, error log, login security, personal security, infrastructure security, firewall security, front-end security, web server security, proxy security, reverse proxy security, secure website, secure login, two factor security, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm, woocommerce support, woocommerce caching, IPv6, IP version 6
4
  Requires at least: 3.9
5
  Tested up to: 4.3
6
- Stable tag: 6.0.16
7
 
8
  The Wordfence WordPress security plugin provides free enterprise-class WordPress security, protecting your website from hacks and malware.
9
  == Description ==
@@ -183,8 +183,15 @@ fully compatible with both IPv4 and IPv6 whether you run both or only one addres
183
 
184
  == Changelog ==
185
 
 
 
 
 
 
 
 
186
  = 6.0.16 =
187
- * Fix: Resolved issue with some variations of author=N scans not being caught.
188
  * Fix: Updated typo in author=N option.
189
  * Fix: Resolved issue with Falcon not writing to .htaccess with WP installed in subdirectory.
190
  * Fix: Added width to logo in activity report email.
3
  Tags: wordpress, security, performance, speed, caching, cache, caching plugin, wordpress cache, wordpress caching, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure, two factor, cellphone sign-in, cellphone signin, cellphone, twofactor, security, secure, htaccess, login, log, users, login alerts, lock, chmod, maintenance, plugin, private, privacy, protection, permissions, 503, base64, injection, code, encode, script, attack, hack, hackers, block, blocked, prevent, prevention, RFI, XSS, CRLF, CSRF, SQL Injection, vulnerability, website security, WordPress security, security log, logging, HTTP log, error log, login security, personal security, infrastructure security, firewall security, front-end security, web server security, proxy security, reverse proxy security, secure website, secure login, two factor security, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm, woocommerce support, woocommerce caching, IPv6, IP version 6
4
  Requires at least: 3.9
5
  Tested up to: 4.3
6
+ Stable tag: 6.0.17
7
 
8
  The Wordfence WordPress security plugin provides free enterprise-class WordPress security, protecting your website from hacks and malware.
9
  == Description ==
183
 
184
  == Changelog ==
185
 
186
+ = 6.0.17 =
187
+ * Fix: Resolved issue where 301 redirects count as 404s with throttling applied.
188
+ * Fix: Fixed Falcon .htaccess code writing to .htaccess when 'Immediately block IP's that access these URLs' option is modified.
189
+ * Fix: Fixed issue where filtering posts by author in wp-admin no longer works due to change in /?author=N scan prevention logic.
190
+ * Fix: Fixed issue in Live Traffic where 404s display as 200s.
191
+ * Fix: Resolved issue with throttling logins via XMLRPC are not applied.
192
+
193
  = 6.0.16 =
194
+ * Fix: Resolved issue with some variations of author=N scans not being caught. Thanks James Golovich.
195
  * Fix: Updated typo in author=N option.
196
  * Fix: Resolved issue with Falcon not writing to .htaccess with WP installed in subdirectory.
197
  * Fix: Added width to logo in activity report email.
wordfence.php CHANGED
@@ -4,13 +4,13 @@ Plugin Name: Wordfence Security
4
  Plugin URI: http://www.wordfence.com/
5
  Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
6
  Author: Wordfence
7
- Version: 6.0.16
8
  Author URI: http://www.wordfence.com/
9
  */
10
  if(defined('WP_INSTALLING') && WP_INSTALLING){
11
  return;
12
  }
13
- define('WORDFENCE_VERSION', '6.0.16');
14
  if(get_option('wordfenceActivated') != 1){
15
  add_action('activated_plugin','wordfence_save_activation_error'); function wordfence_save_activation_error(){ update_option('wf_plugin_act_error', ob_get_contents()); }
16
  }
4
  Plugin URI: http://www.wordfence.com/
5
  Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
6
  Author: Wordfence
7
+ Version: 6.0.17
8
  Author URI: http://www.wordfence.com/
9
  */
10
  if(defined('WP_INSTALLING') && WP_INSTALLING){
11
  return;
12
  }
13
+ define('WORDFENCE_VERSION', '6.0.17');
14
  if(get_option('wordfenceActivated') != 1){
15
  add_action('activated_plugin','wordfence_save_activation_error'); function wordfence_save_activation_error(){ update_option('wf_plugin_act_error', ob_get_contents()); }
16
  }