Version Description
- Fixed bug that caused malformed URLs to be sent to scanning server which caused errors on some installations.
- Fixed issue that caused scans to "hang" or stall on larger sites during "Analyzing" phase when we hash files. Sites of arbitrary size can now be scanned.
- Fixed issue that caused "plugin generated X characters of unexpected output" error during install or upgrade.
Download this release
Release Info
Developer | mmaunder |
Plugin | Wordfence Security – Firewall & Malware Scan |
Version | 3.3.4 |
Comparing to | |
See all releases |
Code changes from version 3.3.3 to 3.3.4
- lib/wfAPI.php +9 -2
- lib/wfScanEngine.php +24 -16
- lib/wordfenceClass.php +4 -2
- lib/wordfenceHash.php +57 -20
- readme.txt +6 -1
- wordfence.php +2 -2
lib/wfAPI.php
CHANGED
@@ -17,7 +17,7 @@ class wfAPI {
|
|
17 |
return $this->getURL($this->getAPIURL() . $url);
|
18 |
}
|
19 |
public function call($action, $getParams = array(), $postParams = array()){
|
20 |
-
$json = $this->getURL($this->getAPIURL() . '/v' . WORDFENCE_API_VERSION . '/?' . $this->makeAPIQueryString() . '&' .
|
21 |
array_merge(
|
22 |
array('action' => $action),
|
23 |
$getParams
|
@@ -157,12 +157,19 @@ class wfAPI {
|
|
157 |
if(function_exists('get_bloginfo')){
|
158 |
$siteurl = get_bloginfo('siteurl');
|
159 |
}
|
160 |
-
return
|
161 |
'v' => $this->wordpressVersion,
|
162 |
's' => $siteurl,
|
163 |
'k' => $this->APIKey
|
164 |
));
|
165 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
private function getAPIURL(){
|
167 |
$ssl_supported = false;
|
168 |
if(defined('CURL_VERSION_SSL') && function_exists('curl_version')){
|
17 |
return $this->getURL($this->getAPIURL() . $url);
|
18 |
}
|
19 |
public function call($action, $getParams = array(), $postParams = array()){
|
20 |
+
$json = $this->getURL($this->getAPIURL() . '/v' . WORDFENCE_API_VERSION . '/?' . $this->makeAPIQueryString() . '&' . self::buildQuery(
|
21 |
array_merge(
|
22 |
array('action' => $action),
|
23 |
$getParams
|
157 |
if(function_exists('get_bloginfo')){
|
158 |
$siteurl = get_bloginfo('siteurl');
|
159 |
}
|
160 |
+
return self::buildQuery(array(
|
161 |
'v' => $this->wordpressVersion,
|
162 |
's' => $siteurl,
|
163 |
'k' => $this->APIKey
|
164 |
));
|
165 |
}
|
166 |
+
private function buildQuery($data){
|
167 |
+
if(version_compare(phpversion(), '5.1.2', '>=')){
|
168 |
+
return http_build_query($data, '', '&'); //arg_separator parameter was only added in PHP 5.1.2. We do this because some PHP.ini's have arg_separator.output set to '&'
|
169 |
+
} else {
|
170 |
+
return http_build_query($data);
|
171 |
+
}
|
172 |
+
}
|
173 |
private function getAPIURL(){
|
174 |
$ssl_supported = false;
|
175 |
if(defined('CURL_VERSION_SSL') && function_exists('curl_version')){
|
lib/wfScanEngine.php
CHANGED
@@ -21,7 +21,7 @@ class wfScanEngine {
|
|
21 |
private $apiKey = false;
|
22 |
private $startTime = 0;
|
23 |
private $scanStep = 0;
|
24 |
-
|
25 |
private $publicScanEnabled = false;
|
26 |
private $fileContentsResults = false;
|
27 |
private $scanner = false;
|
@@ -50,8 +50,10 @@ class wfScanEngine {
|
|
50 |
include('wfDict.php'); //$dictWords
|
51 |
$this->dictWords = $dictWords;
|
52 |
$this->jobList[] = 'publicSite';
|
53 |
-
$this->jobList[] = '
|
54 |
-
|
|
|
|
|
55 |
if(wfConfig::get('scansEnabled_' . $scanType)){
|
56 |
if(method_exists($this, 'scan_' . $scanType . '_init')){
|
57 |
foreach(array('init', 'main', 'finish') as $op){ $this->jobList[] = $scanType . '_' . $op; };
|
@@ -148,10 +150,9 @@ class wfScanEngine {
|
|
148 |
sleep(2); //enough time to read the message before it scrolls off.
|
149 |
}
|
150 |
}
|
151 |
-
private function
|
152 |
$this->status(1, 'info', "Contacting Wordfence to initiate scan");
|
153 |
$this->api->call('log_scan', array(), array());
|
154 |
-
$this->hasher = new wordfenceHash(strlen(ABSPATH));
|
155 |
$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');
|
156 |
$baseContents = scandir(ABSPATH);
|
157 |
if(! is_array($baseContents)){
|
@@ -161,12 +162,13 @@ class wfScanEngine {
|
|
161 |
if($scanOutside){
|
162 |
wordfence::status(2, 'info', "Including files that are outside the WordPress installation in the scan.");
|
163 |
}
|
|
|
164 |
foreach($baseContents as $file){ //Only include base files less than a meg that are files.
|
165 |
$fullFile = rtrim(ABSPATH, '/') . '/' . $file;
|
166 |
if($scanOutside){
|
167 |
-
$
|
168 |
} else if(in_array($file, $baseWPStuff) || (@is_file($fullFile) && @is_readable($fullFile) && (! wfUtils::fileTooBig($fullFile)) ) ){
|
169 |
-
$
|
170 |
}
|
171 |
}
|
172 |
|
@@ -175,12 +177,12 @@ class wfScanEngine {
|
|
175 |
}
|
176 |
$this->status(2, 'info', "Getting plugin list from WordPress");
|
177 |
$pluginData = get_plugins();
|
178 |
-
$
|
179 |
foreach($pluginData as $key => $data){
|
180 |
if(preg_match('/^([^\/]+)\//', $key, $matches)){
|
181 |
$pluginDir = $matches[1];
|
182 |
$pluginFullDir = "wp-content/plugins/" . $pluginDir;
|
183 |
-
$
|
184 |
'Name' => $data['Name'],
|
185 |
'Version' => $data['Version'],
|
186 |
'ShortDir' => $pluginDir,
|
@@ -189,20 +191,20 @@ class wfScanEngine {
|
|
189 |
}
|
190 |
}
|
191 |
|
192 |
-
$this->status(2, 'info', "Found " . sizeof($
|
193 |
-
$this->i->updateSummaryItem('totalPlugins', sizeof($
|
194 |
|
195 |
if(! function_exists( 'get_themes')){
|
196 |
require_once ABSPATH . '/wp-includes/theme.php';
|
197 |
}
|
198 |
$this->status(2, 'info', "Getting theme list from WordPress");
|
199 |
$themeData = get_themes();
|
200 |
-
$
|
201 |
foreach($themeData as $themeName => $themeData){
|
202 |
if(preg_match('/\/([^\/]+)$/', $themeData['Stylesheet Dir'], $matches)){
|
203 |
$shortDir = $matches[1]; //e.g. evo4cms
|
204 |
$fullDir = substr($themeData['Stylesheet Dir'], strlen(ABSPATH)); //e.g. wp-content/themes/evo4cms
|
205 |
-
$
|
206 |
'Name' => $themeData['Name'],
|
207 |
'Version' => $themeData['Version'],
|
208 |
'ShortDir' => $shortDir,
|
@@ -210,15 +212,21 @@ class wfScanEngine {
|
|
210 |
);
|
211 |
}
|
212 |
}
|
213 |
-
$this->status(2, 'info', "Found " . sizeof($
|
214 |
-
$this->i->updateSummaryItem('totalThemes', sizeof($
|
215 |
|
216 |
-
$this->hasher
|
|
|
|
|
|
|
217 |
$this->i->updateSummaryItem('totalData', wfUtils::formatBytes($this->hasher->totalData));
|
218 |
$this->i->updateSummaryItem('totalFiles', $this->hasher->totalFiles);
|
219 |
$this->i->updateSummaryItem('totalDirs', $this->hasher->totalDirs);
|
220 |
$this->i->updateSummaryItem('linesOfPHP', $this->hasher->linesOfPHP);
|
221 |
$this->i->updateSummaryItem('linesOfJCH', $this->hasher->linesOfJCH);
|
|
|
|
|
|
|
222 |
}
|
223 |
private function scan_fileContents_init(){
|
224 |
$this->statusIDX['infect'] = wordfence::statusStart('Scanning file contents for infections and vulnerabilities');
|
21 |
private $apiKey = false;
|
22 |
private $startTime = 0;
|
23 |
private $scanStep = 0;
|
24 |
+
public $maxExecTime = 10; //If more than $maxExecTime has elapsed since last check, fork a new scan process and continue
|
25 |
private $publicScanEnabled = false;
|
26 |
private $fileContentsResults = false;
|
27 |
private $scanner = false;
|
50 |
include('wfDict.php'); //$dictWords
|
51 |
$this->dictWords = $dictWords;
|
52 |
$this->jobList[] = 'publicSite';
|
53 |
+
$this->jobList[] = 'knownFiles_init';
|
54 |
+
$this->jobList[] = 'knownFiles_main';
|
55 |
+
$this->jobList[] = 'knownFiles_finish';
|
56 |
+
foreach(array('knownFiles', 'fileContents', 'posts', 'comments', 'passwds', 'dns', 'diskSpace', 'oldVersions') as $scanType){
|
57 |
if(wfConfig::get('scansEnabled_' . $scanType)){
|
58 |
if(method_exists($this, 'scan_' . $scanType . '_init')){
|
59 |
foreach(array('init', 'main', 'finish') as $op){ $this->jobList[] = $scanType . '_' . $op; };
|
150 |
sleep(2); //enough time to read the message before it scrolls off.
|
151 |
}
|
152 |
}
|
153 |
+
private function scan_knownFiles_init(){
|
154 |
$this->status(1, 'info', "Contacting Wordfence to initiate scan");
|
155 |
$this->api->call('log_scan', array(), array());
|
|
|
156 |
$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');
|
157 |
$baseContents = scandir(ABSPATH);
|
158 |
if(! is_array($baseContents)){
|
162 |
if($scanOutside){
|
163 |
wordfence::status(2, 'info', "Including files that are outside the WordPress installation in the scan.");
|
164 |
}
|
165 |
+
$includeInKnownFilesScan = array();
|
166 |
foreach($baseContents as $file){ //Only include base files less than a meg that are files.
|
167 |
$fullFile = rtrim(ABSPATH, '/') . '/' . $file;
|
168 |
if($scanOutside){
|
169 |
+
$includeInKnownFilesScan[] = $file;
|
170 |
} else if(in_array($file, $baseWPStuff) || (@is_file($fullFile) && @is_readable($fullFile) && (! wfUtils::fileTooBig($fullFile)) ) ){
|
171 |
+
$includeInKnownFilesScan[] = $file;
|
172 |
}
|
173 |
}
|
174 |
|
177 |
}
|
178 |
$this->status(2, 'info', "Getting plugin list from WordPress");
|
179 |
$pluginData = get_plugins();
|
180 |
+
$knownFilesPlugins = array();
|
181 |
foreach($pluginData as $key => $data){
|
182 |
if(preg_match('/^([^\/]+)\//', $key, $matches)){
|
183 |
$pluginDir = $matches[1];
|
184 |
$pluginFullDir = "wp-content/plugins/" . $pluginDir;
|
185 |
+
$knownFilesPlugins[$key] = array(
|
186 |
'Name' => $data['Name'],
|
187 |
'Version' => $data['Version'],
|
188 |
'ShortDir' => $pluginDir,
|
191 |
}
|
192 |
}
|
193 |
|
194 |
+
$this->status(2, 'info', "Found " . sizeof($knownFilesPlugins) . " plugins");
|
195 |
+
$this->i->updateSummaryItem('totalPlugins', sizeof($knownFilesPlugins));
|
196 |
|
197 |
if(! function_exists( 'get_themes')){
|
198 |
require_once ABSPATH . '/wp-includes/theme.php';
|
199 |
}
|
200 |
$this->status(2, 'info', "Getting theme list from WordPress");
|
201 |
$themeData = get_themes();
|
202 |
+
$knownFilesThemes = array();
|
203 |
foreach($themeData as $themeName => $themeData){
|
204 |
if(preg_match('/\/([^\/]+)$/', $themeData['Stylesheet Dir'], $matches)){
|
205 |
$shortDir = $matches[1]; //e.g. evo4cms
|
206 |
$fullDir = substr($themeData['Stylesheet Dir'], strlen(ABSPATH)); //e.g. wp-content/themes/evo4cms
|
207 |
+
$knownFilesThemes[$themeName] = array(
|
208 |
'Name' => $themeData['Name'],
|
209 |
'Version' => $themeData['Version'],
|
210 |
'ShortDir' => $shortDir,
|
212 |
);
|
213 |
}
|
214 |
}
|
215 |
+
$this->status(2, 'info', "Found " . sizeof($knownFilesThemes) . " themes");
|
216 |
+
$this->i->updateSummaryItem('totalThemes', sizeof($knownFilesThemes));
|
217 |
|
218 |
+
$this->hasher = new wordfenceHash(strlen(ABSPATH), ABSPATH, $includeInKnownFilesScan, $knownFilesThemes, $knownFilesPlugins, $this);
|
219 |
+
}
|
220 |
+
private function scan_knownFiles_main(){
|
221 |
+
$this->hasher->run($this); //Include this so we can call addIssue and ->api->
|
222 |
$this->i->updateSummaryItem('totalData', wfUtils::formatBytes($this->hasher->totalData));
|
223 |
$this->i->updateSummaryItem('totalFiles', $this->hasher->totalFiles);
|
224 |
$this->i->updateSummaryItem('totalDirs', $this->hasher->totalDirs);
|
225 |
$this->i->updateSummaryItem('linesOfPHP', $this->hasher->linesOfPHP);
|
226 |
$this->i->updateSummaryItem('linesOfJCH', $this->hasher->linesOfJCH);
|
227 |
+
$this->hasher = false;
|
228 |
+
}
|
229 |
+
private function scan_knownFiles_finish(){
|
230 |
}
|
231 |
private function scan_fileContents_init(){
|
232 |
$this->statusIDX['infect'] = wordfence::statusStart('Scanning file contents for infections and vulnerabilities');
|
lib/wordfenceClass.php
CHANGED
@@ -639,8 +639,10 @@ class wordfence {
|
|
639 |
wp_clear_scheduled_hook('wordfence_start_scheduled_scan'); //Unschedule legacy scans without args
|
640 |
|
641 |
$schedArgs = wfConfig::get_ser('schedScanArgs', array());
|
642 |
-
|
643 |
-
|
|
|
|
|
644 |
}
|
645 |
wfConfig::set_ser('schedScanArgs', array());
|
646 |
}
|
639 |
wp_clear_scheduled_hook('wordfence_start_scheduled_scan'); //Unschedule legacy scans without args
|
640 |
|
641 |
$schedArgs = wfConfig::get_ser('schedScanArgs', array());
|
642 |
+
if(is_array($schedArgs)){
|
643 |
+
foreach($schedArgs as $futureTime){
|
644 |
+
wp_clear_scheduled_hook('wordfence_start_scheduled_scan', array($futureTime));
|
645 |
+
}
|
646 |
}
|
647 |
wfConfig::set_ser('schedScanArgs', array());
|
648 |
}
|
lib/wordfenceHash.php
CHANGED
@@ -1,29 +1,39 @@
|
|
1 |
<?php
|
2 |
require_once('wordfenceClass.php');
|
3 |
class wordfenceHash {
|
4 |
-
//Begin serialized vars
|
5 |
private $whitespace = array("\n","\r","\t"," ");
|
6 |
-
|
|
|
|
|
|
|
|
|
|
|
7 |
public $totalFiles = 0;
|
8 |
public $totalDirs = 0;
|
|
|
9 |
public $linesOfPHP = 0;
|
10 |
public $linesOfJCH = 0; //lines of HTML, CSS and javascript
|
11 |
-
public $
|
12 |
-
private $engine = false;
|
13 |
-
private $db = false;
|
14 |
private $coreEnabled = false;
|
15 |
-
private $themesEnabled = false;
|
16 |
private $pluginsEnabled = false;
|
|
|
17 |
private $malwareEnabled = false;
|
|
|
18 |
private $malwareData = "";
|
19 |
-
private $possibleMalware = array();
|
20 |
-
private $status = array();
|
21 |
private $haveIssues = array();
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
$this->striplen = $striplen;
|
24 |
-
|
25 |
-
|
26 |
-
|
|
|
|
|
27 |
if(wfConfig::get('scansEnabled_core')){
|
28 |
$this->coreEnabled = true;
|
29 |
}
|
@@ -39,7 +49,7 @@ class wordfenceHash {
|
|
39 |
$this->db = new wfDB();
|
40 |
|
41 |
//Doing a delete for now. Later we can optimize this to only scan modified files.
|
42 |
-
//$this->db->query("update " . $this->db->prefix() . "wfFileMods set oldMD5 = newMD5");
|
43 |
$this->db->query("delete from " . $this->db->prefix() . "wfFileMods");
|
44 |
$fetchCoreHashesStatus = wordfence::statusStart("Fetching core, theme and plugin file signatures from Wordfence");
|
45 |
$dataArr = $engine->api->binCall('get_known_files', json_encode(array(
|
@@ -75,14 +85,13 @@ class wordfenceHash {
|
|
75 |
wordfence::statusEnd($malwarePrefixStatus, false, true);
|
76 |
}
|
77 |
|
78 |
-
if($path[strlen($path) - 1] != '/'){
|
79 |
-
$path .= '/';
|
80 |
}
|
81 |
if(! is_readable($path)){
|
82 |
-
throw new Exception("Could not read directory $path to do scan.");
|
83 |
exit();
|
84 |
}
|
85 |
-
$files = scandir($path);
|
86 |
$this->haveIssues = array(
|
87 |
'core' => false,
|
88 |
'themes' => false,
|
@@ -93,11 +102,26 @@ class wordfenceHash {
|
|
93 |
if($this->themesEnabled){ $this->status['themes'] = wordfence::statusStart("Comparing open source themes against WordPress.org originals"); } else { wordfence::statusDisabled("Skipping theme scan"); }
|
94 |
if($this->pluginsEnabled){ $this->status['plugins'] = wordfence::statusStart("Comparing plugins against WordPress.org originals"); } else { wordfence::statusDisabled("Skipping plugin scan"); }
|
95 |
if($this->malwareEnabled){ $this->status['malware'] = wordfence::statusStart("Scanning for known malware files"); } else { wordfence::statusDisabled("Skipping malware scan"); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
foreach($files as $file){
|
97 |
-
if(sizeof($only) > 0 && (! in_array($file, $only))){
|
98 |
continue;
|
99 |
}
|
100 |
-
$file = $path . $file;
|
101 |
wordfence::status(4, 'info', "Hashing item in base dir: $file");
|
102 |
$this->_dirHash($file);
|
103 |
}
|
@@ -121,7 +145,7 @@ class wordfenceHash {
|
|
121 |
$this->engine->addIssue(
|
122 |
'file',
|
123 |
1,
|
124 |
-
$path . $file,
|
125 |
$md5,
|
126 |
'This file is suspected malware: ' . $file,
|
127 |
"This file's signature matches a known malware file. The title of the malware is '" . $name . "'. Immediately inspect this file using the 'View' option below and consider deleting it from your server.",
|
@@ -166,6 +190,19 @@ class wordfenceHash {
|
|
166 |
}
|
167 |
private function processFile($realFile){
|
168 |
$file = substr($realFile, $this->striplen);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
if(wfUtils::fileTooBig($realFile)){
|
170 |
wordfence::status(4, 'info', "Skipping file larger than max size: $realFile");
|
171 |
return;
|
1 |
<?php
|
2 |
require_once('wordfenceClass.php');
|
3 |
class wordfenceHash {
|
|
|
4 |
private $whitespace = array("\n","\r","\t"," ");
|
5 |
+
private $engine = false;
|
6 |
+
private $db = false;
|
7 |
+
private $startTime = false;
|
8 |
+
|
9 |
+
//Begin serialized vars
|
10 |
+
public $striplen = 0;
|
11 |
public $totalFiles = 0;
|
12 |
public $totalDirs = 0;
|
13 |
+
public $totalData = 0; //To do a sanity check, don't use 'du' because it gets sparse files wrong and reports blocks used on disk. Use : find . -type f -ls | awk '{total += $7} END {print total}'
|
14 |
public $linesOfPHP = 0;
|
15 |
public $linesOfJCH = 0; //lines of HTML, CSS and javascript
|
16 |
+
public $stoppedOnFile = false;
|
|
|
|
|
17 |
private $coreEnabled = false;
|
|
|
18 |
private $pluginsEnabled = false;
|
19 |
+
private $themesEnabled = false;
|
20 |
private $malwareEnabled = false;
|
21 |
+
private $knownFiles = false;
|
22 |
private $malwareData = "";
|
|
|
|
|
23 |
private $haveIssues = array();
|
24 |
+
private $status = array();
|
25 |
+
private $possibleMalware = array();
|
26 |
+
private $path = false;
|
27 |
+
private $only = false;
|
28 |
+
private $totalForks = 0;
|
29 |
+
|
30 |
+
public function __construct($striplen, $path, $only, $themes, $plugins, $engine){
|
31 |
$this->striplen = $striplen;
|
32 |
+
$this->path = $path;
|
33 |
+
$this->only = $only;
|
34 |
+
|
35 |
+
$this->startTime = microtime(true);
|
36 |
+
|
37 |
if(wfConfig::get('scansEnabled_core')){
|
38 |
$this->coreEnabled = true;
|
39 |
}
|
49 |
$this->db = new wfDB();
|
50 |
|
51 |
//Doing a delete for now. Later we can optimize this to only scan modified files.
|
52 |
+
//$this->db->query("update " . $this->db->prefix() . "wfFileMods set oldMD5 = newMD5");
|
53 |
$this->db->query("delete from " . $this->db->prefix() . "wfFileMods");
|
54 |
$fetchCoreHashesStatus = wordfence::statusStart("Fetching core, theme and plugin file signatures from Wordfence");
|
55 |
$dataArr = $engine->api->binCall('get_known_files', json_encode(array(
|
85 |
wordfence::statusEnd($malwarePrefixStatus, false, true);
|
86 |
}
|
87 |
|
88 |
+
if($this->path[strlen($this->path) - 1] != '/'){
|
89 |
+
$this->path .= '/';
|
90 |
}
|
91 |
if(! is_readable($path)){
|
92 |
+
throw new Exception("Could not read directory " . $this->path . " to do scan.");
|
93 |
exit();
|
94 |
}
|
|
|
95 |
$this->haveIssues = array(
|
96 |
'core' => false,
|
97 |
'themes' => false,
|
102 |
if($this->themesEnabled){ $this->status['themes'] = wordfence::statusStart("Comparing open source themes against WordPress.org originals"); } else { wordfence::statusDisabled("Skipping theme scan"); }
|
103 |
if($this->pluginsEnabled){ $this->status['plugins'] = wordfence::statusStart("Comparing plugins against WordPress.org originals"); } else { wordfence::statusDisabled("Skipping plugin scan"); }
|
104 |
if($this->malwareEnabled){ $this->status['malware'] = wordfence::statusStart("Scanning for known malware files"); } else { wordfence::statusDisabled("Skipping malware scan"); }
|
105 |
+
}
|
106 |
+
public function __sleep(){
|
107 |
+
return array('striplen', 'totalFiles', 'totalDirs', 'totalData', 'linesOfPHP', 'linesOfJCH', 'stoppedOnFile', 'coreEnabled', 'pluginsEnabled', 'themesEnabled', 'malwareEnabled', 'knownFiles', 'malwareData', 'haveIssues', 'status', 'possibleMalware', 'path', 'only', 'totalForks');
|
108 |
+
}
|
109 |
+
public function __wakeup(){
|
110 |
+
$this->db = new wfDB();
|
111 |
+
$this->startTime = microtime(true);
|
112 |
+
$this->totalForks++;
|
113 |
+
}
|
114 |
+
public function run($engine){ //base path and 'only' is a list of files and dirs in the bast that are the only ones that should be processed. Everything else in base is ignored. If only is empty then everything is processed.
|
115 |
+
if($this->totalForks > 1000){
|
116 |
+
throw new Exception("Wordfence file scanner detected a possible infinite loop. Exiting on file: " . $this->stoppedOnFile);
|
117 |
+
}
|
118 |
+
$this->engine = $engine;
|
119 |
+
$files = scandir($this->path);
|
120 |
foreach($files as $file){
|
121 |
+
if(sizeof($this->only) > 0 && (! in_array($file, $this->only))){
|
122 |
continue;
|
123 |
}
|
124 |
+
$file = $this->path . $file;
|
125 |
wordfence::status(4, 'info', "Hashing item in base dir: $file");
|
126 |
$this->_dirHash($file);
|
127 |
}
|
145 |
$this->engine->addIssue(
|
146 |
'file',
|
147 |
1,
|
148 |
+
$this->path . $file,
|
149 |
$md5,
|
150 |
'This file is suspected malware: ' . $file,
|
151 |
"This file's signature matches a known malware file. The title of the malware is '" . $name . "'. Immediately inspect this file using the 'View' option below and consider deleting it from your server.",
|
190 |
}
|
191 |
private function processFile($realFile){
|
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 |
+
}
|
198 |
+
|
199 |
+
//Put this after the fork, that way we will at least scan one more file after we fork if it takes us more than 10 seconds to search for the stoppedOnFile
|
200 |
+
if($this->stoppedOnFile && $file != $this->stoppedOnFile){
|
201 |
+
return;
|
202 |
+
} else if($this->stoppedOnFile && $file == $this->stoppedOnFile){
|
203 |
+
$this->stoppedOnFile = false; //Continue scanning
|
204 |
+
}
|
205 |
+
|
206 |
if(wfUtils::fileTooBig($realFile)){
|
207 |
wordfence::status(4, 'info', "Skipping file larger than max size: $realFile");
|
208 |
return;
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
|
|
3 |
Tags: wordpress, security, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure
|
4 |
Requires at least: 3.3.1
|
5 |
Tested up to: 3.4.2
|
6 |
-
Stable tag: 3.3.
|
7 |
|
8 |
Wordfence Security is a free enterprise class security plugin that includes a firewall, virus scanning, real-time traffic with geolocation and more.
|
9 |
|
@@ -153,6 +153,11 @@ or a theme, because often these have been updated to fix a security hole.
|
|
153 |
5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
|
154 |
|
155 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
156 |
= 3.3.3 =
|
157 |
* Fixed errors caused by ini_set being disabled on certain servers.
|
158 |
* Removed error logging messages in certain cases because some badly configured hosts write these errors to the web browser.
|
3 |
Tags: wordpress, security, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure
|
4 |
Requires at least: 3.3.1
|
5 |
Tested up to: 3.4.2
|
6 |
+
Stable tag: 3.3.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 |
|
153 |
5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
|
154 |
|
155 |
== Changelog ==
|
156 |
+
= 3.3.4 =
|
157 |
+
* Fixed bug that caused malformed URLs to be sent to scanning server which caused errors on some installations.
|
158 |
+
* Fixed issue that caused scans to "hang" or stall on larger sites during "Analyzing" phase when we hash files. Sites of arbitrary size can now be scanned.
|
159 |
+
* Fixed issue that caused "plugin generated X characters of unexpected output" error during install or upgrade.
|
160 |
+
|
161 |
= 3.3.3 =
|
162 |
* Fixed errors caused by ini_set being disabled on certain servers.
|
163 |
* Removed error logging messages in certain cases because some badly configured hosts write these errors to the web browser.
|
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.3.
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
-
define('WORDFENCE_VERSION', '3.3.
|
11 |
add_action('activated_plugin','wordfence_save_activation_error'); function wordfence_save_activation_error(){ update_option('wf_plugin_act_error', ob_get_contents()); }
|
12 |
if(! defined('WORDFENCE_VERSIONONLY_MODE')){
|
13 |
if((int) @ini_get('memory_limit') < 64){
|
4 |
Plugin URI: http://wordfence.com/
|
5 |
Description: Wordfence Security - Anti-virus and Firewall security plugin for WordPress
|
6 |
Author: Mark Maunder
|
7 |
+
Version: 3.3.4
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
+
define('WORDFENCE_VERSION', '3.3.4');
|
11 |
add_action('activated_plugin','wordfence_save_activation_error'); function wordfence_save_activation_error(){ update_option('wf_plugin_act_error', ob_get_contents()); }
|
12 |
if(! defined('WORDFENCE_VERSIONONLY_MODE')){
|
13 |
if((int) @ini_get('memory_limit') < 64){
|