Wordfence Security – Firewall & Malware Scan - Version 1.4.7

Version Description

  • Vastly improved error logging including catching fatal PHP errors and logging them to status log.
  • Fixed accidental preg_replace variable interpolation.
  • Syntax fixes (various)
Download this release

Release Info

Developer mmaunder
Plugin Icon 128x128 Wordfence Security – Firewall & Malware Scan
Version 1.4.7
Comparing to
See all releases

Code changes from version 1.4.6 to 1.4.7

lib/wfAPI.php CHANGED
@@ -36,7 +36,7 @@ class wfAPI {
36
  if(! is_array($dat)){
37
  $this->errorMsg = "We could not understand the Wordfence API response when calling '$action'.";
38
  }
39
- if($dat['errorMsg']){
40
  $this->errorMsg = $dat['errorMsg'];
41
  }
42
  if($this->errorMsg){
@@ -125,7 +125,7 @@ class wfAPI {
125
  return false;
126
  }
127
  }
128
- wordfence::status(3, 'info', "Completed binary API call $func with code: $code");
129
  return array('code' => $httpStatus, 'data' => $data);
130
  }
131
  public function makeAPIQueryString(){
36
  if(! is_array($dat)){
37
  $this->errorMsg = "We could not understand the Wordfence API response when calling '$action'.";
38
  }
39
+ if(empty($dat['errorMsg']) === false){
40
  $this->errorMsg = $dat['errorMsg'];
41
  }
42
  if($this->errorMsg){
125
  return false;
126
  }
127
  }
128
+ wordfence::status(3, 'info', "Completed binary API call $func with code: $httpStatus");
129
  return array('code' => $httpStatus, 'data' => $data);
130
  }
