Wordfence Security – Firewall & Malware Scan - Version 3.3.3

Version Description

  • Fixed errors caused by ini_set being disabled on certain servers.
  • Removed error logging messages in certain cases because some badly configured hosts write these errors to the web browser.
  • Fixed getIP code that was evaluating arrays as strings in some cases.
  • Added error logging so that if there is an activation error, the Wordfence will display the actual error to you.
  • Fixed issue that caused scan to output "Could not get the administrator's user ID." when a user has changed their table prefixes under certain conditions.
Download this release

Release Info

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

Code changes from version 3.3.2 to 3.3.3

lib/wfDB.php CHANGED
@@ -104,7 +104,7 @@ class wfDB {
104
  mysql_real_escape_string(1),
105
  mysql_real_escape_string('error'),
106
  mysql_real_escape_string($msg)), $this->dbh);
107
- error_log($msg);
108
  return;
109
  }
110
  }
104
  mysql_real_escape_string(1),
105
  mysql_real_escape_string('error'),
106
  mysql_real_escape_string($msg)), $this->dbh);
107
+ //error_log($msg);
108
  return;
109
  }
110
  }
lib/wfLog.php CHANGED
@@ -565,7 +565,7 @@ class wfLog {
565
  if($this->googleSafetyCheckOK()){
566
  $action = wfConfig::get($configVar . '_action');
567
  if(! $action){
568
- error_log("Wordfence action missing for configVar: $configVar");
569
  return;
570
  }
571
  $secsToGo = 0;
@@ -628,12 +628,12 @@ class wfLog {
628
  self::$gbSafeCache[$cacheKey] = true; //This isn't a Google UA, so it's OK to block
629
  }
630
  } else {
631
- error_log("Wordfence error: neverBlockBG option is not set.");
632
  self::$gbSafeCache[$cacheKey] = false; //Oops the config option is not set. This should never happen because it's set on install. So we return false to indicate it's not OK to block just for safety.
633
  }
634
  }
635
  if(! isset(self::$gbSafeCache[$cacheKey])){
636
- error_log("Wordfence assertion fail in googleSafetyCheckOK: cached value is not set.");
637
  return false; //for safety
638
  }
639
  return self::$gbSafeCache[$cacheKey]; //return cached value
565
  if($this->googleSafetyCheckOK()){
566
  $action = wfConfig::get($configVar . '_action');
567
  if(! $action){
568
+ //error_log("Wordfence action missing for configVar: $configVar");
569
  return;
570
  }
571
  $secsToGo = 0;
628
  self::$gbSafeCache[$cacheKey] = true; //This isn't a Google UA, so it's OK to block
629
  }
630
  } else {
631
+ //error_log("Wordfence error: neverBlockBG option is not set.");
632
  self::$gbSafeCache[$cacheKey] = false; //Oops the config option is not set. This should never happen because it's set on install. So we return false to indicate it's not OK to block just for safety.
633
  }
634
  }
635
  if(! isset(self::$gbSafeCache[$cacheKey])){
636
+ //error_log("Wordfence assertion fail in googleSafetyCheckOK: cached value is not set.");
637
  return false; //for safety
638
  }
639
  return self::$gbSafeCache[$cacheKey]; //return cached value
lib/wfUtils.php CHANGED
@@ -106,7 +106,7 @@ class wfUtils {
106
  $msg = "Wordfence can't get the IP of clients and therefore can't operate. We received IP: $IP. X-Forwarded-For was: " . $_SERVER['HTTP_X_FORWARDED_FOR'] . " REMOTE_ADDR was: " . $_SERVER['REMOTE_ADDR'];
107
  $possible = array();
108
  foreach($_SERVER as $key => $val){
109
- if(preg_match('/^\d+\.\d+\.\d+\.\d+/', $val) && strlen($val) < 255){
110
  if($val != '127.0.0.1'){
111
  $possible[$key] = $val;
112
  }
@@ -119,7 +119,6 @@ class wfUtils {
119
  }
120
  }
121
  wordfence::status(1, 'error', $msg);
122
- error_log($msg);
123
  return false;
124
  }
125
  }
