Wordfence Security – Firewall & Malware Scan - Version 6.3.15

Version Description

  • Improvement: Reduced memory usage on scan forking and during the known files scan stage.
  • Improvement: Added additional scan options to allow for disabling the blacklist checks while still allowing malware scanning to be enabled.
  • Improvement: Added a Wordfence Application Firewall code block for the lsapi variant of LiteSpeed.
  • Improvement: Updated the bundled GeoIP database.
  • Fix: Added a validation check to IP range whitelisting to avoid log warnings if they're malformed.
Download this release

Release Info

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

Code changes from version 6.3.14 to 6.3.15

lib/GeoIP.dat CHANGED
Binary file
lib/GeoIPv6.dat CHANGED
Binary file
lib/menu_options.php CHANGED
@@ -8,19 +8,6 @@ $w = new wfConfig();
8
  $pageTitle = "Wordfence Options";
9
  $wantsLiveActivity = true;
10
  include( 'pageTitle.php' ); ?>
11
- <!-- <div class="wordfenceLive">
12
- <table border="0" cellpadding="0" cellspacing="0" class="wordfenceLiveActivity">
13
- <tr>
14
- <td><h2>Wordfence Live Activity:</h2></td>
15
- <td id="wfLiveStatus"></td>
16
- </tr>
17
- </table>
18
- <table border="0" cellpadding="0" cellspacing="0" class="wordfenceLiveStateMessage">
19
- <tr>
20
- <td>Live Updates Paused &mdash; Click inside window to resume</td>
21
- </tr>
22
- </table>
23
- </div> -->
24
 
25
  <div class="wf-container-fluid">
26
  <div class="wf-row">
@@ -108,6 +95,13 @@ $w = new wfConfig();
108
  <span class="wf-help-block"><span style="color: #F00;">Premium Feature</span> In addition to free comment filtering (see below) this option filters comments against several additional real-time lists of known spammers and infected hosts.</span>
109
  </div>
110
  </div>
 
 
 
 
 
 
 
111
  <div class="wf-form-group">
112
  <label for="spamvertizeCheck" class="wf-col-sm-5 wf-control-label">Check if this website is being "Spamvertised" <a href="http://docs.wordfence.com/en/Wordfence_options#Check_if_this_website_is_being_.22Spamvertized.22" target="_blank" rel="noopener noreferrer" class="wfhelp"></a></label>
113
  <div class="wf-col-sm-7">
@@ -440,6 +434,10 @@ $w = new wfConfig();
440
  ),
441
  ),
442
  ),
 
 
 
 
443
  array(
444
  'id' => 'scansEnabled_posts',
445
  'label' => 'Scan posts for known dangerous URLs and suspicious content <a href="http://docs.wordfence.com/en/Wordfence_options#Scan_posts_for_known_dangerous_URLs_and_suspicious_content" target="_blank" rel="noopener noreferrer" class="wfhelp"></a>',
8
  $pageTitle = "Wordfence Options";
9
  $wantsLiveActivity = true;
10
  include( 'pageTitle.php' ); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  <div class="wf-container-fluid">
13
  <div class="wf-row">
95
  <span class="wf-help-block"><span style="color: #F00;">Premium Feature</span> In addition to free comment filtering (see below) this option filters comments against several additional real-time lists of known spammers and infected hosts.</span>
96
  </div>
97
  </div>
98
+ <div class="wf-form-group">
99
+ <label for="scansEnabled_checkGSB" class="wf-col-sm-5 wf-control-label">Check if this website is on a domain blacklist <a href="http://docs.wordfence.com/en/Wordfence_options#Check_if_this_website_is_on_a_domain_blacklist" target="_blank" rel="noopener noreferrer" class="wfhelp"></a></label>
100
+ <div class="wf-col-sm-7">
101
+ <div class="wf-checkbox"><input type="checkbox" id="scansEnabled_checkGSB" class="wfConfigElem" name="scansEnabled_checkGSB" value="1" <?php $w->cbp( 'scansEnabled_checkGSB' ); if (!wfConfig::get('isPaid')) { ?>onclick="alert('This is a paid feature because it places significant additional load on our servers.'); jQuery('#scansEnabled_checkGSB').attr('checked', false); return false;" <?php } ?>></div>
102
+ <span class="wf-help-block"><span style="color: #F00;">Premium Feature</span> When doing a scan, Wordfence will check with multiple domain blacklists to see if your site is listed.</span>
103
+ </div>
104
+ </div>
105
  <div class="wf-form-group">
106
  <label for="spamvertizeCheck" class="wf-col-sm-5 wf-control-label">Check if this website is being "Spamvertised" <a href="http://docs.wordfence.com/en/Wordfence_options#Check_if_this_website_is_being_.22Spamvertized.22" target="_blank" rel="noopener noreferrer" class="wfhelp"></a></label>
107
  <div class="wf-col-sm-7">
434
  ),
435
  ),
436
  ),
437
+ array(
438
+ 'id' => 'scansEnabled_fileContentsGSB',
439
+ 'label' => 'Scan file contents for malicious URLs <a href="http://docs.wordfence.com/en/Wordfence_options#Scan_file_contents_for_malicious_URLs" target="_blank" rel="noopener noreferrer" class="wfhelp"></a>',
440
+ ),
441
  array(
442
  'id' => 'scansEnabled_posts',
443
  'label' => 'Scan posts for known dangerous URLs and suspicious content <a href="http://docs.wordfence.com/en/Wordfence_options#Scan_posts_for_known_dangerous_URLs_and_suspicious_content" target="_blank" rel="noopener noreferrer" class="wfhelp"></a>',
lib/menu_scan_options.php CHANGED
@@ -55,6 +55,10 @@ $w = new wfConfig();
55
  ),
56
  ),
57
  ),
 
 
 
 
58
  array(
59
  'id' => 'scansEnabled_posts',
60
  'label' => 'Scan posts for known dangerous URLs and suspicious content <a href="http://docs.wordfence.com/en/Wordfence_options#Scan_posts_for_known_dangerous_URLs_and_suspicious_content" target="_blank" rel="noopener noreferrer" class="wfhelp"></a>',
55
  ),
56
  ),
57
  ),
58
+ array(
59
+ 'id' => 'scansEnabled_fileContentsGSB',
60
+ 'label' => 'Scan file contents for malicious URLs <a href="http://docs.wordfence.com/en/Wordfence_options#Scan_file_contents_for_malicious_URLs" target="_blank" rel="noopener noreferrer" class="wfhelp"></a>',
61
+ ),
62
  array(
63
  'id' => 'scansEnabled_posts',
64
  'label' => 'Scan posts for known dangerous URLs and suspicious content <a href="http://docs.wordfence.com/en/Wordfence_options#Scan_posts_for_known_dangerous_URLs_and_suspicious_content" target="_blank" rel="noopener noreferrer" class="wfhelp"></a>',
lib/wfAPI.php CHANGED
@@ -122,8 +122,8 @@ class wfAPI {
122
  throw new Exception("The Wordfence scanning servers are currently unavailable. This may be for maintenance or a temporary outage. If this still occurs in an hour, please contact support. [$this->lastHTTPStatus]");
123
  }
124
 
125
- $this->curlContent = wp_remote_retrieve_body($response);
126
- return $this->curlContent;
127
  }
128
 
129
  public function binCall($func, $postData) {
122
  throw new Exception("The Wordfence scanning servers are currently unavailable. This may be for maintenance or a temporary outage. If this still occurs in an hour, please contact support. [$this->lastHTTPStatus]");
123
  }
124
 