131
  public function makeAPIQueryString(){
lib/wfIssues.php CHANGED
@@ -8,6 +8,7 @@ class wfIssues {
8
  public $totalIssues = 0;
9
  public $totalCriticalIssues = 0;
10
  public $totalWarningIssues = 0;
 
11
  public function __construct(){
12
  global $wpdb;
13
  $this->issuesTable = $wpdb->base_prefix . 'wfIssues';
8
  public $totalIssues = 0;
9
  public $totalCriticalIssues = 0;
10
  public $totalWarningIssues = 0;
11
+ private $db = false;
12
  public function __construct(){
13
  global $wpdb;
14
  $this->issuesTable = $wpdb->base_prefix . 'wfIssues';
lib/wfScanEngine.php CHANGED
@@ -121,18 +121,12 @@ class wfScanEngine {
121
  //CORE SCAN
122
  $this->status(2, 'info', "Examining files in WordPress base directory.");
123
  $hasher = new wordfenceHash(strlen(ABSPATH));
124
- $includeInScan = 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');
125
  $baseContents = scandir(ABSPATH);
126
- $includeBase = true;
127
- if(sizeof($baseContents) > 500){ //If there are more than 500 files in the base dir, then don't scan base dir files other than core WP files.
128
- $includeBase = false;
129
- }
130
- if($includeBase){
131
- foreach($baseContents as $file){ //Only include base files less than a meg that are files.
132
- $file = rtrim(ABSPATH, '/') . '/' . $file;
133
- if(is_file($file) && @filesize(ABSPATH . $file) < 1000000 && (! in_array($file, $includeInScan)) ){
134
- $includeInScan[] = $file;
135
- }
136
  }
137
  }
138
  $this->status(2, 'info', "Hashing your WordPress files for comparison against originals.");
@@ -191,7 +185,7 @@ class wfScanEngine {
191
  $this->errorStop($this->api->errorMsg);
192
  return;
193
  }
194
- if($result1['errorMsg']){
195
  $this->errorStop($result['errorMsg']);
196
  return;
197
  }
@@ -370,7 +364,7 @@ class wfScanEngine {
370
  }
371
  private function highestCap($caps){
372
  foreach(array('administrator', 'editor', 'author', 'contributor', 'subscriber') as $cap){
373
- if($caps[$cap]){
374
  return $cap;
375
  }
376
  }
@@ -378,7 +372,7 @@ class wfScanEngine {
378
  }
379
  private function isEditor($caps){
380
  foreach(array('contributor', 'author', 'editor', 'administrator') as $cap){
381
- if($caps[$cap]){
382
  return true;
383
  }
384
  }
@@ -560,7 +554,7 @@ class wfScanEngine {
560
  $pluginFile = wfUtils::getPluginBaseDir() . $plugin;
561
  $data = get_plugin_data($pluginFile);
562
  $data['newVersion'] = $vals->new_version;
563
- $key = 'wfPluginUpgrade' . ' ' . $plugin . ' ' . $data['oldVersion'] . ' ' . $data['Version'];
564
  $this->addIssue('wfPluginUpgrade', 1, $key, $key, "The Plugin \"" . $data['Name'] . "\" needs an upgrade.", "You need to upgrade \"" . $data['Name'] . "\" to the newest version to ensure you have any security fixes the developer has released.", $data);
565
  }
566
  }
121
  //CORE SCAN
122
  $this->status(2, 'info', "Examining files in WordPress base directory.");
123
  $hasher = new wordfenceHash(strlen(ABSPATH));
124
+ $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');
125
  $baseContents = scandir(ABSPATH);
126
+ foreach($baseContents as $file){ //Only include base files less than a meg that are files.
127
+ $fullFile = rtrim(ABSPATH, '/') . '/' . $file;
128
+ if(in_array($file, $baseWPStuff) || (is_file($fullFile) && is_readable($fullFile) && filesize($fullFile) < 1000000) ){
129
+ $includeInScan[] = $file;
 
 
 
 
 
 
130
  }
131
  }
132
  $this->status(2, 'info', "Hashing your WordPress files for comparison against originals.");
185
  $this->errorStop($this->api->errorMsg);
186
  return;
187
  }
188
+ if(empty($result1['errorMsg']) === false){
189
  $this->errorStop($result['errorMsg']);
190
  return;
191
  }
364
  }
365
  private function highestCap($caps){
366
  foreach(array('administrator', 'editor', 'author', 'contributor', 'subscriber') as $cap){
367
+ if(empty($caps[$cap]) === false && $caps[$cap]){
368
  return $cap;
369
  }
370
  }
372
  }
373
  private function isEditor($caps){
374
  foreach(array('contributor', 'author', 'editor', 'administrator') as $cap){
375
+ if(empty($caps[$cap]) === false && $caps[$cap]){
376
  return true;
377
  }
378
  }
554
  $pluginFile = wfUtils::getPluginBaseDir() . $plugin;
555
  $data = get_plugin_data($pluginFile);
556
  $data['newVersion'] = $vals->new_version;
557
+ $key = 'wfPluginUpgrade' . ' ' . $plugin . ' ' . $data['newVersion'] . ' ' . $data['Version'];
558
  $this->addIssue('wfPluginUpgrade', 1, $key, $key, "The Plugin \"" . $data['Name'] . "\" needs an upgrade.", "You need to upgrade \"" . $data['Name'] . "\" to the newest version to ensure you have any security fixes the developer has released.", $data);
559
  }
560
  }
lib/wordfenceClass.php CHANGED
@@ -1104,7 +1104,7 @@ class wordfence {
1104
  }
1105
  $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
1106
  $result = $api->call('get_next_scan_time', array(), array());
1107
- if($result['errorMsg']){
1108
  return $result['errorMsg'];
1109
  }
1110
  $secsToGo = 3600 * 6; //In case we can't contact the API, schedule next scan 6 hours from now.
1104
  }
1105
  $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
1106
  $result = $api->call('get_next_scan_time', array(), array());
1107
+ if(empty($result['errorMsg']) === false){
1108
  return $result['errorMsg'];
1109
  }
1110
  $secsToGo = 3600 * 6; //In case we can't contact the API, schedule next scan 6 hours from now.
lib/wordfenceURLHoover.php CHANGED
@@ -19,7 +19,7 @@ class wordfenceURLHoover {
19
  return;
20
  }
21
  try {
22
- @preg_replace("/(?<=^|[^a-zA-Z0-9\-])((?:[a-zA-Z0-9\-]+\.)+)(" . $this->dRegex . ")((?:$|[^a-zA-Z0-9\-\.\'\"])[^\r\n\s\t\"\'\$\{\}<>]*)/ie", "\$this->" . "addHost(\$id, \"$1$2\", \"$3\")", $data);
23
  } catch(Exception $e){ error_log("Regex error 1: $e"); }
24
  preg_replace("/(?<=[^\d]|^)(\d{8,10}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})([^\d\'\"][^\r\n\s\t\"\'\$\{\}<>]*)/e", "\$this->" . "addIP(\$id, \"$1\",\"$2\")", $data);
25
  }
19
  return;
20
  }
21
  try {
22
+ @preg_replace("/(?<=^|[^a-zA-Z0-9\-])((?:[a-zA-Z0-9\-]+\.)+)(" . $this->dRegex . ")((?:$|[^a-zA-Z0-9\-\.\'\"])[^\r\n\s\t\"\'\$\{\}<>]*)/ie", "\$this->" . "addHost(\$id, '$1$2', '$3')", $data);
23
  } catch(Exception $e){ error_log("Regex error 1: $e"); }
