Version Description
- Fixed issue that caused scans to not complete.
- Fixed issue that caused scans to launch a large number of child processes due to very short scan timeout.
- Fixed issue that caused websites that don't know their own hostname to not be able to scan.
- Added workaround for a bug in Better WP Security breaking Wordfence due to their code overwriting the WP version.
- Optimized the way we calculate max execution time for each process while scanning.
Download this release
Release Info
Developer | mmaunder |
Plugin | Wordfence Security – Firewall & Malware Scan |
Version | 3.4.4 |
Comparing to | |
See all releases |
Code changes from version 3.4.1 to 3.4.4
- lib/menu_options.php +1 -1
- lib/wfScanEngine.php +54 -25
- lib/wfUtils.php +4 -6
- lib/wordfenceClass.php +8 -2
- lib/wordfenceHash.php +1 -0
- readme.txt +8 -1
- wordfence.php +2 -2
lib/menu_options.php
CHANGED
@@ -220,7 +220,7 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
|
|
220 |
<tr><th>Check password strength on profile update</th><td><input type="checkbox" id="other_pwStrengthOnUpdate" class="wfConfigElem" name="other_pwStrengthOnUpdate" value="1" <?php $w->cb('other_pwStrengthOnUpdate'); ?> /></td></tr>
|
221 |
<tr><th>Participate in the Wordfence Security Network</th><td><input type="checkbox" id="other_WFNet" class="wfConfigElem" name="other_WFNet" value="1" <?php $w->cb('other_WFNet'); ?> /></td></tr>
|
222 |
<tr><th>Maximum memory Wordfence can use</th><td><input type="text" id="maxMem" name="maxMem" value="<?php $w->f('maxMem'); ?>" size="4" />Megabytes</td></tr>
|
223 |
-
<tr><th>Maximum execution time for each scan stage</th><td><input type="text" id="maxExecutionTime" name="maxExecutionTime" value="<?php $w->f('maxExecutionTime'); ?>" size="4" />Blank for default. Must be greater than
|
224 |
<tr><th>Enable debugging mode (increases database load)</th><td><input type="checkbox" id="debugOn" class="wfConfigElem" name="debugOn" value="1" <?php $w->cb('debugOn'); ?> /></td></tr>
|
225 |
<tr><th>Delete Wordfence tables and data on deactivation?</th><td><input type="checkbox" id="deleteTablesOnDeact" class="wfConfigElem" name="deleteTablesOnDeact" value="1" <?php $w->cb('deleteTablesOnDeact'); ?> /></td></tr>
|
226 |
<tr><th colspan="2"><a href="<?php echo wfUtils::siteURLRelative(); ?>?_wfsf=sysinfo&nonce=<?php echo wp_create_nonce('wp-ajax'); ?>" target="_blank">Click to view your system's configuration in a new window</a></th></tr>
|
220 |
<tr><th>Check password strength on profile update</th><td><input type="checkbox" id="other_pwStrengthOnUpdate" class="wfConfigElem" name="other_pwStrengthOnUpdate" value="1" <?php $w->cb('other_pwStrengthOnUpdate'); ?> /></td></tr>
|
221 |
<tr><th>Participate in the Wordfence Security Network</th><td><input type="checkbox" id="other_WFNet" class="wfConfigElem" name="other_WFNet" value="1" <?php $w->cb('other_WFNet'); ?> /></td></tr>
|
222 |
<tr><th>Maximum memory Wordfence can use</th><td><input type="text" id="maxMem" name="maxMem" value="<?php $w->f('maxMem'); ?>" size="4" />Megabytes</td></tr>
|
223 |
+
<tr><th>Maximum execution time for each scan stage</th><td><input type="text" id="maxExecutionTime" name="maxExecutionTime" value="<?php $w->f('maxExecutionTime'); ?>" size="4" />Blank for default. Must be greater than 9.</td></tr>
|
224 |
<tr><th>Enable debugging mode (increases database load)</th><td><input type="checkbox" id="debugOn" class="wfConfigElem" name="debugOn" value="1" <?php $w->cb('debugOn'); ?> /></td></tr>
|
225 |
<tr><th>Delete Wordfence tables and data on deactivation?</th><td><input type="checkbox" id="deleteTablesOnDeact" class="wfConfigElem" name="deleteTablesOnDeact" value="1" <?php $w->cb('deleteTablesOnDeact'); ?> /></td></tr>
|
226 |
<tr><th colspan="2"><a href="<?php echo wfUtils::siteURLRelative(); ?>?_wfsf=sysinfo&nonce=<?php echo wp_create_nonce('wp-ajax'); ?>" target="_blank">Click to view your system's configuration in a new window</a></th></tr>
|
lib/wfScanEngine.php
CHANGED
@@ -17,7 +17,6 @@ class wfScanEngine {
|
|
17 |
private $hashes = false;
|
18 |
private $jobList = array();
|
19 |
private $i = false;
|
20 |
-
private $wp_version = false;
|
21 |
private $apiKey = false;
|
22 |
private $startTime = 0;
|
23 |
private $scanStep = 0;
|
@@ -41,7 +40,7 @@ class wfScanEngine {
|
|
41 |
}
|
42 |
public function __construct(){
|
43 |
$this->startTime = time();
|
44 |
-
$this->maxExecTime = self::getMaxExecutionTime()
|
45 |
$this->i = new wfIssues();
|
46 |
$this->i->deleteNew();
|
47 |
$this->cycleStartTime = time();
|
@@ -93,7 +92,9 @@ class wfScanEngine {
|
|
93 |
}
|
94 |
}
|
95 |
public function fork(){
|
|
|
96 |
if(wfConfig::set_ser('wfsd_engine', $this, true)){
|
|
|
97 |
self::startScan(true);
|
98 |
} //Otherwise there was an error so don't start another scan.
|
99 |
exit(0);
|
@@ -860,37 +861,65 @@ class wfScanEngine {
|
|
860 |
return "A scan is already running. Use the kill link if you would like to terminate the current scan.";
|
861 |
}
|
862 |
}
|
863 |
-
|
864 |
-
$cronKey = wfUtils::bigRandomHex();
|
865 |
-
wfConfig::set('currentCronKey', time() . ',' . $cronKey);
|
866 |
-
$cronURL = admin_url('admin-ajax.php');
|
867 |
-
$cronURL .= '?action=wordfence_doScan&isFork=' . ($isFork ? '1' : '0') . '&cronKey=' . $cronKey;
|
868 |
-
wordfence::status(4, 'info', "Starting cron at URL $cronURL");
|
869 |
-
$headers = array();
|
870 |
-
wordfence::status(4, 'info', "Starting wp_remote_post");
|
871 |
$timeout = self::getMaxExecutionTime() - 2; //2 seconds shorter than max execution time which ensures that only 2 HTTP processes are ever occupied
|
872 |
-
|
873 |
-
$
|
874 |
-
'timeout' => $timeout,
|
875 |
-
'blocking' => true,
|
876 |
'sslverify' => false,
|
877 |
-
'headers' =>
|
878 |
-
)
|
879 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
880 |
return false; //No error
|
881 |
}
|
882 |
public function processResponse($result){
|
883 |
return false;
|
884 |
}
|
885 |
public static function getMaxExecutionTime(){
|
886 |
-
$
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
894 |
}
|
895 |
}
|
896 |
|
17 |
private $hashes = false;
|
18 |
private $jobList = array();
|
19 |
private $i = false;
|
|
|
20 |
private $apiKey = false;
|
21 |
private $startTime = 0;
|
22 |
private $scanStep = 0;
|
40 |
}
|
41 |
public function __construct(){
|
42 |
$this->startTime = time();
|
43 |
+
$this->maxExecTime = self::getMaxExecutionTime();
|
44 |
$this->i = new wfIssues();
|
45 |
$this->i->deleteNew();
|
46 |
$this->cycleStartTime = time();
|
92 |
}
|
93 |
}
|
94 |
public function fork(){
|
95 |
+
wordfence::status(4, 'info', "Entered fork()");
|
96 |
if(wfConfig::set_ser('wfsd_engine', $this, true)){
|
97 |
+
wordfence::status(4, 'info', "Calling startScan(true)");
|
98 |
self::startScan(true);
|
99 |
} //Otherwise there was an error so don't start another scan.
|
100 |
exit(0);
|
861 |
return "A scan is already running. Use the kill link if you would like to terminate the current scan.";
|
862 |
}
|
863 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
864 |
$timeout = self::getMaxExecutionTime() - 2; //2 seconds shorter than max execution time which ensures that only 2 HTTP processes are ever occupied
|
865 |
+
$testURL = admin_url('admin-ajax.php') . '?action=wordfence_testAjax';
|
866 |
+
$testResult = wp_remote_post($testURL, array(
|
867 |
+
'timeout' => $timeout,
|
868 |
+
'blocking' => true,
|
869 |
'sslverify' => false,
|
870 |
+
'headers' => array()
|
871 |
+
));
|
872 |
+
|
873 |
+
$cronKey = wfUtils::bigRandomHex();
|
874 |
+
wfConfig::set('currentCronKey', time() . ',' . $cronKey);
|
875 |
+
if( (! is_wp_error($testResult)) && is_array($testResult) && strstr($testResult['body'], 'WFSCANTESTOK') !== false){
|
876 |
+
//ajax requests can be sent by the server to itself
|
877 |
+
$cronURL = admin_url('admin-ajax.php');
|
878 |
+
$cronURL .= '?action=wordfence_doScan&isFork=' . ($isFork ? '1' : '0') . '&cronKey=' . $cronKey;
|
879 |
+
$headers = array();
|
880 |
+
wordfence::status(4, 'info', "Starting cron with normal ajax at URL $cronURL");
|
881 |
+
$result = wp_remote_post( $cronURL, array(
|
882 |
+
'timeout' => $timeout, //Must be less than max execution time or more than 2 HTTP children will be occupied by scan
|
883 |
+
'blocking' => true, //Non-blocking seems to block anyway, so we use blocking
|
884 |
+
'sslverify' => false,
|
885 |
+
'headers' => $headers
|
886 |
+
) );
|
887 |
+
wordfence::status(4, 'info', "Scan process ended after forking.");
|
888 |
+
} else {
|
889 |
+
$cronURL = admin_url('admin-ajax.php');
|
890 |
+
$cronURL = preg_replace('/^(https?:\/\/)/i', '$1noc1.wordfence.com/scanp/', $cronURL);
|
891 |
+
$cronURL .= '?action=wordfence_doScan&isFork=' . ($isFork ? '1' : '0') . '&cronKey=' . $cronKey;
|
892 |
+
$headers = array();
|
893 |
+
wordfence::status(4, 'info', "Starting cron via proxy at URL $cronURL");
|
894 |
+
$result = wp_remote_post( $cronURL, array(
|
895 |
+
'timeout' => $timeout, //Must be less than max execution time or more than 2 HTTP children will be occupied by scan
|
896 |
+
'blocking' => true, //Non-blocking seems to block anyway, so we use blocking
|
897 |
+
'sslverify' => false,
|
898 |
+
'headers' => $headers
|
899 |
+
) );
|
900 |
+
wordfence::status(4, 'info', "Scan process ended after forking.");
|
901 |
+
}
|
902 |
return false; //No error
|
903 |
}
|
904 |
public function processResponse($result){
|
905 |
return false;
|
906 |
}
|
907 |
public static function getMaxExecutionTime(){
|
908 |
+
$config = wfConfig::get('maxExecutionTime');
|
909 |
+
wordfence::status(4, 'info', "Got value from wf config maxExecutionTime: $config");
|
910 |
+
if(is_numeric($config) && $config >= 10){
|
911 |
+
wordfence::status(4, 'info', "getMaxExecutionTime() returning config value: $config");
|
912 |
+
return $config;
|
913 |
+
}
|
914 |
+
$ini = @ini_get('max_execution_time');
|
915 |
+
wordfence::status(4, 'info', "Got max_execution_time value from ini: $ini");
|
916 |
+
if(is_numeric($ini) && $ini >= 10){
|
917 |
+
$ini = floor($ini / 2);
|
918 |
+
wordfence::status(4, 'info', "getMaxExecutionTime() returning half ini value: $ini");
|
919 |
+
return $ini;
|
920 |
+
}
|
921 |
+
wordfence::status(4, 'info', "getMaxExecutionTime() returning default of: 15");
|
922 |
+
return 15;
|
923 |
}
|
924 |
}
|
925 |
|
lib/wfUtils.php
CHANGED
@@ -197,11 +197,10 @@ class wfUtils {
|
|
197 |
error_log("Caller for " . $caller['file'] . " line " . $caller['line'] . " is " . $c2['file'] . ' line ' . $c2['line']);
|
198 |
}
|
199 |
public static function getWPVersion(){
|
200 |
-
|
201 |
-
|
202 |
-
if(isset($wordfence_wp_version)){
|
203 |
-
return $wordfence_wp_version;
|
204 |
} else {
|
|
|
205 |
return $wp_version;
|
206 |
}
|
207 |
}
|
@@ -305,7 +304,6 @@ class wfUtils {
|
|
305 |
}
|
306 |
$toResolve = array();
|
307 |
$db = new wfDB();
|
308 |
-
global $wp_version;
|
309 |
global $wpdb;
|
310 |
$locsTable = $wpdb->base_prefix . 'wfLocs';
|
311 |
$IPLocs = array();
|
@@ -332,7 +330,7 @@ class wfUtils {
|
|
332 |
}
|
333 |
}
|
334 |
if(sizeof($toResolve) > 0){
|
335 |
-
$api = new wfAPI(wfConfig::get('apiKey'),
|
336 |
try {
|
337 |
$freshIPs = $api->call('resolve_ips', array(), array(
|
338 |
'ips' => implode(',', $toResolve)
|
197 |
error_log("Caller for " . $caller['file'] . " line " . $caller['line'] . " is " . $c2['file'] . ' line ' . $c2['line']);
|
198 |
}
|
199 |
public static function getWPVersion(){
|
200 |
+
if(wordfence::$wordfence_wp_version){
|
201 |
+
return wordfence::$wordfence_wp_version;
|
|
|
|
|
202 |
} else {
|
203 |
+
global $wp_version;
|
204 |
return $wp_version;
|
205 |
}
|
206 |
}
|
304 |
}
|
305 |
$toResolve = array();
|
306 |
$db = new wfDB();
|
|
|
307 |
global $wpdb;
|
308 |
$locsTable = $wpdb->base_prefix . 'wfLocs';
|
309 |
$IPLocs = array();
|
330 |
}
|
331 |
}
|
332 |
if(sizeof($toResolve) > 0){
|
333 |
+
$api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
|
334 |
try {
|
335 |
$freshIPs = $api->call('resolve_ips', array(), array(
|
336 |
'ips' => implode(',', $toResolve)
|
lib/wordfenceClass.php
CHANGED
@@ -13,6 +13,7 @@ require_once('wfConfig.php');
|
|
13 |
require_once('wfSchema.php');
|
14 |
class wordfence {
|
15 |
public static $printStatus = false;
|
|
|
16 |
protected static $lastURLError = false;
|
17 |
protected static $curlContent = "";
|
18 |
protected static $curlDataWritten = 0;
|
@@ -246,6 +247,8 @@ class wordfence {
|
|
246 |
add_action('wp_ajax_wordfence_logHuman', 'wordfence::ajax_logHuman_callback');
|
247 |
add_action('wp_ajax_nopriv_wordfence_doScan', 'wordfence::ajax_doScan_callback');
|
248 |
add_action('wp_ajax_wordfence_doScan', 'wordfence::ajax_doScan_callback');
|
|
|
|
|
249 |
|
250 |
|
251 |
add_action('wordfence_start_scheduled_scan', 'wordfence::wordfenceStartScheduledScan');
|
@@ -283,11 +286,14 @@ class wordfence {
|
|
283 |
}
|
284 |
}
|
285 |
}
|
|
|
|
|
|
|
286 |
public static function ajax_doScan_callback(){
|
287 |
ignore_user_abort(true);
|
288 |
-
|
289 |
require(ABSPATH . 'wp-includes/version.php');
|
290 |
-
|
291 |
require('wfScan.php');
|
292 |
wfScan::wfScanMain();
|
293 |
|
13 |
require_once('wfSchema.php');
|
14 |
class wordfence {
|
15 |
public static $printStatus = false;
|
16 |
+
public static $wordfence_wp_version = false;
|
17 |
protected static $lastURLError = false;
|
18 |
protected static $curlContent = "";
|
19 |
protected static $curlDataWritten = 0;
|
247 |
add_action('wp_ajax_wordfence_logHuman', 'wordfence::ajax_logHuman_callback');
|
248 |
add_action('wp_ajax_nopriv_wordfence_doScan', 'wordfence::ajax_doScan_callback');
|
249 |
add_action('wp_ajax_wordfence_doScan', 'wordfence::ajax_doScan_callback');
|
250 |
+
add_action('wp_ajax_nopriv_wordfence_testAjax', 'wordfence::ajax_testAjax_callback');
|
251 |
+
add_action('wp_ajax_wordfence_testAjax', 'wordfence::ajax_testAjax_callback');
|
252 |
|
253 |
|
254 |
add_action('wordfence_start_scheduled_scan', 'wordfence::wordfenceStartScheduledScan');
|
286 |
}
|
287 |
}
|
288 |
}
|
289 |
+
public static function ajax_testAjax_callback(){
|
290 |
+
die("WFSCANTESTOK");
|
291 |
+
}
|
292 |
public static function ajax_doScan_callback(){
|
293 |
ignore_user_abort(true);
|
294 |
+
self::$wordfence_wp_version = false;
|
295 |
require(ABSPATH . 'wp-includes/version.php');
|
296 |
+
self::$wordfence_wp_version = $wp_version;
|
297 |
require('wfScan.php');
|
298 |
wfScan::wfScanMain();
|
299 |
|
lib/wordfenceHash.php
CHANGED
@@ -192,6 +192,7 @@ class wordfenceHash {
|
|
192 |
$file = substr($realFile, $this->striplen);
|
193 |
if( (! $this->stoppedOnFile) && microtime(true) - $this->startTime > $this->engine->maxExecTime){ //max X seconds but don't allow fork if we're looking for the file we stopped on. Search mode is VERY fast.
|
194 |
$this->stoppedOnFile = $file;
|
|
|
195 |
$this->engine->fork();
|
196 |
//exits
|
197 |
}
|
192 |
$file = substr($realFile, $this->striplen);
|
193 |
if( (! $this->stoppedOnFile) && microtime(true) - $this->startTime > $this->engine->maxExecTime){ //max X seconds but don't allow fork if we're looking for the file we stopped on. Search mode is VERY fast.
|
194 |
$this->stoppedOnFile = $file;
|
195 |
+
wordfence::status(4, 'info', "Calling fork() from wordfenceHash::processFile with maxExecTime: " . $this->engine->maxExecTime);
|
196 |
$this->engine->fork();
|
197 |
//exits
|
198 |
}
|
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.4.
|
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 |
|
@@ -154,6 +154,13 @@ or a theme, because often these have been updated to fix a security hole.
|
|
154 |
|
155 |
== Changelog ==
|
156 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
= 3.4.1 =
|
158 |
* Removed wfscan.php script and now using pseudo-ajax calls to fire off scans. Much more reliable.
|
159 |
* Removed visitor.php script and now using pseudo-ajax calls to log human visits.
|
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.4.4
|
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 |
|
154 |
|
155 |
== Changelog ==
|
156 |
|
157 |
+
= 3.4.4 =
|
158 |
+
* Fixed issue that caused scans to not complete.
|
159 |
+
* Fixed issue that caused scans to launch a large number of child processes due to very short scan timeout.
|
160 |
+
* Fixed issue that caused websites that don't know their own hostname to not be able to scan.
|
161 |
+
* Added workaround for a bug in Better WP Security breaking Wordfence due to their code overwriting the WP version.
|
162 |
+
* Optimized the way we calculate max execution time for each process while scanning.
|
163 |
+
|
164 |
= 3.4.1 =
|
165 |
* Removed wfscan.php script and now using pseudo-ajax calls to fire off scans. Much more reliable.
|
166 |
* Removed visitor.php script and now using pseudo-ajax calls to log human visits.
|
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.4.
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
-
define('WORDFENCE_VERSION', '3.4.
|
11 |
if(get_option('wordfenceActivated') != 1){
|
12 |
add_action('activated_plugin','wordfence_save_activation_error'); function wordfence_save_activation_error(){ update_option('wf_plugin_act_error', ob_get_contents()); }
|
13 |
}
|
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.4.4
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
+
define('WORDFENCE_VERSION', '3.4.4');
|
11 |
if(get_option('wordfenceActivated') != 1){
|
12 |
add_action('activated_plugin','wordfence_save_activation_error'); function wordfence_save_activation_error(){ update_option('wf_plugin_act_error', ob_get_contents()); }
|
13 |
}
|