125
+ $content = wp_remote_retrieve_body($response);
126
+ return $content;
127
  }
128
 
129
  public function binCall($func, $postData) {
lib/wfConfig.php CHANGED
@@ -34,6 +34,7 @@ class wfConfig {
34
  //"perfLoggingEnabled" => array('value' => false, 'autoload' => self::AUTOLOAD),
35
  "scheduledScansEnabled" => array('value' => true, 'autoload' => self::AUTOLOAD),
36
  "lowResourceScansEnabled" => array('value' => false, 'autoload' => self::AUTOLOAD),
 
37
  "scansEnabled_checkHowGetIPs" => array('value' => true, 'autoload' => self::AUTOLOAD),
38
  "scansEnabled_core" => array('value' => true, 'autoload' => self::AUTOLOAD),
39
  "scansEnabled_themes" => array('value' => false, 'autoload' => self::AUTOLOAD),
@@ -41,6 +42,7 @@ class wfConfig {
41
  "scansEnabled_coreUnknown" => array('value' => true, 'autoload' => self::AUTOLOAD),
42
  "scansEnabled_malware" => array('value' => true, 'autoload' => self::AUTOLOAD),
43
  "scansEnabled_fileContents" => array('value' => true, 'autoload' => self::AUTOLOAD),
 
44
  "scansEnabled_checkReadableConfig" => array('value' => true, 'autoload' => self::AUTOLOAD),
45
  "scansEnabled_suspectedFiles" => array('value' => true, 'autoload' => self::AUTOLOAD),
46
  "scansEnabled_posts" => array('value' => true, 'autoload' => self::AUTOLOAD),
34
  //"perfLoggingEnabled" => array('value' => false, 'autoload' => self::AUTOLOAD),
35
  "scheduledScansEnabled" => array('value' => true, 'autoload' => self::AUTOLOAD),
36
  "lowResourceScansEnabled" => array('value' => false, 'autoload' => self::AUTOLOAD),
37
+ "scansEnabled_checkGSB" => array('value' => true, 'autoload' => self::AUTOLOAD),
38
  "scansEnabled_checkHowGetIPs" => array('value' => true, 'autoload' => self::AUTOLOAD),
39
  "scansEnabled_core" => array('value' => true, 'autoload' => self::AUTOLOAD),
40
  "scansEnabled_themes" => array('value' => false, 'autoload' => self::AUTOLOAD),
42
  "scansEnabled_coreUnknown" => array('value' => true, 'autoload' => self::AUTOLOAD),
43
  "scansEnabled_malware" => array('value' => true, 'autoload' => self::AUTOLOAD),
44
  "scansEnabled_fileContents" => array('value' => true, 'autoload' => self::AUTOLOAD),
45
+ "scansEnabled_fileContentsGSB" => array('value' => true, 'autoload' => self::AUTOLOAD),
46
  "scansEnabled_checkReadableConfig" => array('value' => true, 'autoload' => self::AUTOLOAD),
47
  "scansEnabled_suspectedFiles" => array('value' => true, 'autoload' => self::AUTOLOAD),
48
  "scansEnabled_posts" => array('value' => true, 'autoload' => self::AUTOLOAD),
lib/wfLog.php CHANGED
@@ -1307,6 +1307,10 @@ class wfUserIPRange {
1307
  $IPparts = explode('.', $ip);
1308
  $whiteParts = explode('.', $ip_string);
1309
  $mismatch = false;
 
 
 
 
1310
  for ($i = 0; $i <= 3; $i++) {
1311
  if (preg_match('/^\[(\d+)\-(\d+)\]$/', $whiteParts[$i], $m)) {
1312
  if ($IPparts[$i] < $m[1] || $IPparts[$i] > $m[2]) {
@@ -1331,6 +1335,10 @@ class wfUserIPRange {
1331
  $IPparts = explode(':', $ip);
1332
  $whiteParts = explode(':', $ip_string);
1333
  $mismatch = false;
 
 
 
 
1334
  for ($i = 0; $i <= 7; $i++) {
1335
  if (preg_match('/^\[([a-f0-9]+)\-([a-f0-9]+)\]$/i', $whiteParts[$i], $m)) {
1336
  $ip_group = hexdec($IPparts[$i]);
1307
  $IPparts = explode('.', $ip);
1308
  $whiteParts = explode('.', $ip_string);
1309
  $mismatch = false;
1310
+ if (count($whiteParts) != 4 || count($IPparts) != 4) {
1311
+ return false;
1312
+ }
1313
+
1314
  for ($i = 0; $i <= 3; $i++) {
1315
  if (preg_match('/^\[(\d+)\-(\d+)\]$/', $whiteParts[$i], $m)) {
1316
  if ($IPparts[$i] < $m[1] || $IPparts[$i] > $m[2]) {
1335
  $IPparts = explode(':', $ip);
1336
  $whiteParts = explode(':', $ip_string);
1337
  $mismatch = false;
1338
+ if (count($whiteParts) != 8 || count($IPparts) != 8) {
1339
+ return false;
1340
+ }
1341
+
1342
  for ($i = 0; $i <= 7; $i++) {
1343
  if (preg_match('/^\[([a-f0-9]+)\-([a-f0-9]+)\]$/i', $whiteParts[$i], $m)) {
1344
  $ip_group = hexdec($IPparts[$i]);
lib/wfScanEngine.php CHANGED
@@ -138,23 +138,22 @@ class wfScanEngine {
138
  $jobs[] = 'checkGSB';
139
  $jobs[] = 'checkHowGetIPs';
140
  $jobs[] = 'knownFiles';
141
- foreach (array('knownFiles', 'checkReadableConfig', 'fileContents', 'suspectedFiles',
142
- // 'wpscan_fullPathDisclosure', 'wpscan_directoryListingEnabled',
143
- 'posts', 'comments', 'passwds', 'dns', 'diskSpace', 'oldVersions', 'suspiciousAdminUsers') as $job) {
144
- if (wfConfig::get('scansEnabled_' . $job)) {
145
- $jobs[] = $job;
146
- }
147
- }
148
  }
149
  else if ($scanMode == self::SCAN_MODE_QUICK) {
150
- foreach (array('oldVersions') as $job) {
151
- if (wfConfig::get('scansEnabled_' . $job)) {
152
- $jobs[] = $job;
153
- }
154
- }
155
  }
156
  return $jobs;
157
  }
 
 
 
 
 
 
 
158
 
159
  public function __sleep(){ //Same order here as above for properties that are included in serialization
160
  return array('hasher', 'jobList', 'i', 'wp_version', 'apiKey', 'startTime', 'maxExecTime', 'publicScanEnabled', 'fileContentsResults', 'scanner', 'scanQueue', 'hoover', 'scanData', 'statusIDX', 'userPasswdQueue', 'passwdHasIssues', 'suspectedFiles', 'dbScanner', 'knownFilesLoader', 'metrics', 'checkHowGetIPsRequestTime', 'gsbMultisiteBlogOffset', 'updateCheck', 'pluginRepoStatus', 'malwarePrefixesHash', 'scanMode');
@@ -411,14 +410,23 @@ class wfScanEngine {
411
 
412
  private function scan_checkGSB_init() {
413
  if (wfConfig::get('isPaid')) {
414
- $this->statusIDX['checkGSB'] = wfIssues::statusStart("Checking if your site is on a domain blacklist");
415
- $h = new wordfenceURLHoover($this->apiKey, $this->wp_version);
416
- $h->cleanup();
 
 
 
 
 
 
 
 
 
417
  }
418
  }
419
 
420
  private function scan_checkGSB_main() {
421
- if (wfConfig::get('isPaid')) {
422
  if (is_multisite()) {
423
  global $wpdb;
424
  $h = new wordfenceURLHoover($this->apiKey, $this->wp_version, false, true);
@@ -441,7 +449,7 @@ class wfScanEngine {
441
  }
442
 
443
  private function scan_checkGSB_finish() {
444
- if (wfConfig::get('isPaid')) {
445
  if (is_multisite()) {
446
  $h = new wordfenceURLHoover($this->apiKey, $this->wp_version, false, true);
447
  $badURLs = $h->getBaddies();
@@ -531,9 +539,6 @@ class wfScanEngine {
531
  }
532
 
533
  wfIssues::statusEnd($this->statusIDX['checkGSB'], $haveIssues);
534
- } else {
535
- wfIssues::statusPaidOnly("Checking if your site is on a domain blacklist is for paid members only");
536
- sleep(2);
537
  }
538
  }
539
 
@@ -792,38 +797,65 @@ class wfScanEngine {
792
  private function scan_knownFiles_finish(){
793
  }
794
  private function scan_fileContents_init(){
795
- $this->statusIDX['infect'] = wfIssues::statusStart('Scanning file contents for infections and vulnerabilities');
796
- $this->statusIDX['GSB'] = wfIssues::statusStart('Scanning files for URLs on a domain blacklist');
797
- $this->scanner = new wordfenceScanner($this->apiKey, $this->wp_version, ABSPATH);
798
- $this->status(2, 'info', "Starting scan of file contents");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
799
  }
800
  private function scan_fileContents_main(){
801
- $this->fileContentsResults = $this->scanner->scan($this);
 
 
802
  }
803
  private function scan_fileContents_finish(){
804
- $this->status(2, 'info', "Done file contents scan");
805
- if($this->scanner->errorMsg){
806
- throw new Exception($this->scanner->errorMsg);
807
- }
808
- $this->scanner = null;
809
- $haveIssues = wfIssues::STATUS_SECURE;
810
- $haveIssuesGSB = wfIssues::STATUS_SECURE;
811
- foreach($this->fileContentsResults as $issue){
812
- $this->status(2, 'info', "Adding issue: " . $issue['shortMsg']);
813
- $added = $this->addIssue($issue['type'], $issue['severity'], $issue['ignoreP'], $issue['ignoreC'], $issue['shortMsg'], $issue['longMsg'], $issue['data']);
 
 
 
 
 
 
 
 
 
 
 
 
814
 
815
- if (isset($issue['data']['gsb'])) {
816
- if ($added == wfIssues::ISSUE_ADDED || $added == wfIssues::ISSUE_UPDATED) { $haveIssuesGSB = wfIssues::STATUS_PROBLEM; }
817
- else if ($haveIssuesGSB != wfIssues::STATUS_PROBLEM && ($added == wfIssues::ISSUE_IGNOREP || $added == wfIssues::ISSUE_IGNOREC)) { $haveIssuesGSB = wfIssues::STATUS_IGNORED; }
818
  }
819
- else {
820
- if ($added == wfIssues::ISSUE_ADDED || $added == wfIssues::ISSUE_UPDATED) { $haveIssues = wfIssues::STATUS_PROBLEM; }
821
- else if ($haveIssues != wfIssues::STATUS_PROBLEM && ($added == wfIssues::ISSUE_IGNOREP || $added == wfIssues::ISSUE_IGNOREC)) { $haveIssues = wfIssues::STATUS_IGNORED; }
822
  }
823
  }
824
- $this->fileContentsResults = null;
825
- wfIssues::statusEnd($this->statusIDX['infect'], $haveIssues);
826
- wfIssues::statusEnd($this->statusIDX['GSB'], $haveIssuesGSB);
827
  }
828
 
829
  private function scan_suspectedFiles() {
138
  $jobs[] = 'checkGSB';
139
  $jobs[] = 'checkHowGetIPs';
140
  $jobs[] = 'knownFiles';
141
+ self::_enqueueJobs(array('knownFiles', 'checkReadableConfig'), $jobs);
142
+ $jobs[] = 'fileContents';
143
+ self::_enqueueJobs(array('suspectedFiles', 'posts', 'comments', 'passwds', 'dns', 'diskSpace', 'oldVersions', 'suspiciousAdminUsers'), $jobs);
 
 
 
 
144
  }
145
  else if ($scanMode == self::SCAN_MODE_QUICK) {
146
+ self::_enqueueJobs(array('oldVersions'), $jobs);
 
 
 
 
147
  }
148
  return $jobs;
149
  }
150
+ private static function _enqueueJobs($possibleJobs, &$jobs) {
151
+ foreach ($possibleJobs as $job) {
152
+ if (wfConfig::get('scansEnabled_' . $job)) {
153
+ $jobs[] = $job;
154
+ }
155
+ }
156
+ }
157
 
158
  public function __sleep(){ //Same order here as above for properties that are included in serialization
159
  return array('hasher', 'jobList', 'i', 'wp_version', 'apiKey', 'startTime', 'maxExecTime', 'publicScanEnabled', 'fileContentsResults', 'scanner', 'scanQueue', 'hoover', 'scanData', 'statusIDX', 'userPasswdQueue', 'passwdHasIssues', 'suspectedFiles', 'dbScanner', 'knownFilesLoader', 'metrics', 'checkHowGetIPsRequestTime', 'gsbMultisiteBlogOffset', 'updateCheck', 'pluginRepoStatus', 'malwarePrefixesHash', 'scanMode');
410
 
411
  private function scan_checkGSB_init() {
412
  if (wfConfig::get('isPaid')) {
413
+ if (wfConfig::get('scansEnabled_checkGSB')) {
414
+ $this->statusIDX['checkGSB'] = wfIssues::statusStart("Checking if your site is on a domain blacklist");
415
+ $h = new wordfenceURLHoover($this->apiKey, $this->wp_version);
416
+ $h->cleanup();
417
+ }
418
+ else {
419
+ wfIssues::statusDisabled("Skipping check if your site is on a domain blacklist");
420
+ }
421
+ }
422
+ else {
423
+ wfIssues::statusPaidOnly("Checking if your site is on a domain blacklist is for paid members only");
424
+ sleep(2);
425
  }
426
  }
427
 
428
  private function scan_checkGSB_main() {
429
+ if (wfConfig::get('isPaid') && wfConfig::get('scansEnabled_checkGSB')) {
430
  if (is_multisite()) {
431
  global $wpdb;
432
  $h = new wordfenceURLHoover($this->apiKey, $this->wp_version, false, true);
449
  }
450
 
451
  private function scan_checkGSB_finish() {
452
+ if (wfConfig::get('isPaid') && wfConfig::get('scansEnabled_checkGSB')) {
453
  if (is_multisite()) {
454
  $h = new wordfenceURLHoover($this->apiKey, $this->wp_version, false, true);
455
  $badURLs = $h->getBaddies();
539
  }
540
 
541
  wfIssues::statusEnd($this->statusIDX['checkGSB'], $haveIssues);
 
 
 
542
  }
543
  }
544
 
797
  private function scan_knownFiles_finish(){
798
  }
799
  private function scan_fileContents_init(){
800
+ if (wfConfig::get('scansEnabled_fileContents')) {
801
+ $this->statusIDX['infect'] = wfIssues::statusStart('Scanning file contents for infections and vulnerabilities');
802
+ }
803
+ else {
804
+ wfIssues::statusDisabled("Skipping scan of file contents for infections and vulnerabilities");
805
+ }
806
+
807
+ if (wfConfig::get('scansEnabled_fileContentsGSB')) {
808
+ $this->statusIDX['GSB'] = wfIssues::statusStart('Scanning file contents for URLs on a domain blacklist');
809
+ }
810
+ else {
811
+ wfIssues::statusDisabled("Skipping scan of file contents for URLs on a domain blacklist");
812
+ }
813
+
814
+ if (wfConfig::get('scansEnabled_fileContents') || wfConfig::get('scansEnabled_fileContentsGSB')) {
815
+ $this->scanner = new wordfenceScanner($this->apiKey, $this->wp_version, ABSPATH);
816
+ $this->status(2, 'info', "Starting scan of file contents");
817
+ }
818
+ else {
819
+ $this->scanner = false;
820
+ }
821
  }
822
  private function scan_fileContents_main(){
823
+ if (wfConfig::get('scansEnabled_fileContents') || wfConfig::get('scansEnabled_fileContentsGSB')) {
824
+ $this->fileContentsResults = $this->scanner->scan($this);
825
+ }
826
  }
827
  private function scan_fileContents_finish(){
828
+ if (wfConfig::get('scansEnabled_fileContents') || wfConfig::get('scansEnabled_fileContentsGSB')) {
829
+ $this->status(2, 'info', "Done file contents scan");
830
+ if($this->scanner->errorMsg){
831
+ throw new Exception($this->scanner->errorMsg);
832
+ }
833
+ $this->scanner = null;
834
+ $haveIssues = wfIssues::STATUS_SECURE;
835
+ $haveIssuesGSB = wfIssues::STATUS_SECURE;
836
+ foreach($this->fileContentsResults as $issue){
837
+ $this->status(2, 'info', "Adding issue: " . $issue['shortMsg']);
838
+ $added = $this->addIssue($issue['type'], $issue['severity'], $issue['ignoreP'], $issue['ignoreC'], $issue['shortMsg'], $issue['longMsg'], $issue['data']);
839
+
840
+ if (isset($issue['data']['gsb'])) {
841
+ if ($added == wfIssues::ISSUE_ADDED || $added == wfIssues::ISSUE_UPDATED) { $haveIssuesGSB = wfIssues::STATUS_PROBLEM; }
842
+ else if ($haveIssuesGSB != wfIssues::STATUS_PROBLEM && ($added == wfIssues::ISSUE_IGNOREP || $added == wfIssues::ISSUE_IGNOREC)) { $haveIssuesGSB = wfIssues::STATUS_IGNORED; }
843
+ }
844
+ else {
845
+ if ($added == wfIssues::ISSUE_ADDED || $added == wfIssues::ISSUE_UPDATED) { $haveIssues = wfIssues::STATUS_PROBLEM; }
846
+ else if ($haveIssues != wfIssues::STATUS_PROBLEM && ($added == wfIssues::ISSUE_IGNOREP || $added == wfIssues::ISSUE_IGNOREC)) { $haveIssues = wfIssues::STATUS_IGNORED; }
847
+ }
848
+ }
849
+ $this->fileContentsResults = null;
850
 
851
+ if (wfConfig::get('scansEnabled_fileContents')) {
852
+ wfIssues::statusEnd($this->statusIDX['infect'], $haveIssues);
 
853
  }
854
+
855
+ if (wfConfig::get('scansEnabled_fileContentsGSB')) {
856
+ wfIssues::statusEnd($this->statusIDX['GSB'], $haveIssuesGSB);
857
  }
858
  }
 
 
 
859
  }
860
 
861
  private function scan_suspectedFiles() {
lib/wordfenceClass.php CHANGED
@@ -725,6 +725,15 @@ SQL
725
  $wpdb->query("ALTER TABLE {$hooverTable} CHANGE `hostKey` `hostKey` VARBINARY(124) NULL DEFAULT NULL");
726
  }
727
 
 
 
 
 
 
 
 
 
 
728
 
729
  //Check the How does Wordfence get IPs setting
730
  wfUtils::requestDetectProxyCallback();
@@ -5532,7 +5541,7 @@ document.location.href=$adminURL;
5532
  array("cgi", 'Apache + CGI/FastCGI', $serverInfo->isApache() &&
5533
  !$serverInfo->isApacheSuPHP() &&
5534
  ($serverInfo->isCGI() || $serverInfo->isFastCGI())),
5535
- array("litespeed", 'LiteSpeed', $serverInfo->isLiteSpeed()),
5536
  array("nginx", 'NGINX', $serverInfo->isNGINX()),
5537
  array("iis", 'Windows (IIS)', $serverInfo->isIIS()),
5538
  );
@@ -5666,7 +5675,7 @@ vulnerable code runs. This PHP setting currently refers to the Wordfence file at
5666
  array("cgi", 'Apache + CGI/FastCGI', $serverInfo->isApache() &&
5667
  !$serverInfo->isApacheSuPHP() &&
5668
  ($serverInfo->isCGI() || $serverInfo->isFastCGI())),
5669
- array("litespeed", 'LiteSpeed', $serverInfo->isLiteSpeed()),
5670
  array("nginx", 'NGINX', $serverInfo->isNGINX()),
5671
  array("iis", 'Windows (IIS)', $serverInfo->isIIS()),
5672
  );
@@ -7644,13 +7653,17 @@ $userIniHtaccessDirectives
7644
  break;
7645
 
7646
  case 'litespeed':
 
7647
  $autoPrependDirective = sprintf("# Wordfence WAF
7648
  <IfModule LiteSpeed>
7649
  php_value auto_prepend_file '%s'
7650
  </IfModule>
 
 
 
7651
  $userIniHtaccessDirectives
7652
  # END Wordfence WAF
7653
- ", addcslashes($bootstrapPath, "'"));
7654
  break;
7655
 
7656
  case 'apache-suphp':
725
  $wpdb->query("ALTER TABLE {$hooverTable} CHANGE `hostKey` `hostKey` VARBINARY(124) NULL DEFAULT NULL");
726
  }
727
 
728
+ //6.3.15
729
+ $scanFileContents = wfConfig::get('scansEnabled_fileContents', false);
730
+ if (!wfConfig::get('fileContentsGSB6315Migration', false)) {
731
+ if (!$scanFileContents) {
732
+ wfConfig::set('scansEnabled_fileContentsGSB', false);
733
+ }
734
+ wfConfig::set('fileContentsGSB6315Migration', 1);
735
+ }
736
+
737
 
738
  //Check the How does Wordfence get IPs setting
739
  wfUtils::requestDetectProxyCallback();
5541
  array("cgi", 'Apache + CGI/FastCGI', $serverInfo->isApache() &&
5542
  !$serverInfo->isApacheSuPHP() &&
5543
  ($serverInfo->isCGI() || $serverInfo->isFastCGI())),
5544
+ array("litespeed", 'LiteSpeed/lsapi', $serverInfo->isLiteSpeed()),
5545
  array("nginx", 'NGINX', $serverInfo->isNGINX()),
5546
  array("iis", 'Windows (IIS)', $serverInfo->isIIS()),
5547
  );
5675
  array("cgi", 'Apache + CGI/FastCGI', $serverInfo->isApache() &&
5676
  !$serverInfo->isApacheSuPHP() &&
5677
  ($serverInfo->isCGI() || $serverInfo->isFastCGI())),
5678
+ array("litespeed", 'LiteSpeed/lsapi', $serverInfo->isLiteSpeed()),
5679
  array("nginx", 'NGINX', $serverInfo->isNGINX()),
5680
  array("iis", 'Windows (IIS)', $serverInfo->isIIS()),
5681
  );
7653
  break;
7654
 
7655
  case 'litespeed':
7656
+ $escapedBootstrapPath = addcslashes($bootstrapPath, "'");
7657
  $autoPrependDirective = sprintf("# Wordfence WAF
7658
  <IfModule LiteSpeed>
7659
  php_value auto_prepend_file '%s'
7660
  </IfModule>
7661
+ <IfModule lsapi_module>
7662
+ php_value auto_prepend_file '%s'
7663
+ </IfModule>
7664
  $userIniHtaccessDirectives
7665
  # END Wordfence WAF
7666
+ ", $escapedBootstrapPath, $escapedBootstrapPath);
7667
  break;
7668
 
7669
  case 'apache-suphp':
lib/wordfenceScanner.php CHANGED
@@ -59,8 +59,19 @@ class wordfenceScanner {
59
  $this->results = array();
60
  $this->errorMsg = false;
61
  //First extract hosts or IP's and their URL's into $this->hostsFound and URL's into $this->urlsFound
62
- $this->urlHoover = new wordfenceURLHoover($this->apiKey, $this->wordpressVersion);
63
- $this->setupSigs();
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
 
66
  /**
@@ -69,7 +80,6 @@ class wordfenceScanner {
69
  * @throws Exception
70
  */
71
  protected function setupSigs() {
72
- $this->api = new wfAPI($this->apiKey, $this->wordpressVersion);
73
  $sigData = $this->api->call('get_patterns', array(), array());
74
  if(! (is_array($sigData) && isset($sigData['rules'])) ){
75
  throw new Exception("Wordfence could not get the attack signature patterns from the scanning server.");
@@ -192,7 +202,10 @@ class wordfenceScanner {
192
  }
193
 
194
  //The site's own URL is checked in an earlier scan stage so we exclude it here.
195
- $hooverExclusions = wordfenceURLHoover::standardExcludedHosts();
 
 
 
196
 
197
  $lastCount = 'whatever';
198
  $excludePattern = self::getExcludeFilePattern(self::EXCLUSION_PATTERNS_USER | self::EXCLUSION_PATTERNS_MALWARE);
@@ -318,122 +331,124 @@ class wordfenceScanner {
318
  }
319
 
320
  $treatAsBinary = ($isPHP || $isHTML || wfConfig::get('scansEnabled_scanImages'));
321
- if ($treatAsBinary && wfUtils::strpos($data, '$allowed'.'Sites') !== false && wfUtils::strpos($data, "define ('VER"."SION', '1.") !== false && wfUtils::strpos($data, "TimThum"."b script created by") !== false) {
322
- $this->addResult(array(
323
- 'type' => 'file',
324
- 'severity' => 1,
325
- 'ignoreP' => $this->path . $file,
326
- 'ignoreC' => $fileSum,
327
- 'shortMsg' => "File is an old version of TimThumb which is vulnerable.",
328
- 'longMsg' => "This file appears to be an old version of the TimThumb script which makes your system vulnerable to attackers. Please upgrade the theme or plugin that uses this or remove it." . $extraMsg,
329
- 'data' => array_merge(array(
330
- 'file' => $file,
331
- 'shac' => $record->SHAC,
332
- ), $dataForFile),
333
- ));
334
- break;
335
- }
336
- else {
337
- $allCommonStrings = $this->patterns['commonStrings'];
338
- $commonStringsFound = array_fill(0, count($allCommonStrings), null); //Lazily looked up below
339
-
340
- $regexMatched = false;
341
- foreach ($this->patterns['rules'] as $rule) {
342
- $stoppedOnSignature = $record->stoppedOnSignature;
343
- if (!empty($stoppedOnSignature)) { //Advance until we find the rule we stopped on last time
344
- //wordfence::status(4, 'info', "Searching for malware scan resume point (". $stoppedOnSignature . ") at rule " . $rule[0]);
345
- if ($stoppedOnSignature == $rule[0]) {
346
- $record->updateStoppedOn('', $currentPosition);
347
- wordfence::status(4, 'info', "Resuming malware scan at rule {$rule[0]}.");
348
- }
349
- continue;
350
- }
351
-
352
- $type = (isset($rule[4]) && !empty($rule[4])) ? $rule[4] : 'server';
353
- $logOnly = (isset($rule[5]) && !empty($rule[5])) ? $rule[5] : false;
354
- $commonStringIndexes = (isset($rule[6]) && is_array($rule[6])) ? $rule[6] : array();
355
- if ($type == 'server' && !$treatAsBinary) { continue; }
356
- else if (($type == 'both' || $type == 'browser') && $fileExt == 'js') { $extraMsg = ''; }
357
- else if (($type == 'both' || $type == 'browser') && !$treatAsBinary) { continue; }
358
 
359
- foreach ($commonStringIndexes as $i) {
360
- if ($commonStringsFound[$i] === null) {
361
- $s = $allCommonStrings[$i];
362
- $commonStringsFound[$i] = (preg_match('/' . $s . '/i', $data) == 1);
 
 
 
 
 
 
363
  }
364
 
365
- if (!$commonStringsFound[$i]) {
366
- //wordfence::status(4, 'info', "Skipping malware signature ({$rule[0]}) due to short circuit.");
367
- continue 2;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  }
369
- }
370
-
371
- /*if (count($commonStringIndexes) > 0) {
372
- wordfence::status(4, 'info', "Processing malware signature ({$rule[0]}) because short circuit matched.");
373
- }*/
374
-
375
- if (preg_match('/(' . $rule[2] . ')/iS', $data, $matches, PREG_OFFSET_CAPTURE)) {
376
- $matchString = $matches[1][0];
377
- $matchOffset = $matches[1][1];
378
- $beforeString = wfWAFUtils::substr($data, max(0, $matchOffset - 100), $matchOffset - max(0, $matchOffset - 100));
379
- $afterString = wfWAFUtils::substr($data, $matchOffset + strlen($matchString), 100);
380
- if (!$logOnly) {
381
- $this->addResult(array(
382
- 'type' => 'file',
383
- 'severity' => 1,
384
- 'ignoreP' => $this->path . $file,
385
- 'ignoreC' => $fileSum,
386
- 'shortMsg' => "File appears to be malicious: " . esc_html($file),
387
- 'longMsg' => "This file appears to be installed by a hacker to perform malicious activity. If you know about this file you can choose to ignore it to exclude it from future scans. The text we found in this file that matches a known malicious file is: <strong style=\"color: #F00;\" class=\"wf-split-word\">\"" . wfUtils::potentialBinaryStringToHTML((wfUtils::strlen($matchString) > 200 ? wfUtils::substr($matchString, 0, 200) . '...' : $matchString)) . "\"</strong>. The infection type is: <strong>" . esc_html($rule[3]) . '</strong>.' . $extraMsg,
388
- 'data' => array_merge(array(
389
- 'file' => $file,
390
- 'shac' => $record->SHAC,
391
- ), $dataForFile),
392
- ));
 
 
 
393
  }
394
- $regexMatched = true;
395
- $this->scanEngine->recordMetric('malwareSignature', $rule[0], array('file' => $file, 'match' => $matchString, 'before' => $beforeString, 'after' => $afterString), false);
396
- break;
397
- }
398
-
399
- if ($forkObj->shouldFork()) {
400
- $record->updateStoppedOn($rule[0], $currentPosition);
401
- fclose($fh);
402
 
403
- wordfence::status(4, 'info', "Forking during malware scan ({$rule[0]}) to ensure continuity.");
404
- $forkObj->fork(); //exits
 
 
 
 
 
405
  }
 
406
  }
407
- if ($regexMatched) { break; }
408
- }
409
- if ($treatAsBinary && wfConfig::get('scansEnabled_highSense')) {
410
- $badStringFound = false;
411
- if (strpos($data, $this->patterns['badstrings'][0]) !== false) {
412
- for ($i = 1; $i < sizeof($this->patterns['badstrings']); $i++) {
413
- if (wfUtils::strpos($data, $this->patterns['badstrings'][$i]) !== false) {
414
- $badStringFound = $this->patterns['badstrings'][$i];
415
- break;
416
  }
417
  }
418
- }
419
- if ($badStringFound) {
420
- $this->addResult(array(
421
- 'type' => 'file',
422
- 'severity' => 1,
423
- 'ignoreP' => $this->path . $file,
424
- 'ignoreC' => $fileSum,
425
- 'shortMsg' => "This file may contain malicious executable code: " . esc_html($this->path . $file),
426
- 'longMsg' => "This file is a PHP executable file and contains the word 'eval' (without quotes) and the word '<span class=\"wf-split-word\">" . esc_html($badStringFound) . "</span>' (without quotes). The eval() function along with an encoding function like the one mentioned are commonly used by hackers to hide their code. If you know about this file you can choose to ignore it to exclude it from future scans. This file was detected because you have enabled HIGH SENSITIVITY scanning. This option is more aggressive than the usual scans, and may cause false positives.",
427
- 'data' => array_merge(array(
428
- 'file' => $file,
429
- 'shac' => $record->SHAC,
430
- ), $dataForFile),
431
  ));
432
- break;
 
433
  }
434
  }
435
 
436
- if (!$dontScanForURLs) {
437
  $this->urlHoover->hoover($file, $data, $hooverExclusions);
438
  }
439
 
@@ -453,74 +468,76 @@ class wordfenceScanner {
453
  }
454
  }
455
  $this->writeScanningStatus();
456
- wordfence::status(2, 'info', "Asking Wordfence to check URLs against malware list.");
457
- $hooverResults = $this->urlHoover->getBaddies();
458
- if($this->urlHoover->errorMsg){
459
- $this->errorMsg = $this->urlHoover->errorMsg;
460
- return false;
461
- }
462
- $this->urlHoover->cleanup();
463
-
464
- foreach($hooverResults as $file => $hresults){
465
- $record = wordfenceMalwareScanFile::fileForPath($file);
466
- $dataForFile = $this->dataForFile($file, $this->path . $file);
467
-
468
- foreach($hresults as $result){
469
- if(preg_match('/wfBrowscapCache\.php$/', $file)){
470
- continue;
471
- }
472
-
473
- if (empty($result['URL'])) {
474
- continue;
475
- }
476
-
477
- if ($result['badList'] == 'goog-malware-shavar') {
478
- $this->addResult(array(
479
- 'type' => 'file',
480
- 'severity' => 1,
481
- 'ignoreP' => $this->path . $file,
482
- 'ignoreC' => md5_file($this->path . $file),
483
- 'shortMsg' => "File contains suspected malware URL: " . esc_html($this->path . $file),
484
- 'longMsg' => "This file contains a suspected malware URL listed on Google's list of malware sites. Wordfence decodes " . esc_html($this->patterns['word3']) . " when scanning files so the URL may not be visible if you view this file. The URL is: " . esc_html($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\" rel=\"noopener noreferrer\">Google Safe Browsing diagnostic page</a>.",
485
- 'data' => array_merge(array(
486
- 'file' => $file,
487
- 'shac' => $record->SHAC,
488
- 'badURL' => $result['URL'],
489
- 'gsb' => 'goog-malware-shavar'
490
- ), $dataForFile),
491
- ));
492
- }
493
- else if ($result['badList'] == 'googpub-phish-shavar') {
494
- $this->addResult(array(
495
- 'type' => 'file',
496
- 'severity' => 1,
497
- 'ignoreP' => $this->path . $file,
498
- 'ignoreC' => md5_file($this->path . $file),
499
- 'shortMsg' => "File contains suspected phishing URL: " . esc_html($this->path . $file),
500
- '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: " . esc_html($result['URL']),
501
- 'data' => array_merge(array(
502
- 'file' => $file,
503
- 'shac' => $record->SHAC,
504
- 'badURL' => $result['URL'],
505
- 'gsb' => 'googpub-phish-shavar'
506
- ), $dataForFile),
507
- ));
508
- }
509
- else if ($result['badList'] == 'wordfence-dbl') {
510
- $this->addResult(array(
511
- 'type' => 'file',
512
- 'severity' => 1,
513
- 'ignoreP' => $this->path . $file,
514
- 'ignoreC' => md5_file($this->path . $file),
515
- 'shortMsg' => "File contains suspected malware URL: " . esc_html($this->path . $file),
516
- 'longMsg' => "This file contains a URL that is currently listed on Wordfence's domain blacklist. The URL is: " . esc_html($result['URL']),
517
- 'data' => array_merge(array(
518
- 'file' => $file,
519
- 'shac' => $record->SHAC,
520
- 'badURL' => $result['URL'],
521
- 'gsb' => 'wordfence-dbl'
522
- ), $dataForFile),
523
- ));
 
 
524
  }
525
  }
526
  }
59
  $this->results = array();
60
  $this->errorMsg = false;
61
  //First extract hosts or IP's and their URL's into $this->hostsFound and URL's into $this->urlsFound
62
+ if (wfConfig::get('scansEnabled_fileContentsGSB')) {
63
+ $this->urlHoover = new wordfenceURLHoover($this->apiKey, $this->wordpressVersion);
64
+ }
65
+ else {
66
+ $this->urlHoover = false;
67
+ }
68
+
69
+ if (wfConfig::get('scansEnabled_fileContents')) {
70
+ $this->setupSigs();
71
+ }
72
+ else {
73
+ $this->patterns = array();
74
+ }
75
  }
76
 
77
  /**
80
  * @throws Exception
81
  */
82
  protected function setupSigs() {
 
83
  $sigData = $this->api->call('get_patterns', array(), array());
84
  if(! (is_array($sigData) && isset($sigData['rules'])) ){
85
  throw new Exception("Wordfence could not get the attack signature patterns from the scanning server.");
202
  }
203
 
204
  //The site's own URL is checked in an earlier scan stage so we exclude it here.
205
+ $hooverExclusions = array();
206
+ if (wfConfig::get('scansEnabled_fileContentsGSB')) {
207
+ $hooverExclusions = wordfenceURLHoover::standardExcludedHosts();
208
+ }
209
 
210
  $lastCount = 'whatever';
211
  $excludePattern = self::getExcludeFilePattern(self::EXCLUSION_PATTERNS_USER | self::EXCLUSION_PATTERNS_MALWARE);
331
  }
332
 
333
  $treatAsBinary = ($isPHP || $isHTML || wfConfig::get('scansEnabled_scanImages'));
334
+ if (wfConfig::get('scansEnabled_fileContents')) {
335
+ if ($treatAsBinary && wfUtils::strpos($data, '$allowed'.'Sites') !== false && wfUtils::strpos($data, "define ('VER"."SION', '1.") !== false && wfUtils::strpos($data, "TimThum"."b script created by") !== false) {
336
+ $this->addResult(array(
337
+ 'type' => 'file',
338
+ 'severity' => 1,
339
+ 'ignoreP' => $this->path . $file,
340
+ 'ignoreC' => $fileSum,
341
+ 'shortMsg' => "File is an old version of TimThumb which is vulnerable.",
342
+ 'longMsg' => "This file appears to be an old version of the TimThumb script which makes your system vulnerable to attackers. Please upgrade the theme or plugin that uses this or remove it." . $extraMsg,
343
+ 'data' => array_merge(array(
344
+ 'file' => $file,
345
+ 'shac' => $record->SHAC,
346
+ ), $dataForFile),
347
+ ));
348
+ break;
349
+ }
350
+ else {
351
+ $allCommonStrings = $this->patterns['commonStrings'];
352
+ $commonStringsFound = array_fill(0, count($allCommonStrings), null); //Lazily looked up below
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
 
354
+ $regexMatched = false;
355
+ foreach ($this->patterns['rules'] as $rule) {
356
+ $stoppedOnSignature = $record->stoppedOnSignature;
357
+ if (!empty($stoppedOnSignature)) { //Advance until we find the rule we stopped on last time
358
+ //wordfence::status(4, 'info', "Searching for malware scan resume point (". $stoppedOnSignature . ") at rule " . $rule[0]);
359
+ if ($stoppedOnSignature == $rule[0]) {
360
+ $record->updateStoppedOn('', $currentPosition);
361
+ wordfence::status(4, 'info', "Resuming malware scan at rule {$rule[0]}.");
362
+ }
363
+ continue;
364
  }
365
 
366
+ $type = (isset($rule[4]) && !empty($rule[4])) ? $rule[4] : 'server';
367
+ $logOnly = (isset($rule[5]) && !empty($rule[5])) ? $rule[5] : false;
368
+ $commonStringIndexes = (isset($rule[6]) && is_array($rule[6])) ? $rule[6] : array();
369
+ if ($type == 'server' && !$treatAsBinary) { continue; }
370
+ else if (($type == 'both' || $type == 'browser') && $fileExt == 'js') { $extraMsg = ''; }
371
+ else if (($type == 'both' || $type == 'browser') && !$treatAsBinary) { continue; }
372
+
373
+ foreach ($commonStringIndexes as $i) {
374
+ if ($commonStringsFound[$i] === null) {
375
+ $s = $allCommonStrings[$i];
376
+ $commonStringsFound[$i] = (preg_match('/' . $s . '/i', $data) == 1);
377
+ }
378
+
379
+ if (!$commonStringsFound[$i]) {
380
+ //wordfence::status(4, 'info', "Skipping malware signature ({$rule[0]}) due to short circuit.");
381
+ continue 2;
382
+ }
383
  }
384
+
385
+ /*if (count($commonStringIndexes) > 0) {
386
+ wordfence::status(4, 'info', "Processing malware signature ({$rule[0]}) because short circuit matched.");
387
+ }*/
388
+
389
+ if (preg_match('/(' . $rule[2] . ')/iS', $data, $matches, PREG_OFFSET_CAPTURE)) {
390
+ $matchString = $matches[1][0];
391
+ $matchOffset = $matches[1][1];
392
+ $beforeString = wfWAFUtils::substr($data, max(0, $matchOffset - 100), $matchOffset - max(0, $matchOffset - 100));
393
+ $afterString = wfWAFUtils::substr($data, $matchOffset + strlen($matchString), 100);
394
+ if (!$logOnly) {
395
+ $this->addResult(array(
396
+ 'type' => 'file',
397
+ 'severity' => 1,
398
+ 'ignoreP' => $this->path . $file,
399
+ 'ignoreC' => $fileSum,
400
+ 'shortMsg' => "File appears to be malicious: " . esc_html($file),
401
+ 'longMsg' => "This file appears to be installed by a hacker to perform malicious activity. If you know about this file you can choose to ignore it to exclude it from future scans. The text we found in this file that matches a known malicious file is: <strong style=\"color: #F00;\" class=\"wf-split-word\">\"" . wfUtils::potentialBinaryStringToHTML((wfUtils::strlen($matchString) > 200 ? wfUtils::substr($matchString, 0, 200) . '...' : $matchString)) . "\"</strong>. The infection type is: <strong>" . esc_html($rule[3]) . '</strong>.' . $extraMsg,
402
+ 'data' => array_merge(array(
403
+ 'file' => $file,
404
+ 'shac' => $record->SHAC,
405
+ ), $dataForFile),
406
+ ));
407
+ }
408
+ $regexMatched = true;
409
+ $this->scanEngine->recordMetric('malwareSignature', $rule[0], array('file' => $file, 'match' => $matchString, 'before' => $beforeString, 'after' => $afterString), false);
410
+ break;
411
  }
 
 
 
 
 
 
 
 
412
 
413
+ if ($forkObj->shouldFork()) {
414
+ $record->updateStoppedOn($rule[0], $currentPosition);
415
+ fclose($fh);
416
+
417
+ wordfence::status(4, 'info', "Forking during malware scan ({$rule[0]}) to ensure continuity.");
418
+ $forkObj->fork(); //exits
419
+ }
420
  }
421
+ if ($regexMatched) { break; }
422
  }
423
+ if ($treatAsBinary && wfConfig::get('scansEnabled_highSense')) {
424
+ $badStringFound = false;
425
+ if (strpos($data, $this->patterns['badstrings'][0]) !== false) {
426
+ for ($i = 1; $i < sizeof($this->patterns['badstrings']); $i++) {
427
+ if (wfUtils::strpos($data, $this->patterns['badstrings'][$i]) !== false) {
428
+ $badStringFound = $this->patterns['badstrings'][$i];
429
+ break;
430
+ }
 
431
  }
432
  }
433
+ if ($badStringFound) {
434
+ $this->addResult(array(
435
+ 'type' => 'file',
436
+ 'severity' => 1,
437
+ 'ignoreP' => $this->path . $file,
438
+ 'ignoreC' => $fileSum,
439
+ 'shortMsg' => "This file may contain malicious executable code: " . esc_html($this->path . $file),
440
+ 'longMsg' => "This file is a PHP executable file and contains the word 'eval' (without quotes) and the word '<span class=\"wf-split-word\">" . esc_html($badStringFound) . "</span>' (without quotes). The eval() function along with an encoding function like the one mentioned are commonly used by hackers to hide their code. If you know about this file you can choose to ignore it to exclude it from future scans. This file was detected because you have enabled HIGH SENSITIVITY scanning. This option is more aggressive than the usual scans, and may cause false positives.",
441
+ 'data' => array_merge(array(
442
+ 'file' => $file,
443
+ 'shac' => $record->SHAC,
444
+ ), $dataForFile),
 
445
  ));
446
+ break;
447
+ }
448
  }
449
  }
450
 
451
+ if (!$dontScanForURLs && wfConfig::get('scansEnabled_fileContentsGSB')) {
452
  $this->urlHoover->hoover($file, $data, $hooverExclusions);
453
  }
454
 
468
  }
469
  }
470
  $this->writeScanningStatus();
471
+ if (wfConfig::get('scansEnabled_fileContentsGSB')) {
472
+ wordfence::status(2, 'info', "Asking Wordfence to check URLs against malware list.");
473
+ $hooverResults = $this->urlHoover->getBaddies();
474
+ if($this->urlHoover->errorMsg){
475
+ $this->errorMsg = $this->urlHoover->errorMsg;
476
+ return false;
477
+ }
478
+ $this->urlHoover->cleanup();
479
+
480
+ foreach($hooverResults as $file => $hresults){
481
+ $record = wordfenceMalwareScanFile::fileForPath($file);
482
+ $dataForFile = $this->dataForFile($file, $this->path . $file);
483
+
484
+ foreach($hresults as $result){
485
+ if(preg_match('/wfBrowscapCache\.php$/', $file)){
486
+ continue;
487
+ }
488
+
489
+ if (empty($result['URL'])) {
490
+ continue;
491
+ }
492
+
493
+ if ($result['badList'] == 'goog-malware-shavar') {
494
+ $this->addResult(array(
495
+ 'type' => 'file',
496
+ 'severity' => 1,
497
+ 'ignoreP' => $this->path . $file,
498
+ 'ignoreC' => md5_file($this->path . $file),
499
+ 'shortMsg' => "File contains suspected malware URL: " . esc_html($this->path . $file),
500
+ 'longMsg' => "This file contains a suspected malware URL listed on Google's list of malware sites. Wordfence decodes " . esc_html($this->patterns['word3']) . " when scanning files so the URL may not be visible if you view this file. The URL is: " . esc_html($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\" rel=\"noopener noreferrer\">Google Safe Browsing diagnostic page</a>.",
501
+ 'data' => array_merge(array(
502
+ 'file' => $file,
503
+ 'shac' => $record->SHAC,
504
+ 'badURL' => $result['URL'],
505
+ 'gsb' => 'goog-malware-shavar'
506
+ ), $dataForFile),
507
+ ));
508
+ }
509
+ else if ($result['badList'] == 'googpub-phish-shavar') {
510
+ $this->addResult(array(
511
+ 'type' => 'file',
512
+ 'severity' => 1,
513
+ 'ignoreP' => $this->path . $file,
514
+ 'ignoreC' => md5_file($this->path . $file),
515
+ 'shortMsg' => "File contains suspected phishing URL: " . esc_html($this->path . $file),
516
+ '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: " . esc_html($result['URL']),
517
+ 'data' => array_merge(array(
518
+ 'file' => $file,
519
+ 'shac' => $record->SHAC,
520
+ 'badURL' => $result['URL'],
521
+ 'gsb' => 'googpub-phish-shavar'
522
+ ), $dataForFile),
523
+ ));
524
+ }
525
+ else if ($result['badList'] == 'wordfence-dbl') {
526
+ $this->addResult(array(
527
+ 'type' => 'file',
528
+ 'severity' => 1,
529
+ 'ignoreP' => $this->path . $file,
530
+ 'ignoreC' => md5_file($this->path . $file),
531
+ 'shortMsg' => "File contains suspected malware URL: " . esc_html($this->path . $file),
532
+ 'longMsg' => "This file contains a URL that is currently listed on Wordfence's domain blacklist. The URL is: " . esc_html($result['URL']),
533
+ 'data' => array_merge(array(
534
+ 'file' => $file,
535
+ 'shac' => $record->SHAC,
536
+ 'badURL' => $result['URL'],
537
+ 'gsb' => 'wordfence-dbl'
538
+ ), $dataForFile),
539
+ ));
540
+ }
541
  }
542
  }
543
  }
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: mmaunder
3
  Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking
4
  Requires at least: 3.9
5
- Tested up to: 4.8.0
6
- Stable tag: 6.3.14
7
 
8
  Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
9
 
@@ -160,6 +160,13 @@ Secure your website with Wordfence.
160
 
161
  == Changelog ==
162
 
 
 
 
 
 
 
 
163
  = 6.3.14 =
164
  * Improvement: Introduced smart scan distribution. Scan times are now distributed intelligently across servers to provide consistent server performance.
165
  * Improvement: Introduced light-weight scan that runs frequently to perform checks that do not use any server resources.
2
  Contributors: mmaunder
3
  Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking
4
  Requires at least: 3.9
5
+ Tested up to: 4.8.1
6
+ Stable tag: 6.3.15
7
 
8
  Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
9
 
160
 
161
  == Changelog ==
162
 
163
+ = 6.3.15 =
164
+ * Improvement: Reduced memory usage on scan forking and during the known files scan stage.
165
+ * Improvement: Added additional scan options to allow for disabling the blacklist checks while still allowing malware scanning to be enabled.
166
+ * Improvement: Added a Wordfence Application Firewall code block for the lsapi variant of LiteSpeed.
167
+ * Improvement: Updated the bundled GeoIP database.
168
+ * Fix: Added a validation check to IP range whitelisting to avoid log warnings if they're malformed.
169
+
170
  = 6.3.14 =
171
  * Improvement: Introduced smart scan distribution. Scan times are now distributed intelligently across servers to provide consistent server performance.
172
  * Improvement: Introduced light-weight scan that runs frequently to perform checks that do not use any server resources.
waf/wfWAFUserIPRange.php CHANGED
@@ -41,6 +41,10 @@ class wfWAFUserIPRange {
41
  $IPparts = explode('.', $ip);
42
  $whiteParts = explode('.', $ip_string);
43
  $mismatch = false;
 
 
 
 
44
  for ($i = 0; $i <= 3; $i++) {
45
  if (preg_match('/^\[(\d+)\-(\d+)\]$/', $whiteParts[$i], $m)) {
46
  if ($IPparts[$i] < $m[1] || $IPparts[$i] > $m[2]) {
@@ -65,6 +69,10 @@ class wfWAFUserIPRange {
65
  $IPparts = explode(':', $ip);
66
  $whiteParts = explode(':', $ip_string);
67
  $mismatch = false;
 
 
 
 
68
  for ($i = 0; $i <= 7; $i++) {
69
  if (preg_match('/^\[([a-f0-9]+)\-([a-f0-9]+)\]$/i', $whiteParts[$i], $m)) {
70
  $ip_group = hexdec($IPparts[$i]);
41
  $IPparts = explode('.', $ip);
42
  $whiteParts = explode('.', $ip_string);
43
  $mismatch = false;
44
+ if (count($whiteParts) != 4 || count($IPparts) != 4) {
45
+ return false;
46
+ }
47
+
48
  for ($i = 0; $i <= 3; $i++) {
49
  if (preg_match('/^\[(\d+)\-(\d+)\]$/', $whiteParts[$i], $m)) {
50
  if ($IPparts[$i] < $m[1] || $IPparts[$i] > $m[2]) {
69
  $IPparts = explode(':', $ip);
70
  $whiteParts = explode(':', $ip_string);
71
  $mismatch = false;
72
+ if (count($whiteParts) != 8 || count($IPparts) != 8) {
73
+ return false;
74
+ }
75
+
76
  for ($i = 0; $i <= 7; $i++) {
77
  if (preg_match('/^\[([a-f0-9]+)\-([a-f0-9]+)\]$/i', $whiteParts[$i], $m)) {
78
  $ip_group = hexdec($IPparts[$i]);
wordfence.php CHANGED
@@ -4,14 +4,14 @@ Plugin Name: Wordfence Security
4
  Plugin URI: http://www.wordfence.com/
5
  Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
6
  Author: Wordfence
7
- Version: 6.3.14
8
  Author URI: http://www.wordfence.com/
9
  Network: true
10
  */
11
  if(defined('WP_INSTALLING') && WP_INSTALLING){
12
  return;
13
  }
14
- define('WORDFENCE_VERSION', '6.3.14');
15
  define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
16
  basename(dirname(__FILE__)) . '/' . basename(__FILE__));
17
 
4
  Plugin URI: http://www.wordfence.com/
5
  Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
6
  Author: Wordfence
7
+ Version: 6.3.15
8
  Author URI: http://www.wordfence.com/
9
  Network: true
10
  */
11
  if(defined('WP_INSTALLING') && WP_INSTALLING){
12
  return;
13
  }
14
+ define('WORDFENCE_VERSION', '6.3.15');
15
  define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
16
  basename(dirname(__FILE__)) . '/' . basename(__FILE__));
17