24
  preg_replace("/(?<=[^\d]|^)(\d{8,10}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})([^\d\'\"][^\r\n\s\t\"\'\$\{\}<>]*)/e", "\$this->" . "addIP(\$id, \"$1\",\"$2\")", $data);
25
  }
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: 1.4.6
7
 
8
  Wordfence Security is a free enterprise class security plugin that includes a firewall, virus scanning, real-time traffic with geolocation and more.
9
 
@@ -152,6 +152,11 @@ 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
  = 1.4.6 =
156
  * Increased memory available to Wordfence to 256M during security scans, configurable in wordfenceConstants.php
157
  * Improved memory logging during security scans. Current memory usage is now shown on the far right of filenames while scans occur.
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: 1.4.7
7
 
8
  Wordfence Security is a free enterprise class security plugin that includes a firewall, virus scanning, real-time traffic with geolocation and more.
9
 
152
  5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
153
 
154
  == Changelog ==
155
+ = 1.4.7 =
156
+ * Vastly improved error logging including catching fatal PHP errors and logging them to status log.
157
+ * Fixed accidental preg_replace variable interpolation.
158
+ * Syntax fixes (various)
159
+
160
  = 1.4.6 =
161
  * Increased memory available to Wordfence to 256M during security scans, configurable in wordfenceConstants.php
162
  * Improved memory logging during security scans. Current memory usage is now shown on the far right of filenames while scans occur.
wfscan.php CHANGED
@@ -47,13 +47,31 @@ class wfScan {
47
  @ini_set('memory_limit', WORDFENCE_MEM_LIMIT . 'M');
48
  }
49
 
50
- wfConfig::set('wf_scanRunning', time());
51
- register_shutdown_function('wfScan::clearScan');
 
 
 
52
 
 
53
  $scan = new wfScanEngine();
54
  $scan->go();
55
  wfConfig::set('wf_scanRunning', '');
56
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  private static function errorExit($msg){
58
  echo json_encode(array('errorMsg' => $msg));
59
  exit();
@@ -77,9 +95,6 @@ class wfScan {
77
  if($a['level'] == $b['level']){ return 0; }
78
  return ($a['level'] < $b['level']) ? -1 : 1;
79
  }
80
- public static function clearScan(){
81
- wfConfig::set('wf_scanRunning', '');
82
- }
83
  }
84
  wfScan::wfScanMain();
85
  ?>
47
  @ini_set('memory_limit', WORDFENCE_MEM_LIMIT . 'M');
48
  }
49
 
50
+ set_error_handler('wfScan::error_handler', E_ALL);
51
+ register_shutdown_function('wfScan::shutdown');
52
+ ob_start('wfScan::obHandler');
53
+ @error_reporting(E_ALL);
54
+ @ini_set('display_errors','On');
55
 
56
+ wfConfig::set('wf_scanRunning', time());
57
  $scan = new wfScanEngine();
58
  $scan->go();
59
  wfConfig::set('wf_scanRunning', '');
60
  }
61
+ public static function obHandler($buf){
62
+ if(strlen($buf) > 1000){
63
+ $buf = substr($buf, 0, 255);
64
+ }
65
+ if(empty($buf) === false && preg_match('/[a-zA-Z0-9]+/', $buf)){
66
+ wordfence::status(1, 'error', $buf);
67
+ }
68
+ }
69
+ public static function error_handler($errno, $errstr, $errfile, $errline){
70
+ wordfence::status(1, 'error', "$errstr ($errno) File: $errfile Line: $errline");
71
+ }
72
+ public static function shutdown(){
73
+ wfConfig::set('wf_scanRunning', '');
74
+ }
75
  private static function errorExit($msg){
76
  echo json_encode(array('errorMsg' => $msg));
77
  exit();
95
  if($a['level'] == $b['level']){ return 0; }
96
  return ($a['level'] < $b['level']) ? -1 : 1;
97
  }
 
 
 
98
  }
99
  wfScan::wfScanMain();
100
  ?>
wordfence.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Wordfence Security
4
  Plugin URI: http://wordfence.com/
5
  Description: WordPress Security - Anti-virus and Firewall security plugin for WordPress
6
  Author: Mark Maunder
7
- Version: 1.4.6
8
  Author URI: http://wordfence.com/
9
  */
10
  require_once('lib/wordfenceConstants.php');
4
  Plugin URI: http://wordfence.com/
5
  Description: WordPress Security - Anti-virus and Firewall security plugin for WordPress
6
  Author: Mark Maunder
7
+ Version: 1.4.7
8
  Author URI: http://wordfence.com/
9
  */
10
  require_once('lib/wordfenceConstants.php');