@@ -230,7 +229,7 @@ class wfUtils {
230
  $maxMem = 256;
231
  }
232
  if( function_exists('memory_get_usage') && ( (int) @ini_get('memory_limit') < $maxMem ) ){
233
- @ini_set('memory_limit', $maxMem . 'M');
234
  }
235
  }
236
  public static function isAdmin(){
@@ -384,12 +383,12 @@ class wfUtils {
384
  self::$lastErrorReporting = @ini_get('error_reporting');
385
  @error_reporting(0);
386
  self::$lastDisplayErrors = @ini_get('display_errors');
387
- @ini_set('display_errors', 0);
388
  if(class_exists('wfScan')){ wfScan::$errorHandlingOn = false; }
389
  }
390
  public static function errorsOn(){
391
  @error_reporting(self::$lastErrorReporting);
392
- @ini_set('display_errors', self::$lastDisplayErrors);
393
  if(class_exists('wfScan')){ wfScan::$errorHandlingOn = true; }
394
  }
395
  public static function fileTooBig($file){ //Deals with files > 2 gigs on 32 bit systems which are reported with the wrong size due to integer overflow
@@ -455,7 +454,19 @@ class wfUtils {
455
  public static function localHumanDate(){
456
  return date('l jS \of F Y \a\t h:i:s A', time() + (3600 * get_option('gmt_offset')));
457
  }
458
-
 
 
 
 
 
 
 
 
 
 
 
 
459
  }
460
 
461
 
106
  $msg = "Wordfence can't get the IP of clients and therefore can't operate. We received IP: $IP. X-Forwarded-For was: " . $_SERVER['HTTP_X_FORWARDED_FOR'] . " REMOTE_ADDR was: " . $_SERVER['REMOTE_ADDR'];
107
  $possible = array();
108
  foreach($_SERVER as $key => $val){
109
+ if(is_string($val) && preg_match('/^\d+\.\d+\.\d+\.\d+/', $val) && strlen($val) < 255){
110
  if($val != '127.0.0.1'){
111
  $possible[$key] = $val;
112
  }
119
  }
120
  }
121
  wordfence::status(1, 'error', $msg);
 
122
  return false;
123
  }
124
  }
229
  $maxMem = 256;
230
  }
231
  if( function_exists('memory_get_usage') && ( (int) @ini_get('memory_limit') < $maxMem ) ){
232
+ self::iniSet('memory_limit', $maxMem . 'M');
233
  }
234
  }
235
  public static function isAdmin(){
383
  self::$lastErrorReporting = @ini_get('error_reporting');
384
  @error_reporting(0);
385
  self::$lastDisplayErrors = @ini_get('display_errors');
386
+ self::iniSet('display_errors', 0);
387
  if(class_exists('wfScan')){ wfScan::$errorHandlingOn = false; }
388
  }
389
  public static function errorsOn(){
390
  @error_reporting(self::$lastErrorReporting);
391
+ self::iniSet('display_errors', self::$lastDisplayErrors);
392
  if(class_exists('wfScan')){ wfScan::$errorHandlingOn = true; }
393
  }
394
  public static function fileTooBig($file){ //Deals with files > 2 gigs on 32 bit systems which are reported with the wrong size due to integer overflow
454
  public static function localHumanDate(){
455
  return date('l jS \of F Y \a\t h:i:s A', time() + (3600 * get_option('gmt_offset')));
456
  }
457
+ public static function funcEnabled($func){
458
+ if(! function_exists($func)){ return false; }
459
+ $disabled = explode(',', ini_get('disable_functions'));
460
+ foreach($disabled as $f){
461
+ if($func == $f){ return false; }
462
+ }
463
+ return true;
464
+ }
465
+ public static function iniSet($key, $val){
466
+ if(self::funcEnabled('ini_set')){
467
+ @ini_set($key, $val);
468
+ }
469
+ }
470
  }
