Version Description
- Added ability to permanently block IP's
- Added ability to manually block IP's
- Made Wordfence more memory efficient, particularly the forking process.
- Fixed issue that caused WF to not work on databases with blank passwords.
- Wordfence now stops execution of a DB connection error is encountered.
- Clear cron jobs if Wordfence is uninstalled.
- Enabled hourly cron for Wordfence security network.
- Wordfence now works if your server doesn't have openssl installed
- Wordfence now works even if you don't have CURL
- Fixed visitor logging so it works with HTTPS websites.
- Alert emails now contain filenames in each alert description.
- Users with weak passwords alerts now contain the username in the email.
- Upgraded API to 1.7.
- Fixed issue that caused DISALLOW_FILE_MODS to make WF menu disappear.
- Modified wfDB to deal with very large queries without exceeding max_allowed_packet
- Fixed issue that broke ability to see file changes and repair files.
Download this release
Release Info
Developer | mmaunder |
Plugin | Wordfence Security – Firewall & Malware Scan |
Version | 2.1.1 |
Comparing to | |
See all releases |
Code changes from version 2.1.0 to 2.1.1
- js/admin.js +26 -7
- lib/menu_blockedIPs.php +9 -2
- lib/wfAPI.php +57 -18
- lib/wfConfig.php +36 -7
- lib/wfDB.php +44 -21
- lib/wfLog.php +12 -7
- lib/wfScanEngine.php +5 -5
- lib/wfSchema.php +2 -1
- lib/wfUtils.php +1 -1
- lib/wordfenceClass.php +44 -33
- lib/wordfenceConstants.php +3 -2
- lib/wordfenceScanner.php +3 -3
- readme.txt +20 -2
- wfscan.php +3 -2
- wordfence.php +2 -2
js/admin.js
CHANGED
@@ -177,7 +177,7 @@ window['wordfenceAdmin'] = {
|
|
177 |
summaryUpdated = true;
|
178 |
} else if(item.msg.indexOf('SUM_ENDERR') != -1){
|
179 |
var msg = item.msg.replace('SUM_ENDERR:', '');
|
180 |
-
jQuery('div.wfSummaryMsg:contains("' + msg + '")').next().addClass('wfSummaryErr').html('An error
|
181 |
summaryUpdated = true;
|
182 |
} else if(item.msg.indexOf('SUM_DISABLED:') != -1){
|
183 |
var msg = item.msg.replace('SUM_DISABLED:', '');
|
@@ -337,7 +337,7 @@ window['wordfenceAdmin'] = {
|
|
337 |
return;
|
338 |
} else if(res.errorAlert){
|
339 |
jQuery.colorbox({ width: '400px', html:
|
340 |
-
"<h3>An error
|
341 |
});
|
342 |
}
|
343 |
|
@@ -476,7 +476,7 @@ window['wordfenceAdmin'] = {
|
|
476 |
self.nonce = json.nonce;
|
477 |
}
|
478 |
if(json && json.errorMsg){
|
479 |
-
self.colorbox('400px', 'An error
|
480 |
}
|
481 |
cb(json);
|
482 |
},
|
@@ -498,7 +498,7 @@ window['wordfenceAdmin'] = {
|
|
498 |
jQuery.colorbox({ width: width, html: "<h3>" + heading + "</h3><p>" + body + "</p>"});
|
499 |
},
|
500 |
scanRunningMsg: function(){ this.colorbox('400px', "A scan is running", "A scan is currently in progress. Please wait until it finishes before starting another scan."); },
|
501 |
-
errorMsg: function(msg){ this.colorbox('400px', "An error
|
502 |
deleteFile: function(issueID){
|
503 |
var self = this;
|
504 |
this.ajax('wordfence_deleteFile', {
|
@@ -511,7 +511,7 @@ window['wordfenceAdmin'] = {
|
|
511 |
if(res.ok){
|
512 |
this.loadIssues(function(){ self.colorbox('400px', "Success deleting file", "The file " + res.file + " containing " + res.filesize + " bytes was successfully deleted."); });
|
513 |
} else if(res.cerrorMsg){
|
514 |
-
this.loadIssues(function(){ self.colorbox('400px', 'An error
|
515 |
}
|
516 |
},
|
517 |
restoreFile: function(issueID){
|
@@ -525,7 +525,7 @@ window['wordfenceAdmin'] = {
|
|
525 |
if(res.ok){
|
526 |
this.loadIssues(function(){ self.colorbox("400px", "File restored OK", "The file " + res.file + " was restored succesfully."); });
|
527 |
} else if(res.cerrorMsg){
|
528 |
-
this.loadIssues(function(){ self.colorbox('400px', 'An error
|
529 |
}
|
530 |
},
|
531 |
deleteIssue: function(id){
|
@@ -761,6 +761,19 @@ window['wordfenceAdmin'] = {
|
|
761 |
}
|
762 |
});
|
763 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
764 |
unlockOutIP: function(IP){
|
765 |
var self = this;
|
766 |
this.ajax('wordfence_unlockOutIP', {
|
@@ -773,6 +786,12 @@ window['wordfenceAdmin'] = {
|
|
773 |
IP: IP
|
774 |
}, function(res){ self.staticTabChanged(); });
|
775 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
776 |
makeElemID: function(){
|
777 |
return 'wfElemGen' + this.elementGeneratorIter++;
|
778 |
},
|
@@ -801,7 +820,7 @@ window['wordfenceAdmin'] = {
|
|
801 |
} else if(res.errorMsg){
|
802 |
return;
|
803 |
} else {
|
804 |
-
self.colorbox('400px', 'An error
|
805 |
}
|
806 |
});
|
807 |
},
|
177 |
summaryUpdated = true;
|
178 |
} else if(item.msg.indexOf('SUM_ENDERR') != -1){
|
179 |
var msg = item.msg.replace('SUM_ENDERR:', '');
|
180 |
+
jQuery('div.wfSummaryMsg:contains("' + msg + '")').next().addClass('wfSummaryErr').html('An error occurred.');
|
181 |
summaryUpdated = true;
|
182 |
} else if(item.msg.indexOf('SUM_DISABLED:') != -1){
|
183 |
var msg = item.msg.replace('SUM_DISABLED:', '');
|
337 |
return;
|
338 |
} else if(res.errorAlert){
|
339 |
jQuery.colorbox({ width: '400px', html:
|
340 |
+
"<h3>An error occurred:</h3><p>" + res.errorAlert + "</p>"
|
341 |
});
|
342 |
}
|
343 |
|
476 |
self.nonce = json.nonce;
|
477 |
}
|
478 |
if(json && json.errorMsg){
|
479 |
+
self.colorbox('400px', 'An error occurred', json.errorMsg);
|
480 |
}
|
481 |
cb(json);
|
482 |
},
|
498 |
jQuery.colorbox({ width: width, html: "<h3>" + heading + "</h3><p>" + body + "</p>"});
|
499 |
},
|
500 |
scanRunningMsg: function(){ this.colorbox('400px', "A scan is running", "A scan is currently in progress. Please wait until it finishes before starting another scan."); },
|
501 |
+
errorMsg: function(msg){ this.colorbox('400px', "An error occurred:", msg); },
|
502 |
deleteFile: function(issueID){
|
503 |
var self = this;
|
504 |
this.ajax('wordfence_deleteFile', {
|
511 |
if(res.ok){
|
512 |
this.loadIssues(function(){ self.colorbox('400px', "Success deleting file", "The file " + res.file + " containing " + res.filesize + " bytes was successfully deleted."); });
|
513 |
} else if(res.cerrorMsg){
|
514 |
+
this.loadIssues(function(){ self.colorbox('400px', 'An error occurred', res.cerrorMsg); });
|
515 |
}
|
516 |
},
|
517 |
restoreFile: function(issueID){
|
525 |
if(res.ok){
|
526 |
this.loadIssues(function(){ self.colorbox("400px", "File restored OK", "The file " + res.file + " was restored succesfully."); });
|
527 |
} else if(res.cerrorMsg){
|
528 |
+
this.loadIssues(function(){ self.colorbox('400px', 'An error occurred', res.cerrorMsg); });
|
529 |
}
|
530 |
},
|
531 |
deleteIssue: function(id){
|
761 |
}
|
762 |
});
|
763 |
},
|
764 |
+
blockIPTwo: function(IP, reason){
|
765 |
+
var self = this;
|
766 |
+
this.ajax('wordfence_blockIP', {
|
767 |
+
IP: IP,
|
768 |
+
reason: reason
|
769 |
+
}, function(res){
|
770 |
+
if(res.errorMsg){
|
771 |
+
return;
|
772 |
+
} else {
|
773 |
+
self.staticTabChanged();
|
774 |
+
}
|
775 |
+
});
|
776 |
+
},
|
777 |
unlockOutIP: function(IP){
|
778 |
var self = this;
|
779 |
this.ajax('wordfence_unlockOutIP', {
|
786 |
IP: IP
|
787 |
}, function(res){ self.staticTabChanged(); });
|
788 |
},
|
789 |
+
permBlockIP: function(IP){
|
790 |
+
var self = this;
|
791 |
+
this.ajax('wordfence_permBlockIP', {
|
792 |
+
IP: IP
|
793 |
+
}, function(res){ self.staticTabChanged(); });
|
794 |
+
},
|
795 |
makeElemID: function(){
|
796 |
return 'wfElemGen' + this.elementGeneratorIter++;
|
797 |
},
|
820 |
} else if(res.errorMsg){
|
821 |
return;
|
822 |
} else {
|
823 |
+
self.colorbox('400px', 'An error occurred', 'We encountered an error trying to save your changes.');
|
824 |
}
|
825 |
});
|
826 |
},
|
lib/menu_blockedIPs.php
CHANGED
@@ -7,7 +7,8 @@
|
|
7 |
</table>
|
8 |
</div>
|
9 |
<div class="wordfenceWrap" style="margin: 20px 20px 20px 30px;">
|
10 |
-
<a href="#" onclick="WFAD.clearAllBlocked('blocked'); return false;">Clear all blocked IP addresses</a> | <a href="#" onclick="WFAD.clearAllBlocked('locked'); return false;">Clear all locked out IP addresses</a
|
|
|
11 |
</div>
|
12 |
<div class="wordfenceWrap">
|
13 |
<div>
|
@@ -118,6 +119,9 @@
|
|
118 |
</div>
|
119 |
<div>
|
120 |
<strong>IP:</strong> <a href="${WFAD.makeIPTrafLink(IP)}" target="_blank">${IP}</a> [<a href="#" onclick="WFAD.unblockIP('${IP}'); return false;">unblock</a>]
|
|
|
|
|
|
|
121 |
</div>
|
122 |
<div>
|
123 |
<strong>Reason:</strong> ${reason}
|
@@ -142,7 +146,10 @@
|
|
142 |
<ul>
|
143 |
<li>${totalHits} hits before blocked</li>
|
144 |
<li>${blockedHits} blocked hits</li>
|
145 |
-
<li>
|
|
|
|
|
|
|
146 |
</ul>
|
147 |
</td></tr>
|
148 |
{{/each}}
|
7 |
</table>
|
8 |
</div>
|
9 |
<div class="wordfenceWrap" style="margin: 20px 20px 20px 30px;">
|
10 |
+
<a href="#" onclick="WFAD.clearAllBlocked('blocked'); return false;">Clear all blocked IP addresses</a> | <a href="#" onclick="WFAD.clearAllBlocked('locked'); return false;">Clear all locked out IP addresses</a><br />
|
11 |
+
You can manually block an IP by entering the address here: <input type="text" id="wfManualBlock" size="20" maxlength="40" value="" /> <input type="button" name="but1" value="Manually block IP" onclick="WFAD.blockIPTwo(jQuery('#wfManualBlock').val(), 'Manual block by administrator'); return false;" />
|
12 |
</div>
|
13 |
<div class="wordfenceWrap">
|
14 |
<div>
|
119 |
</div>
|
120 |
<div>
|
121 |
<strong>IP:</strong> <a href="${WFAD.makeIPTrafLink(IP)}" target="_blank">${IP}</a> [<a href="#" onclick="WFAD.unblockIP('${IP}'); return false;">unblock</a>]
|
122 |
+
{{if permanent == '1'}}
|
123 |
+
[<span style="color: #F00;">permanently blocked</span>]
|
124 |
+
{{else}} [<a href="#" onclick="WFAD.permBlockIP('${IP}'); return false;">make permanent</a>]{{/if}}
|
125 |
</div>
|
126 |
<div>
|
127 |
<strong>Reason:</strong> ${reason}
|
146 |
<ul>
|
147 |
<li>${totalHits} hits before blocked</li>
|
148 |
<li>${blockedHits} blocked hits</li>
|
149 |
+
<li>
|
150 |
+
{{if permanent == '1'}}Permanently blocked{{else}}
|
151 |
+
Will be unblocked in ${blockedForAgo}{{/if}}
|
152 |
+
</li>
|
153 |
</ul>
|
154 |
</td></tr>
|
155 |
{{/each}}
|
lib/wfAPI.php
CHANGED
@@ -16,7 +16,7 @@ class wfAPI {
|
|
16 |
}
|
17 |
public function call($action, $getParams = array(), $postParams = array()){
|
18 |
$this->errorMsg = false;
|
19 |
-
$json = $this->getURL(
|
20 |
array_merge(
|
21 |
array('action' => $action),
|
22 |
$getParams
|
@@ -76,7 +76,7 @@ class wfAPI {
|
|
76 |
return false;
|
77 |
}
|
78 |
} else {
|
79 |
-
$data =
|
80 |
if($data === false){
|
81 |
$err = error_get_last();
|
82 |
$this->lastURLError = $err;
|
@@ -86,24 +86,55 @@ class wfAPI {
|
|
86 |
}
|
87 |
|
88 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
public function binCall($func, $postData){
|
90 |
$this->errorMsg = false;
|
91 |
-
$url =
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
if(preg_match('/\{.*errorMsg/', $data)){
|
108 |
$jdat = @json_decode($data, true);
|
109 |
if(is_array($jdat) && $jdat['errorMsg']){
|
@@ -124,6 +155,14 @@ class wfAPI {
|
|
124 |
'k' => $this->APIKey
|
125 |
));
|
126 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
}
|
128 |
|
129 |
?>
|
16 |
}
|
17 |
public function call($action, $getParams = array(), $postParams = array()){
|
18 |
$this->errorMsg = false;
|
19 |
+
$json = $this->getURL($this->getAPIURL() . '/v' . WORDFENCE_API_VERSION . '/?' . $this->makeAPIQueryString() . '&' . http_build_query(
|
20 |
array_merge(
|
21 |
array('action' => $action),
|
22 |
$getParams
|
76 |
return false;
|
77 |
}
|
78 |
} else {
|
79 |
+
$data = $this->fileGet($url, $postParams);
|
80 |
if($data === false){
|
81 |
$err = error_get_last();
|
82 |
$this->lastURLError = $err;
|
86 |
}
|
87 |
|
88 |
}
|
89 |
+
private function fileGet($url, $postParams){
|
90 |
+
$body = "";
|
91 |
+
if(is_array($postParams)){
|
92 |
+
$bodyArr = array();
|
93 |
+
foreach($postParams as $key => $val){
|
94 |
+
$bodyArr[] = urlencode($key) . '=' . urlencode($val);
|
95 |
+
}
|
96 |
+
$body = implode('&', $bodyArr);
|
97 |
+
} else {
|
98 |
+
$body = $postParams;
|
99 |
+
}
|
100 |
+
$opts = array('http' =>
|
101 |
+
array(
|
102 |
+
'method' => 'POST',
|
103 |
+
'content' => $body,
|
104 |
+
'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
|
105 |
+
'timeout' => 60
|
106 |
+
)
|
107 |
+
);
|
108 |
+
$context = stream_context_create($opts);
|
109 |
+
return @file_get_contents($url, false, $context, -1);
|
110 |
+
}
|
111 |
public function binCall($func, $postData){
|
112 |
$this->errorMsg = false;
|
113 |
+
$url = $this->getAPIURL() . '/v' . WORDFENCE_API_VERSION . '/?' . $this->makeAPIQueryString() . '&action=' . $func;
|
114 |
+
if(function_exists('curl_init')){
|
115 |
+
$curl = curl_init($url);
|
116 |
+
curl_setopt ($curl, CURLOPT_TIMEOUT, 300);
|
117 |
+
//curl_setopt($curl, CURLOPT_VERBOSE, true);
|
118 |
+
curl_setopt ($curl, CURLOPT_USERAGENT, "Wordfence");
|
119 |
+
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, TRUE);
|
120 |
+
curl_setopt ($curl, CURLOPT_SSL_VERIFYPEER, false);
|
121 |
+
curl_setopt ($curl, CURLOPT_SSL_VERIFYHOST, false);
|
122 |
+
curl_setopt($curl, CURLOPT_POST, true);
|
123 |
+
if($postData){
|
124 |
+
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
|
125 |
+
} else {
|
126 |
+
curl_setopt($curl, CURLOPT_POSTFIELDS, array());
|
127 |
+
}
|
128 |
+
$data = curl_exec($curl);
|
129 |
+
$httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
130 |
+
} else {
|
131 |
+
$data = $this->fileGet($url, $postData);
|
132 |
+
if($data === false){
|
133 |
+
$this->errorMsg = error_get_last();
|
134 |
+
return false;
|
135 |
+
}
|
136 |
+
$httpStatus = '200';
|
137 |
+
}
|
138 |
if(preg_match('/\{.*errorMsg/', $data)){
|
139 |
$jdat = @json_decode($data, true);
|
140 |
if(is_array($jdat) && $jdat['errorMsg']){
|
155 |
'k' => $this->APIKey
|
156 |
));
|
157 |
}
|
158 |
+
private function getAPIURL(){
|
159 |
+
$ssl_supported = false;
|
160 |
+
if(defined('CURL_VERSION_SSL') && function_exists('curl_version')){
|
161 |
+
$version = curl_version();
|
162 |
+
$ssl_supported = ($version['features'] & CURL_VERSION_SSL);
|
163 |
+
}
|
164 |
+
return $ssl_supported ? WORDFENCE_API_URL_SEC : WORDFENCE_API_URL_NONSEC;
|
165 |
+
}
|
166 |
}
|
167 |
|
168 |
?>
|
lib/wfConfig.php
CHANGED
@@ -366,6 +366,27 @@ class wfConfig {
|
|
366 |
public static function clearCache(){
|
367 |
self::$cache = array();
|
368 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
369 |
public static function set($key, $val){
|
370 |
if(is_array($val)){
|
371 |
$trace=debug_backtrace(); $caller=array_shift($trace); error_log("wfConfig::set() got array as second param. Please use set_ser(). " . $caller['file'] . " line " . $caller['line']);
|
@@ -389,14 +410,22 @@ class wfConfig {
|
|
389 |
return self::$cache[$key];
|
390 |
}
|
391 |
public static function get_ser($key, $default){
|
392 |
-
$
|
393 |
-
|
394 |
-
|
|
|
|
|
|
|
|
|
|
|
395 |
}
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
|
|
|
|
|
|
400 |
}
|
401 |
public static function f($key){
|
402 |
echo esc_attr(self::get($key));
|
366 |
public static function clearCache(){
|
367 |
self::$cache = array();
|
368 |
}
|
369 |
+
public static function set_ser($key, $val){
|
370 |
+
//We serialize some very big values so this is ultra-memory efficient. We don't make any copies of $val and don't use ON DUPLICATE KEY UPDATE
|
371 |
+
// because we would have to concatenate $val twice into the query which could also exceed max packet for the mysql server
|
372 |
+
$dbh = self::getDB()->getDBH();
|
373 |
+
$exists = self::getDB()->querySingle("select name from " . self::table() . " where name='%s'", $key);
|
374 |
+
if($exists){
|
375 |
+
wordfence::status(4, 'info', "set_ser() updating key $key with value to be serialized that has type: " . gettype($val));
|
376 |
+
$res = mysql_query("update " . self::table() . " set val='" . mysql_real_escape_string(serialize($val)) . "' where name='" . mysql_real_escape_string($key) . "'", $dbh);
|
377 |
+
} else {
|
378 |
+
wordfence::status(4, 'info', "set_ser() inserting key $key with value to be serialized that has type: " . gettype($val));
|
379 |
+
$res = mysql_query("insert IGNORE into " . self::table() . " (name, val) values ('" . mysql_real_escape_string($key) . "', '" . mysql_real_escape_string(serialize($val)) . "')", $dbh);
|
380 |
+
}
|
381 |
+
$err = mysql_error();
|
382 |
+
if($err){
|
383 |
+
$trace=debug_backtrace();
|
384 |
+
$caller=array_shift($trace);
|
385 |
+
wordfence::status(2, 'error', "Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
386 |
+
return false;
|
387 |
+
}
|
388 |
+
return true;
|
389 |
+
}
|
390 |
public static function set($key, $val){
|
391 |
if(is_array($val)){
|
392 |
$trace=debug_backtrace(); $caller=array_shift($trace); error_log("wfConfig::set() got array as second param. Please use set_ser(). " . $caller['file'] . " line " . $caller['line']);
|
410 |
return self::$cache[$key];
|
411 |
}
|
412 |
public static function get_ser($key, $default){
|
413 |
+
$dbh = self::getDB()->getDBH();
|
414 |
+
$res = mysql_query("select val from " . self::table() . " where name='" . mysql_real_escape_string($key) . "'", $dbh);
|
415 |
+
$err = mysql_error();
|
416 |
+
if($err){
|
417 |
+
$trace=debug_backtrace();
|
418 |
+
$caller=array_shift($trace);
|
419 |
+
wordfence::status(2, 'error', "Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
420 |
+
return false;
|
421 |
}
|
422 |
+
|
423 |
+
if(mysql_num_rows($res) > 0){
|
424 |
+
$row = mysql_fetch_row($res);
|
425 |
+
wordfence::status(4, 'info', "get_ser() Unserializing key $key with data length " . strlen($row[0]));
|
426 |
+
return unserialize($row[0]);
|
427 |
+
}
|
428 |
+
return $default;
|
429 |
}
|
430 |
public static function f($key){
|
431 |
echo esc_attr(self::get($key));
|
lib/wfDB.php
CHANGED
@@ -16,14 +16,12 @@ class wfDB {
|
|
16 |
} else {
|
17 |
global $wpdb;
|
18 |
if(! $wpdb){
|
19 |
-
|
20 |
-
return;
|
21 |
}
|
22 |
-
if(! $wpdb->dbhost ){
|
23 |
-
if(! $wpdb->dbuser ){
|
24 |
-
if(! $wpdb->dbpassword ){
|
25 |
-
if(! $wpdb->dbname ){
|
26 |
-
if($this->errorMsg){ return; }
|
27 |
$this->dbhost = $wpdb->dbhost;
|
28 |
$this->dbuser = $wpdb->dbuser;
|
29 |
$this->dbpassword = $wpdb->dbpassword;
|
@@ -32,12 +30,13 @@ class wfDB {
|
|
32 |
if($createNewHandle){
|
33 |
$dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, true );
|
34 |
if($dbh === false){
|
35 |
-
|
36 |
-
return;
|
37 |
}
|
38 |
mysql_select_db($this->dbname, $dbh);
|
39 |
$this->dbh = $dbh;
|
40 |
$this->query("SET NAMES 'utf8'");
|
|
|
|
|
41 |
} else {
|
42 |
$handleKey = md5($dbhost . $dbuser . $dbpassword . $dbname);
|
43 |
if(isset(self::$dbhCache[$handleKey])){
|
@@ -45,14 +44,15 @@ class wfDB {
|
|
45 |
} else {
|
46 |
$dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, true );
|
47 |
if($dbh === false){
|
48 |
-
|
49 |
-
return;
|
50 |
}
|
51 |
|
52 |
mysql_select_db($this->dbname, $dbh);
|
53 |
self::$dbhCache[$handleKey] = $dbh;
|
54 |
$this->dbh = self::$dbhCache[$handleKey];
|
55 |
$this->query("SET NAMES 'utf8'");
|
|
|
|
|
56 |
}
|
57 |
}
|
58 |
}
|
@@ -68,9 +68,9 @@ class wfDB {
|
|
68 |
}
|
69 |
$res = mysql_query($query, $this->dbh);
|
70 |
$err = mysql_error();
|
71 |
-
if($err){
|
72 |
$this->errorMsg = $err;
|
73 |
-
$trace=debug_backtrace(); $caller=array_shift($trace);
|
74 |
}
|
75 |
return mysql_fetch_assoc($res); //returns false if no rows found
|
76 |
}
|
@@ -89,9 +89,9 @@ class wfDB {
|
|
89 |
}
|
90 |
$res = mysql_query($query, $this->dbh);
|
91 |
$err = mysql_error();
|
92 |
-
if($err){
|
93 |
$this->errorMsg = $err;
|
94 |
-
$trace=debug_backtrace(); $caller=array_shift($trace);
|
95 |
}
|
96 |
if(! $res){
|
97 |
return false;
|
@@ -103,26 +103,48 @@ class wfDB {
|
|
103 |
public function query(){ //sprintfString, arguments
|
104 |
$this->errorMsg = false;
|
105 |
$args = func_get_args();
|
|
|
106 |
if(sizeof($args) == 1){
|
107 |
-
|
|
|
|
|
|
|
108 |
} else if(sizeof($args) > 1){
|
109 |
for($i = 1; $i < sizeof($args); $i++){
|
|
|
|
|
|
|
110 |
$args[$i] = mysql_real_escape_string($args[$i]);
|
111 |
}
|
112 |
-
$
|
113 |
} else {
|
114 |
wfdie("No arguments passed to query()");
|
115 |
}
|
116 |
-
$res = mysql_query($query, $this->dbh);
|
117 |
$err = mysql_error();
|
118 |
-
if($err){
|
119 |
$this->errorMsg = $err;
|
120 |
-
$trace=debug_backtrace(); $caller=array_shift($trace);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
}
|
122 |
return $res;
|
123 |
}
|
|
|
124 |
private function wfdie($msg){
|
125 |
-
error_log($msg);
|
126 |
exit(1);
|
127 |
}
|
128 |
public function createKeyIfNotExists($table, $col, $keyName){
|
@@ -144,6 +166,7 @@ class wfDB {
|
|
144 |
$this->query("alter table $table add KEY $keyName($col)");
|
145 |
}
|
146 |
}
|
|
|
147 |
}
|
148 |
|
149 |
?>
|
16 |
} else {
|
17 |
global $wpdb;
|
18 |
if(! $wpdb){
|
19 |
+
self::wfdie("The WordPress variable wpdb is not defined.");
|
|
|
20 |
}
|
21 |
+
if(! $wpdb->dbhost ){ self::wfdie("The WordPress variable from wpdb dbhost is not defined."); }
|
22 |
+
if(! $wpdb->dbuser ){ self::wfdie("The WordPress variable from wpdb dbuser is not defined."); }
|
23 |
+
if(! isset($wpdb->dbpassword) ){ self::wfdie("The WordPress variable from wpdb dbpassword is not defined."); }
|
24 |
+
if(! $wpdb->dbname ){ self::wfdie("The WordPress variable from wpdb dbname is not defined."); }
|
|
|
25 |
$this->dbhost = $wpdb->dbhost;
|
26 |
$this->dbuser = $wpdb->dbuser;
|
27 |
$this->dbpassword = $wpdb->dbpassword;
|
30 |
if($createNewHandle){
|
31 |
$dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, true );
|
32 |
if($dbh === false){
|
33 |
+
self::wfdie("Could not connect to database on " . $this->dbhost . " with user " . $this->dbuser . ' : ' . mysql_error());
|
|
|
34 |
}
|
35 |
mysql_select_db($this->dbname, $dbh);
|
36 |
$this->dbh = $dbh;
|
37 |
$this->query("SET NAMES 'utf8'");
|
38 |
+
//Set big packets for set_ser when it serializes a scan in between forks
|
39 |
+
$this->queryIgnoreError("SET GLOBAL max_allowed_packet=256*1024*1024");
|
40 |
} else {
|
41 |
$handleKey = md5($dbhost . $dbuser . $dbpassword . $dbname);
|
42 |
if(isset(self::$dbhCache[$handleKey])){
|
44 |
} else {
|
45 |
$dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, true );
|
46 |
if($dbh === false){
|
47 |
+
self::wfdie("Could not connect to database on " . $this->dbhost . " with user " . $this->dbuser . ' : ' . mysql_error());
|
|
|
48 |
}
|
49 |
|
50 |
mysql_select_db($this->dbname, $dbh);
|
51 |
self::$dbhCache[$handleKey] = $dbh;
|
52 |
$this->dbh = self::$dbhCache[$handleKey];
|
53 |
$this->query("SET NAMES 'utf8'");
|
54 |
+
//Set big packets for set_ser when it serializes a scan in between forks
|
55 |
+
$this->queryIgnoreError("SET GLOBAL max_allowed_packet=256*1024*1024");
|
56 |
}
|
57 |
}
|
58 |
}
|
68 |
}
|
69 |
$res = mysql_query($query, $this->dbh);
|
70 |
$err = mysql_error();
|
71 |
+
if( (! preg_match('/Wordfence DB error/i', $query)) && $err){ //prevent loops
|
72 |
$this->errorMsg = $err;
|
73 |
+
$trace=debug_backtrace(); $caller=array_shift($trace); wordfence::status(2, 'error', "Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
74 |
}
|
75 |
return mysql_fetch_assoc($res); //returns false if no rows found
|
76 |
}
|
89 |
}
|
90 |
$res = mysql_query($query, $this->dbh);
|
91 |
$err = mysql_error();
|
92 |
+
if( (! preg_match('/Wordfence DB error/i', $query)) && $err){
|
93 |
$this->errorMsg = $err;
|
94 |
+
$trace=debug_backtrace(); $caller=array_shift($trace); wordfence::status(2, 'error', "Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
95 |
}
|
96 |
if(! $res){
|
97 |
return false;
|
103 |
public function query(){ //sprintfString, arguments
|
104 |
$this->errorMsg = false;
|
105 |
$args = func_get_args();
|
106 |
+
$isStatusQuery = false;
|
107 |
if(sizeof($args) == 1){
|
108 |
+
if(preg_match('/Wordfence DB error/i', $args[0])){
|
109 |
+
$isStatusQuery = true;
|
110 |
+
}
|
111 |
+
$res = mysql_query($args[0], $this->dbh);
|
112 |
} else if(sizeof($args) > 1){
|
113 |
for($i = 1; $i < sizeof($args); $i++){
|
114 |
+
if(preg_match('/Wordfence DB error/i', $args[$i])){
|
115 |
+
$isStatusQuery = true;
|
116 |
+
}
|
117 |
$args[$i] = mysql_real_escape_string($args[$i]);
|
118 |
}
|
119 |
+
$res = mysql_query(call_user_func_array('sprintf', $args), $this->dbh);
|
120 |
} else {
|
121 |
wfdie("No arguments passed to query()");
|
122 |
}
|
|
|
123 |
$err = mysql_error();
|
124 |
+
if( (! $isStatusQuery) && $err){ //isStatusQuery prevents loops if status itself is causing error
|
125 |
$this->errorMsg = $err;
|
126 |
+
$trace=debug_backtrace(); $caller=array_shift($trace); wordfence::status(2, 'error', "Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
127 |
+
}
|
128 |
+
return $res;
|
129 |
+
}
|
130 |
+
public function queryIgnoreError(){ //sprintfString, arguments
|
131 |
+
$this->errorMsg = false;
|
132 |
+
$args = func_get_args();
|
133 |
+
if(sizeof($args) == 1){
|
134 |
+
$res = mysql_query($args[0], $this->dbh);
|
135 |
+
} else if(sizeof($args) > 1){
|
136 |
+
for($i = 1; $i < sizeof($args); $i++){
|
137 |
+
$args[$i] = mysql_real_escape_string($args[$i]);
|
138 |
+
}
|
139 |
+
$res = mysql_query(call_user_func_array('sprintf', $args), $this->dbh);
|
140 |
+
} else {
|
141 |
+
wfdie("No arguments passed to query()");
|
142 |
}
|
143 |
return $res;
|
144 |
}
|
145 |
+
|
146 |
private function wfdie($msg){
|
147 |
+
error_log("Wordfence critical database error: $msg");
|
148 |
exit(1);
|
149 |
}
|
150 |
public function createKeyIfNotExists($table, $col, $keyName){
|
166 |
$this->query("alter table $table add KEY $keyName($col)");
|
167 |
}
|
168 |
}
|
169 |
+
public function getDBH(){ return $this->dbh; }
|
170 |
}
|
171 |
|
172 |
?>
|
lib/wfLog.php
CHANGED
@@ -156,15 +156,18 @@ class wfLog {
|
|
156 |
public function unblockIP($IP){
|
157 |
$this->getDB()->query("delete from " . $this->blocksTable . " where IP=%s", wfUtils::inet_aton($IP));
|
158 |
}
|
159 |
-
public function blockIP($IP, $reason, $wfsn = false){
|
160 |
if($this->isWhitelisted($IP)){ return false; }
|
161 |
$wfsn = $wfsn ? 1 : 0;
|
162 |
-
$
|
|
|
163 |
wfUtils::inet_aton($IP),
|
164 |
$reason,
|
165 |
$wfsn,
|
|
|
166 |
$reason,
|
167 |
-
$wfsn
|
|
|
168 |
);
|
169 |
return true;
|
170 |
}
|
@@ -217,7 +220,7 @@ class wfLog {
|
|
217 |
return $results;
|
218 |
}
|
219 |
public function getBlockedIPs(){
|
220 |
-
$res = $this->getDB()->query("select IP, unix_timestamp() - blockedTime as createdAgo, reason, unix_timestamp() - lastAttempt as lastAttemptAgo, lastAttempt, blockedHits, (blockedTime + %s) - unix_timestamp() as blockedFor from " . $this->blocksTable . " where blockedTime + %s > unix_timestamp() order by blockedTime desc", wfConfig::get('blockedTime'), wfConfig::get('blockedTime'));
|
221 |
$results = array();
|
222 |
while($elem = mysql_fetch_assoc($res)){
|
223 |
$lastHitAgo = 0;
|
@@ -468,7 +471,7 @@ class wfLog {
|
|
468 |
}
|
469 |
public function firewallBadIPs(){
|
470 |
$IP = wfUtils::inet_aton(wfUtils::getIP());
|
471 |
-
if($secsToGo = $this->getDB()->querySingle("select (blockedTime + %s) - unix_timestamp() as secsToGo from " . $this->blocksTable . " where IP=%s and blockedTime + %s > unix_timestamp()", wfConfig::get('blockedTime'), $IP, wfConfig::get('blockedTime'))){
|
472 |
$this->getDB()->query("update " . $this->blocksTable . " set lastAttempt=unix_timestamp(), blockedHits = blockedHits + 1 where IP=%s", $IP);
|
473 |
$this->do503($secsToGo);
|
474 |
}
|
@@ -500,10 +503,12 @@ class wfLog {
|
|
500 |
return;
|
501 |
}
|
502 |
}
|
503 |
-
private function do503($secsToGo){
|
504 |
header('HTTP/1.1 503 Service Temporarily Unavailable');
|
505 |
header('Status: 503 Service Temporarily Unavailable');
|
506 |
-
|
|
|
|
|
507 |
require_once('wf503.php');
|
508 |
exit();
|
509 |
}
|
156 |
public function unblockIP($IP){
|
157 |
$this->getDB()->query("delete from " . $this->blocksTable . " where IP=%s", wfUtils::inet_aton($IP));
|
158 |
}
|
159 |
+
public function blockIP($IP, $reason, $wfsn = false, $permanent = false){ //wfsn indicates it comes from Wordfence secure network
|
160 |
if($this->isWhitelisted($IP)){ return false; }
|
161 |
$wfsn = $wfsn ? 1 : 0;
|
162 |
+
$permanent = $permanent ? 1 : 0;
|
163 |
+
$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",
|
164 |
wfUtils::inet_aton($IP),
|
165 |
$reason,
|
166 |
$wfsn,
|
167 |
+
$permanent,
|
168 |
$reason,
|
169 |
+
$wfsn,
|
170 |
+
$permanent
|
171 |
);
|
172 |
return true;
|
173 |
}
|
220 |
return $results;
|
221 |
}
|
222 |
public function getBlockedIPs(){
|
223 |
+
$res = $this->getDB()->query("select IP, unix_timestamp() - blockedTime as createdAgo, reason, unix_timestamp() - lastAttempt as lastAttemptAgo, lastAttempt, blockedHits, (blockedTime + %s) - unix_timestamp() as blockedFor, permanent from " . $this->blocksTable . " where blockedTime + %s > unix_timestamp() order by blockedTime desc", wfConfig::get('blockedTime'), wfConfig::get('blockedTime'));
|
224 |
$results = array();
|
225 |
while($elem = mysql_fetch_assoc($res)){
|
226 |
$lastHitAgo = 0;
|
471 |
}
|
472 |
public function firewallBadIPs(){
|
473 |
$IP = wfUtils::inet_aton(wfUtils::getIP());
|
474 |
+
if($secsToGo = $this->getDB()->querySingle("select (blockedTime + %s) - unix_timestamp() as secsToGo from " . $this->blocksTable . " where IP=%s and (permanent=1 OR blockedTime + %s > unix_timestamp())", wfConfig::get('blockedTime'), $IP, wfConfig::get('blockedTime'))){
|
475 |
$this->getDB()->query("update " . $this->blocksTable . " set lastAttempt=unix_timestamp(), blockedHits = blockedHits + 1 where IP=%s", $IP);
|
476 |
$this->do503($secsToGo);
|
477 |
}
|
503 |
return;
|
504 |
}
|
505 |
}
|
506 |
+
private function do503($secsToGo = false){
|
507 |
header('HTTP/1.1 503 Service Temporarily Unavailable');
|
508 |
header('Status: 503 Service Temporarily Unavailable');
|
509 |
+
if($secsToGo){
|
510 |
+
header('Retry-After: ' . $secsToGo);
|
511 |
+
}
|
512 |
require_once('wf503.php');
|
513 |
exit();
|
514 |
}
|
lib/wfScanEngine.php
CHANGED
@@ -359,10 +359,10 @@ class wfScanEngine {
|
|
359 |
$type = $this->scanData[$idString]['type'];
|
360 |
foreach($hresults as $result){
|
361 |
if($result['badList'] == 'goog-malware-shavar'){
|
362 |
-
$shortMsg = "$uctype contains a suspected malware URL.
|
363 |
$longMsg = "This $type contains a suspected malware URL listed on Google's list of malware sites. 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>.";
|
364 |
} else if($result['badList'] == 'googpub-phish-shavar'){
|
365 |
-
$shortMsg = "$uctype contains a suspected phishing site URL.
|
366 |
$longMsg = "This $type contains a URL that is a suspected phishing site that is currently listed on Google's list of known phishing sites. The URL is: " . $result['URL'];
|
367 |
} else {
|
368 |
//A list type that may be new and the plugin has not been upgraded yet.
|
@@ -456,7 +456,7 @@ class wfScanEngine {
|
|
456 |
$type = $this->scanData[$idString]['type'];
|
457 |
foreach($hresults as $result){
|
458 |
if($result['badList'] == 'goog-malware-shavar'){
|
459 |
-
$shortMsg = "$uctype contains a suspected malware URL.";
|
460 |
$longMsg = "This $type contains a suspected malware URL listed on Google's list of malware sites. 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>.";
|
461 |
} else if($result['badList'] == 'googpub-phish-shavar'){
|
462 |
$shortMsg = "$uctype contains a suspected phishing site URL.";
|
@@ -593,12 +593,12 @@ class wfScanEngine {
|
|
593 |
$level = 1;
|
594 |
$highCap = $this->highestCap($userDat->wp_capabilities);
|
595 |
if($this->isEditor($userDat->wp_capabilities)){
|
596 |
-
$shortMsg = "
|
597 |
$longMsg = "A user with the a role of '" . $highCap . "' has a password that is easy to guess. Please change this password yourself or ask the user to change it.";
|
598 |
$level = 1;
|
599 |
$words = $this->dictWords;
|
600 |
} else {
|
601 |
-
$shortMsg = "
|
602 |
$longMsg = "A user with 'subscriber' access has a password that is very easy to guess. Please either change it or ask the user to change their password.";
|
603 |
$level = 2;
|
604 |
$words = array($userDat->user_login);
|
359 |
$type = $this->scanData[$idString]['type'];
|
360 |
foreach($hresults as $result){
|
361 |
if($result['badList'] == 'goog-malware-shavar'){
|
362 |
+
$shortMsg = "$uctype contains a suspected malware URL: " . $this->scanData[$idString]['title'];
|
363 |
$longMsg = "This $type contains a suspected malware URL listed on Google's list of malware sites. 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>.";
|
364 |
} else if($result['badList'] == 'googpub-phish-shavar'){
|
365 |
+
$shortMsg = "$uctype contains a suspected phishing site URL: " . $this->scanData[$idString]['title'];
|
366 |
$longMsg = "This $type contains a URL that is a suspected phishing site that is currently listed on Google's list of known phishing sites. The URL is: " . $result['URL'];
|
367 |
} else {
|
368 |
//A list type that may be new and the plugin has not been upgraded yet.
|
456 |
$type = $this->scanData[$idString]['type'];
|
457 |
foreach($hresults as $result){
|
458 |
if($result['badList'] == 'goog-malware-shavar'){
|
459 |
+
$shortMsg = "$uctype with author " . $this->scanData[$idString]['author'] . " contains a suspected malware URL.";
|
460 |
$longMsg = "This $type contains a suspected malware URL listed on Google's list of malware sites. 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>.";
|
461 |
} else if($result['badList'] == 'googpub-phish-shavar'){
|
462 |
$shortMsg = "$uctype contains a suspected phishing site URL.";
|
593 |
$level = 1;
|
594 |
$highCap = $this->highestCap($userDat->wp_capabilities);
|
595 |
if($this->isEditor($userDat->wp_capabilities)){
|
596 |
+
$shortMsg = "User \"" . $userDat->user_login . "\" with \"" . $highCap . "\" access has an easy password.";
|
597 |
$longMsg = "A user with the a role of '" . $highCap . "' has a password that is easy to guess. Please change this password yourself or ask the user to change it.";
|
598 |
$level = 1;
|
599 |
$words = $this->dictWords;
|
600 |
} else {
|
601 |
+
$shortMsg = "User \"" . $userDat->user_login . "\" with 'subscriber' access has a very easy password.";
|
602 |
$longMsg = "A user with 'subscriber' access has a password that is very easy to guess. Please either change it or ask the user to change their password.";
|
603 |
$level = 2;
|
604 |
$words = array($userDat->user_login);
|
lib/wfSchema.php
CHANGED
@@ -20,11 +20,12 @@ class wfSchema {
|
|
20 |
lastAttempt int UNSIGNED default 0,
|
21 |
blockedHits int UNSIGNED default 0,
|
22 |
wfsn tinyint UNSIGNED default 0,
|
|
|
23 |
KEY k1(wfsn)
|
24 |
) default charset=utf8",
|
25 |
"wfConfig" => "(
|
26 |
name varchar(100) PRIMARY KEY NOT NULL,
|
27 |
-
val
|
28 |
) default charset=utf8",
|
29 |
"wfCrawlers" => "(
|
30 |
IP INT UNSIGNED NOT NULL,
|
20 |
lastAttempt int UNSIGNED default 0,
|
21 |
blockedHits int UNSIGNED default 0,
|
22 |
wfsn tinyint UNSIGNED default 0,
|
23 |
+
permanent tinyint UNSIGNED default 0,
|
24 |
KEY k1(wfsn)
|
25 |
) default charset=utf8",
|
26 |
"wfConfig" => "(
|
27 |
name varchar(100) PRIMARY KEY NOT NULL,
|
28 |
+
val longblob
|
29 |
) default charset=utf8",
|
30 |
"wfCrawlers" => "(
|
31 |
IP INT UNSIGNED NOT NULL,
|
lib/wfUtils.php
CHANGED
@@ -181,7 +181,7 @@ class wfUtils {
|
|
181 |
return true;
|
182 |
}
|
183 |
} else {
|
184 |
-
if(current_user_can('
|
185 |
return true;
|
186 |
}
|
187 |
}
|
181 |
return true;
|
182 |
}
|
183 |
} else {
|
184 |
+
if(current_user_can('manage_options')){
|
185 |
return true;
|
186 |
}
|
187 |
}
|
lib/wordfenceClass.php
CHANGED
@@ -31,6 +31,9 @@ class wordfence {
|
|
31 |
public static function uninstallPlugin(){
|
32 |
//Used by MU code below
|
33 |
update_option('wordfenceActivated', 0);
|
|
|
|
|
|
|
34 |
}
|
35 |
public static function hourlyCron(){
|
36 |
global $wpdb; $p = $wpdb->base_prefix;
|
@@ -44,38 +47,41 @@ class wordfence {
|
|
44 |
|
45 |
if(wfConfig::get('other_WFNet')){
|
46 |
$wfdb = new wfDB();
|
47 |
-
$q1 = $wfdb->query("select URI from $p"."
|
48 |
$URIs = array();
|
49 |
while($rec = mysql_fetch_assoc($q1)){
|
50 |
array_push($URIs, $rec['URI']);
|
51 |
}
|
52 |
-
$wfdb->query("truncate table $p"."
|
53 |
-
|
|
|
|
|
54 |
|
55 |
$q2 = $wfdb->query("select INET_NTOA(IP) as IP from $p"."wfVulnScanners where ctime > unix_timestamp() - 3600");
|
56 |
-
$wfdb->query("truncate table $p"."wfVulnScanners");
|
57 |
$scanCont = "";
|
58 |
while($rec = mysql_fetch_assoc($q2)){
|
59 |
$scanCont .= pack('N', ip2long($rec['IP']));
|
60 |
}
|
|
|
61 |
|
62 |
$q3 = $wfdb->query("select INET_NTOA(IP) as IP from $p"."wfLockedOut where blockedTime > unix_timestamp() - 3600");
|
63 |
$lockCont = "";
|
64 |
while($rec = mysql_fetch_assoc($q3)){
|
65 |
$lockCont .= pack('N', ip2long($rec['IP']));
|
66 |
}
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
|
|
79 |
}
|
80 |
}
|
81 |
}
|
@@ -86,7 +92,7 @@ class wordfence {
|
|
86 |
global $wpdb; $p = $wpdb->base_prefix;
|
87 |
$wfdb->query("delete from $p"."wfLocs where ctime < unix_timestamp() - %d", WORDFENCE_MAX_IPLOC_AGE);
|
88 |
$wfdb->query("truncate table $p"."wfBadLeechers"); //only uses date that's less than 1 minute old
|
89 |
-
$wfdb->query("delete from $p"."wfBlocks where blockedTime + %s < unix_timestamp()", wfConfig::get('blockedTime'));
|
90 |
$wfdb->query("delete from $p"."wfCrawlers where lastUpdate < unix_timestamp() - (86400 * 7)");
|
91 |
|
92 |
if(wfConfig::get('liveTraf_hitsMaxSize') && wfConfig::get('liveTraf_hitsMaxSize') > 0){
|
@@ -139,7 +145,6 @@ class wordfence {
|
|
139 |
}
|
140 |
public static function runInstall(){
|
141 |
//EVERYTHING HERE MUST BE IDEMPOTENT
|
142 |
-
|
143 |
$schema = new wfSchema();
|
144 |
$schema->createAll(); //if not exists
|
145 |
wfConfig::setDefaults(); //If not set
|
@@ -156,14 +161,10 @@ class wordfence {
|
|
156 |
die("Could not understand the response we received from the Wordfence servers when applying for a free API key.");
|
157 |
}
|
158 |
}
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
}
|
164 |
-
if( !wp_next_scheduled( 'wordfence_hourly_cron' )){
|
165 |
-
wp_schedule_event(time(), 'hourly', 'wordfence_daily_cron');
|
166 |
-
}
|
167 |
$db = new wfDB();
|
168 |
|
169 |
//Upgrading from 1.5.6 or earlier needs:
|
@@ -183,7 +184,8 @@ class wordfence {
|
|
183 |
|
184 |
global $wpdb;
|
185 |
$prefix = $wpdb->base_prefix;
|
186 |
-
$db->
|
|
|
187 |
|
188 |
//Must be the final line
|
189 |
update_option('wordfence_version', WORDFENCE_VERSION);
|
@@ -469,6 +471,7 @@ class wordfence {
|
|
469 |
}
|
470 |
$api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
|
471 |
$contResult = $api->binCall('get_wp_file_content', array(
|
|
|
472 |
'file' => $file,
|
473 |
'cType' => $cType,
|
474 |
'cName' => $cName,
|
@@ -652,6 +655,11 @@ class wordfence {
|
|
652 |
self::getLog()->unblockIP($IP);
|
653 |
return array('ok' => 1);
|
654 |
}
|
|
|
|
|
|
|
|
|
|
|
655 |
public static function ajax_loadStaticPanel_callback(){
|
656 |
$mode = $_POST['mode'];
|
657 |
$wfLog = self::getLog();
|
@@ -667,7 +675,10 @@ class wordfence {
|
|
667 |
return array('ok' => 1, 'results' => $results);
|
668 |
}
|
669 |
public static function ajax_blockIP_callback(){
|
670 |
-
$IP = $_POST['IP'];
|
|
|
|
|
|
|
671 |
if($IP == wfUtils::getIP()){
|
672 |
return array('err' => 1, 'errorMsg' => "You can't block your own IP address.");
|
673 |
}
|
@@ -864,7 +875,7 @@ class wordfence {
|
|
864 |
return array("ok" => 1);
|
865 |
}
|
866 |
} else {
|
867 |
-
return array('errorAlert' => "An unknown error
|
868 |
}
|
869 |
}
|
870 |
public static function ajax_scan_callback(){
|
@@ -984,7 +995,7 @@ class wordfence {
|
|
984 |
exit();
|
985 |
}
|
986 |
public static function wp_head(){
|
987 |
-
echo '<script type="text/javascript">var
|
988 |
}
|
989 |
public static function shutdownAction(){
|
990 |
}
|
@@ -1087,7 +1098,7 @@ class wordfence {
|
|
1087 |
}
|
1088 |
public static function admin_init(){
|
1089 |
if(! wfUtils::isAdmin()){ return; }
|
1090 |
-
foreach(array('activate', 'scan', 'sendActivityLog', 'restoreFile', 'deleteFile', 'removeExclusion', 'activityLogUpdate', 'ticker', 'loadIssues', 'updateIssueStatus', 'deleteIssue', 'updateAllIssues', 'reverseLookup', 'unlockOutIP', 'unblockIP', 'blockIP', 'loadStaticPanel', 'saveConfig', 'clearAllBlocked') as $func){
|
1091 |
add_action('wp_ajax_wordfence_' . $func, 'wordfence::ajaxReceiver');
|
1092 |
}
|
1093 |
|
@@ -1237,7 +1248,7 @@ class wordfence {
|
|
1237 |
public static function scheduleNextScan($force = false){
|
1238 |
if(wfConfig::get('scheduledScansEnabled')){
|
1239 |
$nextScan = wp_next_scheduled('wordfence_scheduled_scan');
|
1240 |
-
if((! $force) && $nextScan && $nextScan -
|
1241 |
//scan is already scheduled for the future
|
1242 |
return;
|
1243 |
}
|
@@ -1251,7 +1262,7 @@ class wordfence {
|
|
1251 |
$secsToGo = $result['secsToGo'];
|
1252 |
}
|
1253 |
wp_clear_scheduled_hook('wordfence_scheduled_scan');
|
1254 |
-
wp_schedule_single_event(
|
1255 |
} else {
|
1256 |
wp_clear_scheduled_hook('wordfence_scheduled_scan');
|
1257 |
}
|
31 |
public static function uninstallPlugin(){
|
32 |
//Used by MU code below
|
33 |
update_option('wordfenceActivated', 0);
|
34 |
+
wp_clear_scheduled_hook('wordfence_daily_cron');
|
35 |
+
wp_clear_scheduled_hook('wordfence_hourly_cron');
|
36 |
+
wp_clear_scheduled_hook('wordfence_scheduled_scan');
|
37 |
}
|
38 |
public static function hourlyCron(){
|
39 |
global $wpdb; $p = $wpdb->base_prefix;
|
47 |
|
48 |
if(wfConfig::get('other_WFNet')){
|
49 |
$wfdb = new wfDB();
|
50 |
+
$q1 = $wfdb->query("select URI from $p"."wfNet404s where ctime > unix_timestamp() - 3600 limit 1000");
|
51 |
$URIs = array();
|
52 |
while($rec = mysql_fetch_assoc($q1)){
|
53 |
array_push($URIs, $rec['URI']);
|
54 |
}
|
55 |
+
$wfdb->query("truncate table $p"."wfNet404s");
|
56 |
+
if(sizeof($URIs) > 0){
|
57 |
+
$api->call('send_net_404s', array(), array( 'URIs' => json_encode($URIs) ));
|
58 |
+
}
|
59 |
|
60 |
$q2 = $wfdb->query("select INET_NTOA(IP) as IP from $p"."wfVulnScanners where ctime > unix_timestamp() - 3600");
|
|
|
61 |
$scanCont = "";
|
62 |
while($rec = mysql_fetch_assoc($q2)){
|
63 |
$scanCont .= pack('N', ip2long($rec['IP']));
|
64 |
}
|
65 |
+
$wfdb->query("truncate table $p"."wfVulnScanners");
|
66 |
|
67 |
$q3 = $wfdb->query("select INET_NTOA(IP) as IP from $p"."wfLockedOut where blockedTime > unix_timestamp() - 3600");
|
68 |
$lockCont = "";
|
69 |
while($rec = mysql_fetch_assoc($q3)){
|
70 |
$lockCont .= pack('N', ip2long($rec['IP']));
|
71 |
}
|
72 |
+
if(strlen($lockCont) > 0 || strlen($scanCont) > 0){
|
73 |
+
$cont = pack('N', strlen($lockCont) / 4) . $lockCont . pack('N', strlen($scanCont) / 4) . $scanCont;
|
74 |
+
$resp = $api->binCall('get_net_bad_ips', $cont);
|
75 |
+
if($resp['code'] == 200){
|
76 |
+
$len = strlen($resp['data']);
|
77 |
+
$reason = "WFSN: Blocked by Wordfence Security Network";
|
78 |
+
$wfdb->query("delete from $p"."wfBlocks where wfsn=1");
|
79 |
+
if($len > 0 && $len % 4 == 0){
|
80 |
+
for($i = 0; $i < $len; $i += 4){
|
81 |
+
list($ipLong) = array_values(unpack('N', substr($resp['data'], $i, 4)));
|
82 |
+
$IPStr = long2ip($ipLong);
|
83 |
+
self::getLog()->blockIP($IPStr, $reason, true);
|
84 |
+
}
|
85 |
}
|
86 |
}
|
87 |
}
|
92 |
global $wpdb; $p = $wpdb->base_prefix;
|
93 |
$wfdb->query("delete from $p"."wfLocs where ctime < unix_timestamp() - %d", WORDFENCE_MAX_IPLOC_AGE);
|
94 |
$wfdb->query("truncate table $p"."wfBadLeechers"); //only uses date that's less than 1 minute old
|
95 |
+
$wfdb->query("delete from $p"."wfBlocks where blockedTime + %s < unix_timestamp() and permanent=0", wfConfig::get('blockedTime'));
|
96 |
$wfdb->query("delete from $p"."wfCrawlers where lastUpdate < unix_timestamp() - (86400 * 7)");
|
97 |
|
98 |
if(wfConfig::get('liveTraf_hitsMaxSize') && wfConfig::get('liveTraf_hitsMaxSize') > 0){
|
145 |
}
|
146 |
public static function runInstall(){
|
147 |
//EVERYTHING HERE MUST BE IDEMPOTENT
|
|
|
148 |
$schema = new wfSchema();
|
149 |
$schema->createAll(); //if not exists
|
150 |
wfConfig::setDefaults(); //If not set
|
161 |
die("Could not understand the response we received from the Wordfence servers when applying for a free API key.");
|
162 |
}
|
163 |
}
|
164 |
+
wp_clear_scheduled_hook('wordfence_daily_cron');
|
165 |
+
wp_clear_scheduled_hook('wordfence_hourly_cron');
|
166 |
+
wp_schedule_event(current_time('timestamp'), 'daily', 'wordfence_daily_cron');
|
167 |
+
wp_schedule_event(current_time('timestamp'), 'hourly', 'wordfence_hourly_cron');
|
|
|
|
|
|
|
|
|
168 |
$db = new wfDB();
|
169 |
|
170 |
//Upgrading from 1.5.6 or earlier needs:
|
184 |
|
185 |
global $wpdb;
|
186 |
$prefix = $wpdb->base_prefix;
|
187 |
+
$db->queryIgnoreError("alter table $prefix"."wfConfig modify column val longblob");
|
188 |
+
$db->queryIgnoreError("alter table $prefix"."wfBlocks add column permanent tinyint UNSIGNED default 0");
|
189 |
|
190 |
//Must be the final line
|
191 |
update_option('wordfence_version', WORDFENCE_VERSION);
|
471 |
}
|
472 |
$api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
|
473 |
$contResult = $api->binCall('get_wp_file_content', array(
|
474 |
+
'v' => wfUtils::getWPVersion(),
|
475 |
'file' => $file,
|
476 |
'cType' => $cType,
|
477 |
'cName' => $cName,
|
655 |
self::getLog()->unblockIP($IP);
|
656 |
return array('ok' => 1);
|
657 |
}
|
658 |
+
public static function ajax_permBlockIP_callback(){
|
659 |
+
$IP = $_POST['IP'];
|
660 |
+
self::getLog()->blockIP($IP, "Manual permanent block by admin", false, true);
|
661 |
+
return array('ok' => 1);
|
662 |
+
}
|
663 |
public static function ajax_loadStaticPanel_callback(){
|
664 |
$mode = $_POST['mode'];
|
665 |
$wfLog = self::getLog();
|
675 |
return array('ok' => 1, 'results' => $results);
|
676 |
}
|
677 |
public static function ajax_blockIP_callback(){
|
678 |
+
$IP = trim($_POST['IP']);
|
679 |
+
if(! preg_match('/^\d+\.\d+\.\d+\.\d+$/', $IP)){
|
680 |
+
return array('err' => 1, 'errorMsg' => "Please enter a valid IP address to block.");
|
681 |
+
}
|
682 |
if($IP == wfUtils::getIP()){
|
683 |
return array('err' => 1, 'errorMsg' => "You can't block your own IP address.");
|
684 |
}
|
875 |
return array("ok" => 1);
|
876 |
}
|
877 |
} else {
|
878 |
+
return array('errorAlert' => "An unknown error occurred trying to activate Wordfence. Please try again in a few minutes." );
|
879 |
}
|
880 |
}
|
881 |
public static function ajax_scan_callback(){
|
995 |
exit();
|
996 |
}
|
997 |
public static function wp_head(){
|
998 |
+
echo '<script type="text/javascript">var src="' . wfUtils::getBaseURL() . 'visitor.php?hid=' . wfUtils::encrypt(self::$hitID) . '"; if(window.location.protocol == "https:"){ src = src.replace("http:", "https:"); } var wfHTImg = new Image(); wfHTImg.src=src;</script>';
|
999 |
}
|
1000 |
public static function shutdownAction(){
|
1001 |
}
|
1098 |
}
|
1099 |
public static function admin_init(){
|
1100 |
if(! wfUtils::isAdmin()){ return; }
|
1101 |
+
foreach(array('activate', 'scan', 'sendActivityLog', 'restoreFile', 'deleteFile', 'removeExclusion', 'activityLogUpdate', 'ticker', 'loadIssues', 'updateIssueStatus', 'deleteIssue', 'updateAllIssues', 'reverseLookup', 'unlockOutIP', 'unblockIP', 'blockIP', 'permBlockIP', 'loadStaticPanel', 'saveConfig', 'clearAllBlocked') as $func){
|
1102 |
add_action('wp_ajax_wordfence_' . $func, 'wordfence::ajaxReceiver');
|
1103 |
}
|
1104 |
|
1248 |
public static function scheduleNextScan($force = false){
|
1249 |
if(wfConfig::get('scheduledScansEnabled')){
|
1250 |
$nextScan = wp_next_scheduled('wordfence_scheduled_scan');
|
1251 |
+
if((! $force) && $nextScan && $nextScan - current_time('timestamp') > 0){
|
1252 |
//scan is already scheduled for the future
|
1253 |
return;
|
1254 |
}
|
1262 |
$secsToGo = $result['secsToGo'];
|
1263 |
}
|
1264 |
wp_clear_scheduled_hook('wordfence_scheduled_scan');
|
1265 |
+
wp_schedule_single_event(current_time('timestamp') + $secsToGo, 'wordfence_scheduled_scan');
|
1266 |
} else {
|
1267 |
wp_clear_scheduled_hook('wordfence_scheduled_scan');
|
1268 |
}
|
lib/wordfenceConstants.php
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
<?php
|
2 |
-
define('WORDFENCE_API_VERSION', 1.
|
3 |
-
define('
|
|
|
4 |
define('WORDFENCE_MAX_SCAN_TIME', 600);
|
5 |
define('WORDFENCE_TRANSIENTS_TIMEOUT', 3600); //how long are items cached in seconds e.g. files downloaded for diffing
|
6 |
define('WORDFENCE_MAX_IPLOC_AGE', 604800); //1 week
|
1 |
<?php
|
2 |
+
define('WORDFENCE_API_VERSION', 1.7);
|
3 |
+
define('WORDFENCE_API_URL_SEC', 'https://noc1.wordfence.com/');
|
4 |
+
define('WORDFENCE_API_URL_NONSEC', 'http://noc1.wordfence.com/');
|
5 |
define('WORDFENCE_MAX_SCAN_TIME', 600);
|
6 |
define('WORDFENCE_TRANSIENTS_TIMEOUT', 3600); //how long are items cached in seconds e.g. files downloaded for diffing
|
7 |
define('WORDFENCE_MAX_IPLOC_AGE', 604800); //1 week
|
lib/wordfenceScanner.php
CHANGED
@@ -139,7 +139,7 @@ class wordfenceScanner {
|
|
139 |
'severity' => 1,
|
140 |
'ignoreP' => $this->path . $file,
|
141 |
'ignoreC' => md5_file($this->path . $file),
|
142 |
-
'shortMsg' => "File contains suspected malware URL.
|
143 |
'longMsg' => "This file contains a suspected malware URL listed on Google's list of malware sites. Wordfence decodes base64 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>.",
|
144 |
'data' => array(
|
145 |
'file' => $file,
|
@@ -155,7 +155,7 @@ class wordfenceScanner {
|
|
155 |
'severity' => 1,
|
156 |
'ignoreP' => $this->path . $file,
|
157 |
'ignoreC' => md5_file($this->path . $file),
|
158 |
-
'shortMsg' => "File contains suspected phishing URL.
|
159 |
'longMsg' => "This file contains a URL that is a suspected phishing site that is currently listed on Google's list of known phishing sites. The URL is: " . $result['URL'],
|
160 |
'data' => array(
|
161 |
'file' => $file,
|
@@ -177,7 +177,7 @@ class wordfenceScanner {
|
|
177 |
'severity' => 1,
|
178 |
'ignoreP' => $ignoreP,
|
179 |
'ignoreC' => $ignoreC,
|
180 |
-
'shortMsg' => "File contains $encoding encoded programming language.
|
181 |
'longMsg' => "This file contains programming language code that has been encoded using $encoding. This is often used by hackers to hide their tracks.",
|
182 |
'data' => array(
|
183 |
'file' => $file,
|
139 |
'severity' => 1,
|
140 |
'ignoreP' => $this->path . $file,
|
141 |
'ignoreC' => md5_file($this->path . $file),
|
142 |
+
'shortMsg' => "File contains suspected malware URL: " . $this->path . $file,
|
143 |
'longMsg' => "This file contains a suspected malware URL listed on Google's list of malware sites. Wordfence decodes base64 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>.",
|
144 |
'data' => array(
|
145 |
'file' => $file,
|
155 |
'severity' => 1,
|
156 |
'ignoreP' => $this->path . $file,
|
157 |
'ignoreC' => md5_file($this->path . $file),
|
158 |
+
'shortMsg' => "File contains suspected phishing URL: " . $this->path . $file,
|
159 |
'longMsg' => "This file contains a URL that is a suspected phishing site that is currently listed on Google's list of known phishing sites. The URL is: " . $result['URL'],
|
160 |
'data' => array(
|
161 |
'file' => $file,
|
177 |
'severity' => 1,
|
178 |
'ignoreP' => $ignoreP,
|
179 |
'ignoreC' => $ignoreC,
|
180 |
+
'shortMsg' => "File contains $encoding encoded programming language: " . $file,
|
181 |
'longMsg' => "This file contains programming language code that has been encoded using $encoding. This is often used by hackers to hide their tracks.",
|
182 |
'data' => array(
|
183 |
'file' => $file,
|
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.3.2
|
6 |
-
Stable tag: 2.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 |
|
@@ -130,7 +130,7 @@ and as long as it does that, it may become face a security vulnerability at some
|
|
130 |
|
131 |
= Will Wordfence protect me against the Timthumb security problem? =
|
132 |
|
133 |
-
The timthumb security exploit
|
134 |
version of timthumb (which the creator of Wordfence wrote and donated to the timthumb author) which closes the security hole that
|
135 |
caused the problem. However we do scan for old version of timthumb for good measure to make sure they don't
|
136 |
cause a security hole on your site.
|
@@ -152,6 +152,24 @@ 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 |
= 2.1.0 =
|
156 |
* Fixed scans hanging on Dreamhost and other hosts.
|
157 |
* Made Wordfence more memory efficient.
|
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.3.2
|
6 |
+
Stable tag: 2.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 |
|
130 |
|
131 |
= Will Wordfence protect me against the Timthumb security problem? =
|
132 |
|
133 |
+
The timthumb security exploit occurred in 2011 and all good plugins and themes now use an updated
|
134 |
version of timthumb (which the creator of Wordfence wrote and donated to the timthumb author) which closes the security hole that
|
135 |
caused the problem. However we do scan for old version of timthumb for good measure to make sure they don't
|
136 |
cause a security hole on your site.
|
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 |
+
= 2.1.1 =
|
156 |
+
* Added ability to permanently block IP's
|
157 |
+
* Added ability to manually block IP's
|
158 |
+
* Made Wordfence more memory efficient, particularly the forking process.
|
159 |
+
* Fixed issue that caused WF to not work on databases with blank passwords.
|
160 |
+
* Wordfence now stops execution of a DB connection error is encountered.
|
161 |
+
* Clear cron jobs if Wordfence is uninstalled.
|
162 |
+
* Enabled hourly cron for Wordfence security network.
|
163 |
+
* Wordfence now works if your server doesn't have openssl installed
|
164 |
+
* Wordfence now works even if you don't have CURL
|
165 |
+
* Fixed visitor logging so it works with HTTPS websites.
|
166 |
+
* Alert emails now contain filenames in each alert description.
|
167 |
+
* Users with weak passwords alerts now contain the username in the email.
|
168 |
+
* Upgraded API to 1.7.
|
169 |
+
* Fixed issue that caused DISALLOW_FILE_MODS to make WF menu disappear.
|
170 |
+
* Modified wfDB to deal with very large queries without exceeding max_allowed_packet
|
171 |
+
* Fixed issue that broke ability to see file changes and repair files.
|
172 |
+
|
173 |
= 2.1.0 =
|
174 |
* Fixed scans hanging on Dreamhost and other hosts.
|
175 |
* Made Wordfence more memory efficient.
|
wfscan.php
CHANGED
@@ -86,11 +86,12 @@ class wfScan {
|
|
86 |
$scan = wfConfig::get_ser('wfsd_engine', false);
|
87 |
if($scan){
|
88 |
//Set false so that we don't get stuck in a loop where we're repeating scan stages.
|
|
|
89 |
wfConfig::set('wfsd_engine', '');
|
90 |
} else {
|
91 |
if($isFork){ //We encountered an error so blank scan and exit
|
92 |
-
wordfence::status(2, 'error', "Scan
|
93 |
-
|
94 |
exit();
|
95 |
} else {
|
96 |
wordfence::statusPrep(); //Re-initializes all status counters
|
86 |
$scan = wfConfig::get_ser('wfsd_engine', false);
|
87 |
if($scan){
|
88 |
//Set false so that we don't get stuck in a loop where we're repeating scan stages.
|
89 |
+
wordfence::status(4, 'info', "Got a true deserialized value back from 'wfsd_engine' with type: " . gettype($scan));
|
90 |
wfConfig::set('wfsd_engine', '');
|
91 |
} else {
|
92 |
if($isFork){ //We encountered an error so blank scan and exit
|
93 |
+
wordfence::status(2, 'error', "Scan can't continue - stored data not found after a fork. Got type: " . gettype($scan));
|
94 |
+
wfConfig::set('wfsd_engine', '');
|
95 |
exit();
|
96 |
} else {
|
97 |
wordfence::statusPrep(); //Re-initializes all status counters
|
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: 2.1.
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
-
define('WORDFENCE_VERSION', '2.1.
|
11 |
|
12 |
require_once('lib/wordfenceConstants.php');
|
13 |
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: 2.1.1
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
+
define('WORDFENCE_VERSION', '2.1.1');
|
11 |
|
12 |
require_once('lib/wordfenceConstants.php');
|
13 |
require_once('lib/wordfenceClass.php');
|