Version Description
- Added another fix for "mysql server has gone away" error. Wordfence now makes sure the DB is still connected and reconnects if not.
- Added new detection for encoded malicious code in files.
- Fixed bug introduced yesterday that prevented permanent blocking of IP's.
- Improved ability to detect if we're running on Windows (but we don't support Windows yet).
- Issue intelligent warning if Wordfence can't read base WordPress directory.
- Don't activate Wordfence if user is running Windows.
- Cleaned up errors if a file can't be scanned due to permission restrictions.
- Improved reporting of which user scan is running as and how we determined who the admin user is.
Download this release
Release Info
Developer | mmaunder |
Plugin | Wordfence Security – Firewall & Malware Scan |
Version | 3.1.1 |
Comparing to | |
See all releases |
Code changes from version 3.1.0 to 3.1.1
- lib/wfDB.php +25 -4
- lib/wfLog.php +22 -9
- lib/wfScanEngine.php +3 -0
- lib/wfUtils.php +3 -1
- lib/wordfenceClass.php +4 -0
- lib/wordfenceHash.php +4 -1
- lib/wordfenceScanner.php +19 -3
- readme.txt +14 -1
- wfscan.php +7 -3
- wordfence.php +2 -2
lib/wfDB.php
CHANGED
@@ -6,8 +6,10 @@ class wfDB {
|
|
6 |
private $dbpassword = false;
|
7 |
private $dbname = false;
|
8 |
private $dbuser = false;
|
|
|
9 |
public $errorMsg = false;
|
10 |
public function __construct($createNewHandle = false, $dbhost = false, $dbuser = false, $dbpassword = false, $dbname = false){
|
|
|
11 |
if($dbhost && $dbuser && $dbpassword && $dbname){
|
12 |
$this->dbhost = $dbhost;
|
13 |
$this->dbuser = $dbuser;
|
@@ -37,14 +39,23 @@ class wfDB {
|
|
37 |
}
|
38 |
}
|
39 |
}
|
|
|
|
|
|
|
40 |
//We tried reusing wpdb but got disconnection errors from many users.
|
41 |
-
$handleKey = md5($dbhost . $dbuser . $dbpassword . $dbname);
|
42 |
-
if
|
|
|
43 |
$this->dbh = self::$dbhCache[$handleKey];
|
44 |
} else {
|
45 |
-
|
|
|
|
|
|
|
|
|
|
|
46 |
mysql_select_db($this->dbname, $dbh);
|
47 |
-
if($createNewHandle){
|
48 |
$this->dbh = $dbh;
|
49 |
} else {
|
50 |
self::$dbhCache[$handleKey] = $dbh;
|
@@ -56,7 +67,13 @@ class wfDB {
|
|
56 |
$this->queryIgnoreError("SET @@wait_timeout=30800"); //Changing to session setting bc user may not have super privilege
|
57 |
}
|
58 |
}
|
|
|
|
|
|
|
|
|
|
|
59 |
public function querySingleRec(){
|
|
|
60 |
$this->errorMsg = false;
|
61 |
$args = func_get_args();
|
62 |
if(sizeof($args) == 1){
|
@@ -81,6 +98,7 @@ class wfDB {
|
|
81 |
$msg = "Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err";
|
82 |
global $wpdb;
|
83 |
$statusTable = $wpdb->base_prefix . 'wfStatus';
|
|
|
84 |
mysql_query(sprintf("insert into " . $statusTable . " (ctime, level, type, msg) values (%s, %d, '%s', '%s')",
|
85 |
mysql_real_escape_string(sprintf('%.6f', microtime(true))),
|
86 |
mysql_real_escape_string(1),
|
@@ -91,6 +109,7 @@ class wfDB {
|
|
91 |
}
|
92 |
}
|
93 |
public function querySingle(){
|
|
|
94 |
$this->errorMsg = false;
|
95 |
$args = func_get_args();
|
96 |
if(sizeof($args) == 1){
|
@@ -113,6 +132,7 @@ class wfDB {
|
|
113 |
return $row[0];
|
114 |
}
|
115 |
public function query(){ //sprintfString, arguments
|
|
|
116 |
$this->errorMsg = false;
|
117 |
$args = func_get_args();
|
118 |
$isStatusQuery = false;
|
@@ -136,6 +156,7 @@ class wfDB {
|
|
136 |
return $res;
|
137 |
}
|
138 |
public function queryIgnoreError(){ //sprintfString, arguments
|
|
|
139 |
$this->errorMsg = false;
|
140 |
$args = func_get_args();
|
141 |
if(sizeof($args) == 1){
|
6 |
private $dbpassword = false;
|
7 |
private $dbname = false;
|
8 |
private $dbuser = false;
|
9 |
+
private $createNewHandle = false;
|
10 |
public $errorMsg = false;
|
11 |
public function __construct($createNewHandle = false, $dbhost = false, $dbuser = false, $dbpassword = false, $dbname = false){
|
12 |
+
$this->createNewHandle = $createNewHandle;
|
13 |
if($dbhost && $dbuser && $dbpassword && $dbname){
|
14 |
$this->dbhost = $dbhost;
|
15 |
$this->dbuser = $dbuser;
|
39 |
}
|
40 |
}
|
41 |
}
|
42 |
+
$this->connectHandle();
|
43 |
+
}
|
44 |
+
private function connectHandle(){
|
45 |
//We tried reusing wpdb but got disconnection errors from many users.
|
46 |
+
$handleKey = md5($this->dbhost . $this->dbuser . $this->dbpassword . $this->dbname);
|
47 |
+
//Use a cached handle if it exists and is still connected
|
48 |
+
if( (! $this->createNewHandle) && isset(self::$dbhCache[$handleKey]) && mysql_ping(self::$dbhCache[$handleKey]) ){
|
49 |
$this->dbh = self::$dbhCache[$handleKey];
|
50 |
} else {
|
51 |
+
//This close call is to deal with versions of mysql prior to 5.0.3 which auto-recommend when callig ping. So the conditional above may have reconnected this handle, so we disconnect it before reconnecting, if it's connected.
|
52 |
+
if(isset(self::$dbhCache[$handleKey]) && mysql_ping(self::$dbhCache[$handleKey])){
|
53 |
+
mysql_close(self::$dbhCache[$handleKey]);
|
54 |
+
unset(self::$dbhCache[$handleKey]);
|
55 |
+
}
|
56 |
+
$dbh = mysql_connect($this->dbhost, $this->dbuser, $this->dbpassword, true );
|
57 |
mysql_select_db($this->dbname, $dbh);
|
58 |
+
if($this->createNewHandle){
|
59 |
$this->dbh = $dbh;
|
60 |
} else {
|
61 |
self::$dbhCache[$handleKey] = $dbh;
|
67 |
$this->queryIgnoreError("SET @@wait_timeout=30800"); //Changing to session setting bc user may not have super privilege
|
68 |
}
|
69 |
}
|
70 |
+
private function reconnect(){
|
71 |
+
if(! mysql_ping($this->dbh)){
|
72 |
+
$this->connectHandle();
|
73 |
+
}
|
74 |
+
}
|
75 |
public function querySingleRec(){
|
76 |
+
$this->reconnect();
|
77 |
$this->errorMsg = false;
|
78 |
$args = func_get_args();
|
79 |
if(sizeof($args) == 1){
|
98 |
$msg = "Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err";
|
99 |
global $wpdb;
|
100 |
$statusTable = $wpdb->base_prefix . 'wfStatus';
|
101 |
+
$this->reconnect(); //Putting reconnect here so it doesn't mess with the mysql_error() call
|
102 |
mysql_query(sprintf("insert into " . $statusTable . " (ctime, level, type, msg) values (%s, %d, '%s', '%s')",
|
103 |
mysql_real_escape_string(sprintf('%.6f', microtime(true))),
|
104 |
mysql_real_escape_string(1),
|
109 |
}
|
110 |
}
|
111 |
public function querySingle(){
|
112 |
+
$this->reconnect();
|
113 |
$this->errorMsg = false;
|
114 |
$args = func_get_args();
|
115 |
if(sizeof($args) == 1){
|
132 |
return $row[0];
|
133 |
}
|
134 |
public function query(){ //sprintfString, arguments
|
135 |
+
$this->reconnect();
|
136 |
$this->errorMsg = false;
|
137 |
$args = func_get_args();
|
138 |
$isStatusQuery = false;
|
156 |
return $res;
|
157 |
}
|
158 |
public function queryIgnoreError(){ //sprintfString, arguments
|
159 |
+
$this->reconnect();
|
160 |
$this->errorMsg = false;
|
161 |
$args = func_get_args();
|
162 |
if(sizeof($args) == 1){
|
lib/wfLog.php
CHANGED
@@ -160,15 +160,28 @@ class wfLog {
|
|
160 |
public function blockIP($IP, $reason, $wfsn = false, $permanent = false){ //wfsn indicates it comes from Wordfence secure network
|
161 |
if($this->isWhitelisted($IP)){ return false; }
|
162 |
$wfsn = $wfsn ? 1 : 0;
|
163 |
-
$permanent
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
return true;
|
173 |
}
|
174 |
public function lockOutIP($IP, $reason){
|
160 |
public function blockIP($IP, $reason, $wfsn = false, $permanent = false){ //wfsn indicates it comes from Wordfence secure network
|
161 |
if($this->isWhitelisted($IP)){ return false; }
|
162 |
$wfsn = $wfsn ? 1 : 0;
|
163 |
+
if($permanent){
|
164 |
+
//Insert permanent=1 or update existing perm or non-per block to be permanent
|
165 |
+
$this->getDB()->query("insert into " . $this->blocksTable . " (IP, blockedTime, reason, wfsn, permanent) values (%s, unix_timestamp(), '%s', %d, %d) ON DUPLICATE KEY update blockedTime=unix_timestamp(), reason='%s', wfsn=%d, permanent=%d",
|
166 |
+
wfUtils::inet_aton($IP),
|
167 |
+
$reason,
|
168 |
+
$wfsn,
|
169 |
+
1,
|
170 |
+
$reason,
|
171 |
+
$wfsn,
|
172 |
+
1
|
173 |
+
);
|
174 |
+
} else {
|
175 |
+
//insert perm=0 but don't update and make perm blocks non-perm.
|
176 |
+
$this->getDB()->query("insert into " . $this->blocksTable . " (IP, blockedTime, reason, wfsn, permanent) values (%s, unix_timestamp(), '%s', %d, %d) ON DUPLICATE KEY update blockedTime=unix_timestamp(), reason='%s', wfsn=%d",
|
177 |
+
wfUtils::inet_aton($IP),
|
178 |
+
$reason,
|
179 |
+
$wfsn,
|
180 |
+
0,
|
181 |
+
$reason,
|
182 |
+
$wfsn
|
183 |
+
);
|
184 |
+
}
|
185 |
return true;
|
186 |
}
|
187 |
public function lockOutIP($IP, $reason){
|
lib/wfScanEngine.php
CHANGED
@@ -176,6 +176,9 @@ class wfScanEngine {
|
|
176 |
$this->hasher = new wordfenceHash(strlen(ABSPATH));
|
177 |
$baseWPStuff = array( '.htaccess', 'index.php', 'license.txt', 'readme.html', 'wp-activate.php', 'wp-admin', 'wp-app.php', 'wp-blog-header.php', 'wp-comments-post.php', 'wp-config-sample.php', 'wp-content', 'wp-cron.php', 'wp-includes', 'wp-links-opml.php', 'wp-load.php', 'wp-login.php', 'wp-mail.php', 'wp-pass.php', 'wp-register.php', 'wp-settings.php', 'wp-signup.php', 'wp-trackback.php', 'xmlrpc.php');
|
178 |
$baseContents = scandir(ABSPATH);
|
|
|
|
|
|
|
179 |
$scanOutside = wfConfig::get('other_scanOutside');
|
180 |
if($scanOutside){
|
181 |
wordfence::status(2, 'info', "Including files that are outside the WordPress installation in the scan.");
|
176 |
$this->hasher = new wordfenceHash(strlen(ABSPATH));
|
177 |
$baseWPStuff = array( '.htaccess', 'index.php', 'license.txt', 'readme.html', 'wp-activate.php', 'wp-admin', 'wp-app.php', 'wp-blog-header.php', 'wp-comments-post.php', 'wp-config-sample.php', 'wp-content', 'wp-cron.php', 'wp-includes', 'wp-links-opml.php', 'wp-load.php', 'wp-login.php', 'wp-mail.php', 'wp-pass.php', 'wp-register.php', 'wp-settings.php', 'wp-signup.php', 'wp-trackback.php', 'xmlrpc.php');
|
178 |
$baseContents = scandir(ABSPATH);
|
179 |
+
if(! is_array($baseContents)){
|
180 |
+
throw new Exception("Wordfence could not read the contents of your base WordPress directory. This usually indicates your permissions are so strict that your web server can't read your WordPress directory.");
|
181 |
+
}
|
182 |
$scanOutside = wfConfig::get('other_scanOutside');
|
183 |
if($scanOutside){
|
184 |
wordfence::status(2, 'info', "Including files that are outside the WordPress installation in the scan.");
|
lib/wfUtils.php
CHANGED
@@ -246,7 +246,7 @@ class wfUtils {
|
|
246 |
}
|
247 |
public static function isWindows(){
|
248 |
if(! self::$isWindows){
|
249 |
-
if(preg_match('/^win/', PHP_OS)){
|
250 |
self::$isWindows = 'yes';
|
251 |
} else {
|
252 |
self::$isWindows = 'no';
|
@@ -392,7 +392,9 @@ class wfUtils {
|
|
392 |
if(class_exists('wfScan')){ wfScan::$errorHandlingOn = true; }
|
393 |
}
|
394 |
public static function fileTooBig($file){
|
|
|
395 |
$fh = @fopen($file, 'r');
|
|
|
396 |
if(! $fh){ return false; }
|
397 |
$offset = WORDFENCE_MAX_FILE_SIZE_TO_PROCESS + 1;
|
398 |
$tooBig = false;
|
246 |
}
|
247 |
public static function isWindows(){
|
248 |
if(! self::$isWindows){
|
249 |
+
if(preg_match('/^win/i', PHP_OS)){
|
250 |
self::$isWindows = 'yes';
|
251 |
} else {
|
252 |
self::$isWindows = 'no';
|
392 |
if(class_exists('wfScan')){ wfScan::$errorHandlingOn = true; }
|
393 |
}
|
394 |
public static function fileTooBig($file){
|
395 |
+
wfUtils::errorsOff();
|
396 |
$fh = @fopen($file, 'r');
|
397 |
+
wfUtils::errorsOn();
|
398 |
if(! $fh){ return false; }
|
399 |
$offset = WORDFENCE_MAX_FILE_SIZE_TO_PROCESS + 1;
|
400 |
$tooBig = false;
|
lib/wordfenceClass.php
CHANGED
@@ -25,6 +25,10 @@ class wordfence {
|
|
25 |
private static $statusStartMsgs = array();
|
26 |
private static $debugOn = null;
|
27 |
public static function installPlugin(){
|
|
|
|
|
|
|
|
|
28 |
self::runInstall();
|
29 |
//Used by MU code below
|
30 |
update_option('wordfenceActivated', 1);
|
25 |
private static $statusStartMsgs = array();
|
26 |
private static $debugOn = null;
|
27 |
public static function installPlugin(){
|
28 |
+
if(wfUtils::isWindows()){
|
29 |
+
die("You are running Windows. Unfortunately Wordfence is not supported on Windows at this time. We may add Windows support in future, but have no ETA at present.");
|
30 |
+
}
|
31 |
+
|
32 |
self::runInstall();
|
33 |
//Used by MU code below
|
34 |
update_option('wordfenceActivated', 1);
|
lib/wordfenceHash.php
CHANGED
@@ -169,7 +169,7 @@ class wordfenceHash {
|
|
169 |
$this->writeHashingStatus();
|
170 |
}
|
171 |
} else {
|
172 |
-
wordfence::status(2, 'error', "Could not gen hash for file: $file");
|
173 |
}
|
174 |
}
|
175 |
private function sendHashPacket(){
|
@@ -199,7 +199,10 @@ class wordfenceHash {
|
|
199 |
return $this->hashStorageID;
|
200 |
}
|
201 |
public function wfHash($file){
|
|
|
202 |
$md5 = @md5_file($file, false);
|
|
|
|
|
203 |
if(! $md5){ return false; }
|
204 |
$fp = @fopen($file, "rb");
|
205 |
if(! $fp){
|
169 |
$this->writeHashingStatus();
|
170 |
}
|
171 |
} else {
|
172 |
+
wordfence::status(2, 'error', "Could not gen hash for file (probably because we don't have permission to access the file): $file");
|
173 |
}
|
174 |
}
|
175 |
private function sendHashPacket(){
|
199 |
return $this->hashStorageID;
|
200 |
}
|
201 |
public function wfHash($file){
|
202 |
+
wfUtils::errorsOff();
|
203 |
$md5 = @md5_file($file, false);
|
204 |
+
wfUtils::errorsOn();
|
205 |
+
|
206 |
if(! $md5){ return false; }
|
207 |
$fp = @fopen($file, "rb");
|
208 |
if(! $fp){
|
lib/wordfenceScanner.php
CHANGED
@@ -135,7 +135,23 @@ class wordfenceScanner {
|
|
135 |
));
|
136 |
break;
|
137 |
}
|
138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
$this->urlHoover->hoover($file, $data);
|
140 |
} else {
|
141 |
$this->urlHoover->hoover($file, $data);
|
@@ -170,7 +186,7 @@ class wordfenceScanner {
|
|
170 |
'ignoreP' => $this->path . $file,
|
171 |
'ignoreC' => md5_file($this->path . $file),
|
172 |
'shortMsg' => "File contains suspected malware URL: " . $this->path . $file,
|
173 |
-
'longMsg' => "This file contains a suspected malware URL listed on Google's list of malware sites. Wordfence decodes
|
174 |
'data' => array(
|
175 |
'file' => $file,
|
176 |
'badURL' => $result['URL'],
|
@@ -225,7 +241,7 @@ class wordfenceScanner {
|
|
225 |
}
|
226 |
public static function containsCode($arr){
|
227 |
foreach($arr as $elem){
|
228 |
-
if(preg_match('/(?:
|
229 |
return true;
|
230 |
}
|
231 |
}
|
135 |
));
|
136 |
break;
|
137 |
}
|
138 |
+
if(preg_match('/eval.*base'.'64_decode/i', $data)){
|
139 |
+
$this->addResult(array(
|
140 |
+
'type' => 'file',
|
141 |
+
'severity' => 1,
|
142 |
+
'ignoreP' => $this->path . $file,
|
143 |
+
'ignoreC' => $fileSum,
|
144 |
+
'shortMsg' => "This file may contain malicious executable code",
|
145 |
+
'longMsg' => "This file is a PHP executable file and contains an evaluation function and base"."64 decoding function on the same line. This is a common technique used by hackers to hide and execute code. If you know about this file you can choose to ignore it to exclude it from future scans.",
|
146 |
+
'data' => array(
|
147 |
+
'file' => $file,
|
148 |
+
'canDiff' => false,
|
149 |
+
'canFix' => false,
|
150 |
+
'canDelete' => true
|
151 |
+
)
|
152 |
+
));
|
153 |
+
break;
|
154 |
+
}
|
155 |
$this->urlHoover->hoover($file, $data);
|
156 |
} else {
|
157 |
$this->urlHoover->hoover($file, $data);
|
186 |
'ignoreP' => $this->path . $file,
|
187 |
'ignoreC' => md5_file($this->path . $file),
|
188 |
'shortMsg' => "File contains suspected malware URL: " . $this->path . $file,
|
189 |
+
'longMsg' => "This file contains a suspected malware URL listed on Google's list of malware sites. Wordfence decodes base"."64 when scanning files so the URL may not be visible if you view this file. The URL is: " . $result['URL'] . " - More info available at <a href=\"http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=" . urlencode($result['URL']) . "&client=googlechrome&hl=en-US\" target=\"_blank\">Google Safe Browsing diagnostic page</a>.",
|
190 |
'data' => array(
|
191 |
'file' => $file,
|
192 |
'badURL' => $result['URL'],
|
241 |
}
|
242 |
public static function containsCode($arr){
|
243 |
foreach($arr as $elem){
|
244 |
+
if(preg_match('/(?:base'.'64_decode|base'.'64_encode|eval|if|exists|isset|close|file|implode|fopen|while|feof|fread|fclose|fsockopen|fwrite|explode|chr|gethostbyname|strstr|filemtime|time|count|trim|rand|stristr|dir|mkdir|urlencode|ord|substr|unpack|strpos|sprintf)[\r\n\s\t]*\(/i', $elem)){
|
245 |
return true;
|
246 |
}
|
247 |
}
|
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.1
|
6 |
-
Stable tag: 3.1.
|
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 |
|
@@ -152,6 +152,16 @@ or a theme, because often these have been updated to fix a security hole.
|
|
152 |
5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
|
153 |
|
154 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
= 3.1.0 =
|
156 |
* Changed the way we monitor disk space from % to warning on 20 megs and critical on 5 megs remaining. This deals with very large disks in a more rational way. (Thanks Yael M. and Ola A.)
|
157 |
* We now deal with cases where the $_SERVER variable contains an array instead of string for IP address. It seems that some installations modify the value into an array. (Thanks S.S.)
|
@@ -468,6 +478,9 @@ or a theme, because often these have been updated to fix a security hole.
|
|
468 |
* Initial public release of Wordfence.
|
469 |
|
470 |
== Upgrade Notice ==
|
|
|
|
|
|
|
471 |
= 3.0.9 =
|
472 |
Upgrade immediately. Fixes two critical bugs: Could not get admin ID bug and permanent IP blocks not staying permanent.
|
473 |
|
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.1
|
6 |
+
Stable tag: 3.1.1
|
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 |
|
152 |
5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
|
153 |
|
154 |
== Changelog ==
|
155 |
+
= 3.1.1 =
|
156 |
+
* Added another fix for "mysql server has gone away" error. Wordfence now makes sure the DB is still connected and reconnects if not.
|
157 |
+
* Added new detection for encoded malicious code in files.
|
158 |
+
* Fixed bug introduced yesterday that prevented permanent blocking of IP's.
|
159 |
+
* Improved ability to detect if we're running on Windows (but we don't support Windows yet).
|
160 |
+
* Issue intelligent warning if Wordfence can't read base WordPress directory.
|
161 |
+
* Don't activate Wordfence if user is running Windows.
|
162 |
+
* Cleaned up errors if a file can't be scanned due to permission restrictions.
|
163 |
+
* Improved reporting of which user scan is running as and how we determined who the admin user is.
|
164 |
+
|
165 |
= 3.1.0 =
|
166 |
* Changed the way we monitor disk space from % to warning on 20 megs and critical on 5 megs remaining. This deals with very large disks in a more rational way. (Thanks Yael M. and Ola A.)
|
167 |
* We now deal with cases where the $_SERVER variable contains an array instead of string for IP address. It seems that some installations modify the value into an array. (Thanks S.S.)
|
478 |
* Initial public release of Wordfence.
|
479 |
|
480 |
== Upgrade Notice ==
|
481 |
+
= 3.1.1 =
|
482 |
+
Upgrade immediately. Fixes bug introduced in last release that broke permenent IP blocking.
|
483 |
+
|
484 |
= 3.0.9 =
|
485 |
Upgrade immediately. Fixes two critical bugs: Could not get admin ID bug and permanent IP blocks not staying permanent.
|
486 |
|
wfscan.php
CHANGED
@@ -152,10 +152,13 @@ class wfScan {
|
|
152 |
$db = new wfDB();
|
153 |
global $wpdb;
|
154 |
$adminUserID = false;
|
|
|
155 |
if(is_multisite()){
|
156 |
$users = get_users('role=super&fields=ID');
|
|
|
157 |
} else {
|
158 |
$users = get_users('role=administrator&fields=ID');
|
|
|
159 |
}
|
160 |
if(sizeof($users) > 1){
|
161 |
sort($users, SORT_NUMERIC);
|
@@ -167,12 +170,13 @@ class wfScan {
|
|
167 |
self::status(1, 'error', "Could not get the administrator's user ID. Scan can't continue.");
|
168 |
exit();
|
169 |
}
|
|
|
170 |
}
|
171 |
-
$adminUsername = $db->querySingle("select
|
172 |
-
self::status(4, 'info', "Scan will run as admin user '$adminUsername' with ID '$adminUserID'");
|
173 |
wp_set_current_user($adminUserID);
|
174 |
if(! is_user_logged_in()){
|
175 |
-
self::status(1, 'error', "Scan could not sign in as user '$adminUsername' with ID '$adminUserID'. Scan can't continue.");
|
176 |
exit();
|
177 |
}
|
178 |
self::status(4, 'info', "Scan authentication complete.");
|
152 |
$db = new wfDB();
|
153 |
global $wpdb;
|
154 |
$adminUserID = false;
|
155 |
+
$userSource = '';
|
156 |
if(is_multisite()){
|
157 |
$users = get_users('role=super&fields=ID');
|
158 |
+
$userSource = 'multisite get_users() function';
|
159 |
} else {
|
160 |
$users = get_users('role=administrator&fields=ID');
|
161 |
+
$userSource = 'singlesite get_users() function';
|
162 |
}
|
163 |
if(sizeof($users) > 1){
|
164 |
sort($users, SORT_NUMERIC);
|
170 |
self::status(1, 'error', "Could not get the administrator's user ID. Scan can't continue.");
|
171 |
exit();
|
172 |
}
|
173 |
+
$userSource = 'manual DB query';
|
174 |
}
|
175 |
+
$adminUsername = $db->querySingle("select user_login from " . $wpdb->users . " where ID=%d", $adminUserID);
|
176 |
+
self::status(4, 'info', "Scan will run as admin user '$adminUsername' with ID '$adminUserID' sourced from: $userSource");
|
177 |
wp_set_current_user($adminUserID);
|
178 |
if(! is_user_logged_in()){
|
179 |
+
self::status(1, 'error', "Scan could not sign in as user '$adminUsername' with ID '$adminUserID' from source '$userSource'. Scan can't continue.");
|
180 |
exit();
|
181 |
}
|
182 |
self::status(4, 'info', "Scan authentication complete.");
|
wordfence.php
CHANGED
@@ -4,10 +4,10 @@ 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.1.
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
-
define('WORDFENCE_VERSION', '3.1.
|
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.
|
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.1.1
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
+
define('WORDFENCE_VERSION', '3.1.1');
|
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.
|