471
 
472
 
lib/wordfenceClass.php CHANGED
@@ -1122,9 +1122,9 @@ class wordfence {
1122
  }
1123
  private static function wfFunc_testtime(){
1124
  header('Content-Type: text/plain');
1125
- ini_set('max_execution_time', 1800); //30 mins
1126
  @error_reporting(E_ALL);
1127
- @ini_set('display_errors','On');
1128
  set_error_handler('wordfence::memtest_error_handler', E_ALL);
1129
 
1130
  echo "Wordfence process duration benchmarking utility version " . WORDFENCE_VERSION . ".\n";
@@ -1144,7 +1144,7 @@ class wordfence {
1144
  private static function wfFunc_testmem(){
1145
  header('Content-Type: text/plain');
1146
  @error_reporting(E_ALL);
1147
- @ini_set('display_errors','On');
1148
  set_error_handler('wordfence::memtest_error_handler', E_ALL);
1149
 
1150
  echo "Wordfence Memory benchmarking utility version " . WORDFENCE_VERSION . ".\n";
@@ -1152,7 +1152,7 @@ class wordfence {
1152
  echo "Current maximum memory configured in php.ini: " . ini_get('memory_limit') . "\n";
1153
  echo "Current memory usage: " . sprintf('%.2f', memory_get_usage(true) / (1024 * 1024)) . "M\n";
1154
  echo "Setting max memory to 90M.\n";
1155
- ini_set('memory_limit', '90M');
1156
  echo "Starting memory benchmark. Seeing an error after this line is not unusual. Read the error carefully\nto determine how much memory your host allows. We have requested 90 megabytes.\n";
1157
  if(memory_get_usage(true) < 1){
1158
  echo "Exiting test because memory_get_usage() returned a negative number\n";
@@ -1322,30 +1322,28 @@ class wordfence {
1322
  'tourClosed' => wfConfig::get('tourClosed', 0)
1323
  ));
1324
  }
1325
- public static function configure_warning(){
1326
- if(! preg_match('/WordfenceSecOpt/', $_SERVER['REQUEST_URI'])){
1327
- $numRun = wfConfig::get('alertEmailMsgCount', 0);
1328
- if($numRun <= 3){
1329
- echo '<div id="wordfenceConfigWarning" class="updated fade"><p><strong>Please set up an email address to receive Wordfence security alerts</strong> on the <a href="admin.php?page=WordfenceSecOpt">Wordfence Options Page</a>. This message will appear ' . (3 - $numRun) . ' more times.</p></div>';
1330
- wfConfig::set('alertEmailMsgCount', ++$numRun);
1331
- }
1332
-
1333
  }
 
1334
  }
1335
  public static function noKeyError(){
1336
  echo '<div id="wordfenceConfigWarning" class="fade error"><p><strong>Wordfence could not get an API key from the Wordfence scanning servers when it activated.</strong> You can try to fix this by going to the Wordfence "options" page and hitting "Save Changes". This will cause Wordfence to retry fetching an API key for you. If you keep seeing this error it usually means your WordPress server can\'t connect to our scanning servers. You can try asking your WordPress host to allow your WordPress server to connect to noc1.wordfence.com.</p></div>';
1337
  }
1338
  public static function admin_menus(){
1339
  if(! wfUtils::isAdmin()){ return; }
1340
- /* Removed this because we now have the tour.
1341
- if(! wfConfig::get('alertEmails')){
1342
  if(wfUtils::isAdminPageMU()){
1343
- add_action('network_admin_notices', 'wordfence::configure_warning');
1344
  } else {
1345
- add_action('admin_notices', 'wordfence::configure_warning');
1346
  }
1347
  }
1348
- */
1349
  if(! wfConfig::get('apiKey')){
1350
  if(wfUtils::isAdminPageMU()){
1351
  add_action('network_admin_notices', 'wordfence::noKeyError');
1122
  }
1123
  private static function wfFunc_testtime(){
1124
  header('Content-Type: text/plain');
1125
+ wfUtils::iniSet('max_execution_time', 1800); //30 mins
1126
  @error_reporting(E_ALL);
1127
+ wfUtils::iniSet('display_errors','On');
1128
  set_error_handler('wordfence::memtest_error_handler', E_ALL);
1129
 
1130
  echo "Wordfence process duration benchmarking utility version " . WORDFENCE_VERSION . ".\n";
1144
  private static function wfFunc_testmem(){
1145
  header('Content-Type: text/plain');
1146
  @error_reporting(E_ALL);
1147
+ wfUtils::iniSet('display_errors','On');
1148
  set_error_handler('wordfence::memtest_error_handler', E_ALL);
1149
 
1150
  echo "Wordfence Memory benchmarking utility version " . WORDFENCE_VERSION . ".\n";
1152
  echo "Current maximum memory configured in php.ini: " . ini_get('memory_limit') . "\n";
1153
  echo "Current memory usage: " . sprintf('%.2f', memory_get_usage(true) / (1024 * 1024)) . "M\n";
1154
  echo "Setting max memory to 90M.\n";
1155
+ wfUtils::iniSet('memory_limit', '90M');
1156
  echo "Starting memory benchmark. Seeing an error after this line is not unusual. Read the error carefully\nto determine how much memory your host allows. We have requested 90 megabytes.\n";
1157
  if(memory_get_usage(true) < 1){
1158
  echo "Exiting test because memory_get_usage() returned a negative number\n";
1322
  'tourClosed' => wfConfig::get('tourClosed', 0)
1323
  ));
1324
  }
1325
+ public static function activation_warning(){
1326
+ $activationError = get_option('wf_plugin_act_error', '');
1327
+ if(strlen($activationError) > 400){
1328
+ $activationError = substr($activationError, 0, 400) . '...[output truncated]';
1329
+ }
1330
+ if($activationError){
1331
+ echo '<div id="wordfenceConfigWarning" class="updated fade"><p><strong>Wordfence generated an error on activation. Please report this on <a href="http://www.wordfence.com/forums/" target="_blank">our support forum</a>. The output we received during activation was:</strong> ' . htmlspecialchars($activationError) . '</p></div>';
 
1332
  }
1333
+ delete_option('wf_plugin_act_error');
1334
  }
1335
  public static function noKeyError(){
1336
  echo '<div id="wordfenceConfigWarning" class="fade error"><p><strong>Wordfence could not get an API key from the Wordfence scanning servers when it activated.</strong> You can try to fix this by going to the Wordfence "options" page and hitting "Save Changes". This will cause Wordfence to retry fetching an API key for you. If you keep seeing this error it usually means your WordPress server can\'t connect to our scanning servers. You can try asking your WordPress host to allow your WordPress server to connect to noc1.wordfence.com.</p></div>';
1337
  }
1338
  public static function admin_menus(){
1339
  if(! wfUtils::isAdmin()){ return; }
1340
+ if(get_option('wf_plugin_act_error', false)){
 
1341
  if(wfUtils::isAdminPageMU()){
1342
+ add_action('network_admin_notices', 'wordfence::activation_warning');
1343
  } else {
1344
+ add_action('admin_notices', 'wordfence::activation_warning');
1345
  }
1346
  }
 
1347
  if(! wfConfig::get('apiKey')){
1348
  if(wfUtils::isAdminPageMU()){
1349
  add_action('network_admin_notices', 'wordfence::noKeyError');
lib/wordfenceURLHoover.php CHANGED
@@ -47,11 +47,17 @@ class wordfenceURLHoover {
47
  }
48
  try {
49
  @preg_replace("/(?<=^|[^a-zA-Z0-9\-])((?:[a-zA-Z0-9\-]+\.)+)(" . $this->dRegex . ")((?:$|[^a-zA-Z0-9\-\.\'\"])[^\r\n\s\t\"\'\$\{\}<>]*)/ie", "\$this->" . "addHost(\$id, '$1$2', '$3')", $data);
50
- } catch(Exception $e){ error_log("Regex error 1: $e"); }
 
 
51
  @preg_replace("/(?<=[^\d]|^)(\d{8,10}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})([^\d\'\"][^\r\n\s\t\"\'\$\{\}<>]*)/e", "\$this->" . "addIP(\$id, \"$1\",\"$2\")", $data);
52
  $this->writeHosts();
53
  }
54
- private function dbg($msg){ if($this->debug){ error_log("DEBUG: $msg\n"); } }
 
 
 
 
55
  public function addHost($id, $host, $path){
56
  if(strpos($path, '/') !== 0){
57
  $path = '/';
47
  }
48
  try {
49
  @preg_replace("/(?<=^|[^a-zA-Z0-9\-])((?:[a-zA-Z0-9\-]+\.)+)(" . $this->dRegex . ")((?:$|[^a-zA-Z0-9\-\.\'\"])[^\r\n\s\t\"\'\$\{\}<>]*)/ie", "\$this->" . "addHost(\$id, '$1$2', '$3')", $data);
50
+ } catch(Exception $e){
51
+ //error_log("Regex error 1: $e");
52
+ }
53
  @preg_replace("/(?<=[^\d]|^)(\d{8,10}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})([^\d\'\"][^\r\n\s\t\"\'\$\{\}<>]*)/e", "\$this->" . "addIP(\$id, \"$1\",\"$2\")", $data);
54
  $this->writeHosts();
55
  }
56
+ private function dbg($msg){
57
+ if($this->debug){
58
+ //error_log("DEBUG: $msg\n");
59
+ }
60
+ }
61
  public function addHost($id, $host, $path){
62
  if(strpos($path, '/') !== 0){
63
  $path = '/';
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
3
  Tags: wordpress, security, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure
4
  Requires at least: 3.3.1
5
  Tested up to: 3.4.2
6
- Stable tag: 3.3.2
7
 
8
  Wordfence Security is a free enterprise class security plugin that includes a firewall, virus scanning, real-time traffic with geolocation and more.
9
 
@@ -153,6 +153,13 @@ or a theme, because often these have been updated to fix a security hole.
153
  5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
154
 
155
  == Changelog ==
 
 
 
 
 
 
 
156
  = 3.3.2 =
157
  * A complete rearchitecture of Wordfence scanning to massively improve performance.
158
  * Our free customers are now 100% back in business. Apologies for the delay, but this was worth the wait.
3
  Tags: wordpress, security, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure
4
  Requires at least: 3.3.1
5
  Tested up to: 3.4.2
6
+ Stable tag: 3.3.3
7
 
8
  Wordfence Security is a free enterprise class security plugin that includes a firewall, virus scanning, real-time traffic with geolocation and more.
9
 
153
  5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
154
 
155
  == Changelog ==
156
+ = 3.3.3 =
157
+ * Fixed errors caused by ini_set being disabled on certain servers.
158
+ * Removed error logging messages in certain cases because some badly configured hosts write these errors to the web browser.
159
+ * Fixed getIP code that was evaluating arrays as strings in some cases.
160
+ * Added error logging so that if there is an activation error, the Wordfence will display the actual error to you.
161
+ * Fixed issue that caused scan to output "Could not get the administrator's user ID." when a user has changed their table prefixes under certain conditions.
162
+
163
  = 3.3.2 =
164
  * A complete rearchitecture of Wordfence scanning to massively improve performance.
165
  * Our free customers are now 100% back in business. Apologies for the delay, but this was worth the wait.
wfscan.php CHANGED
@@ -65,7 +65,7 @@ class wfScan {
65
  }
66
  /* --------- end cronkey check ---------- */
67
 
68
- ini_set('max_execution_time', 1800); //30 mins
69
  self::status(4, 'info', "Becoming admin for scan");
70
  self::becomeAdmin();
71
  self::status(4, 'info', "Done become admin");
@@ -87,7 +87,7 @@ class wfScan {
87
  ob_start('wfScan::obHandler');
88
  }
89
  @error_reporting(E_ALL);
90
- @ini_set('display_errors','On');
91
  self::status(4, 'info', "Setting up scanRunning and starting scan");
92
  $scan = false;
93
  if($isFork){
@@ -195,8 +195,12 @@ class wfScan {
195
  //Last ditch attempt
196
  $adminUserID = $db->querySingle("select user_id from " . $wpdb->usermeta . " where meta_key='" . $wpdb->base_prefix . "user_level' order by meta_value desc, user_id asc limit 1");
197
  if(! $adminUserID){
198
- self::status(1, 'error', "Could not get the administrator's user ID. Scan can't continue.");
199
- exit();
 
 
 
 
200
  }
201
  $userSource = 'manual DB query';
202
  }
65
  }
66
  /* --------- end cronkey check ---------- */
67
 
68
+ wfUtils::iniSet('max_execution_time', 1800); //30 mins
69
  self::status(4, 'info', "Becoming admin for scan");
70
  self::becomeAdmin();
71
  self::status(4, 'info', "Done become admin");
87
  ob_start('wfScan::obHandler');
88
  }
89
  @error_reporting(E_ALL);
90
+ wfUtils::iniSet('display_errors','On');
91
  self::status(4, 'info', "Setting up scanRunning and starting scan");
92
  $scan = false;
93
  if($isFork){
195
  //Last ditch attempt
196
  $adminUserID = $db->querySingle("select user_id from " . $wpdb->usermeta . " where meta_key='" . $wpdb->base_prefix . "user_level' order by meta_value desc, user_id asc limit 1");
197
  if(! $adminUserID){
198
+ //One final attempt for those who have changed their table prefixes but the meta_key is still wp_ prefixed...
199
+ $adminUserID = $db->querySingle("select user_id from " . $wpdb->usermeta . " where meta_key='wp_user_level' order by meta_value desc, user_id asc limit 1");
200
+ if(! $adminUserID){
201
+ self::status(1, 'error', "Could not get the administrator's user ID. Scan can't continue.");
202
+ exit();
203
+ }
204
  }
205
  $userSource = 'manual DB query';
206
  }
wordfence.php CHANGED
@@ -4,13 +4,16 @@ Plugin Name: Wordfence Security
4
  Plugin URI: http://wordfence.com/
5
  Description: Wordfence Security - Anti-virus and Firewall security plugin for WordPress
6
  Author: Mark Maunder
7
- Version: 3.3.2
8
  Author URI: http://wordfence.com/
9
  */
10
- define('WORDFENCE_VERSION', '3.3.2');
 
11
  if(! defined('WORDFENCE_VERSIONONLY_MODE')){
12
  if((int) @ini_get('memory_limit') < 64){
13
- @ini_set('memory_limit', '64M'); //Some hosts have ini set at as little as 32 megs. 64 is the min sane amount of memory.
 
 
14
  }
15
  require_once('lib/wordfenceConstants.php');
16
  require_once('lib/wordfenceClass.php');
4
  Plugin URI: http://wordfence.com/
5
  Description: Wordfence Security - Anti-virus and Firewall security plugin for WordPress
6
  Author: Mark Maunder
7
+ Version: 3.3.3
8
  Author URI: http://wordfence.com/
9
  */
10
+ define('WORDFENCE_VERSION', '3.3.3');
11
+ add_action('activated_plugin','wordfence_save_activation_error'); function wordfence_save_activation_error(){ update_option('wf_plugin_act_error', ob_get_contents()); }
12
  if(! defined('WORDFENCE_VERSIONONLY_MODE')){
13
  if((int) @ini_get('memory_limit') < 64){
14
+ if(strpos(ini_get('disable_functions'), 'ini_set') === false){
15
+ @ini_set('memory_limit', '64M'); //Some hosts have ini set at as little as 32 megs. 64 is the min sane amount of memory.
16
+ }
17
  }
18
  require_once('lib/wordfenceConstants.php');
19
  require_once('lib/wordfenceClass.php');