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');