Wordfence Security – Firewall & Malware Scan - Version 5.0.7

Version Description

  • Feature: Immediately block IP if hacker tries any of the following usernames. (Comma separated list that you can specify on the Wordfence options page)
  • Feature: Exclude exact URL's from caching. Specifically, this allows you to exclude the home page which was not possible before.
  • Feature: Exclude browsers or partial browser matches and specific cookies from caching.
  • Fix: Fixed issue where /.. dirs would be included in certain scandir operations.
  • Fix: logHuman function was not analyzing user-agent strings correctly which would allow some crawlers that execute JS to be logged as humans.
  • Fix: Removed ob_end_clean warnings about empty buffers when a human is being logged.
  • Fix: Removed warning in lib/wfCache.php caused by unset $_SERVER['QUERY_STRING'] when we check it.
  • Fix: Fixed "logged out as ''" blank username logout messages.
  • Fix: Improved security of config cache by adding a PHP header to file that we strip. Already secure because we have a .htaccess denying access, but more is better.
  • Fix: Falcon Engine option to clear Falcon cache when a post scheduled to be published in future is published.
  • Fix: Fixed Heartbleed scans hanging.
Download this release

Release Info

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

Code changes from version 5.0.6 to 5.0.7

js/admin.js CHANGED
@@ -1264,7 +1264,8 @@ window['wordfenceAdmin'] = {
1264
  var self = this;
1265
  this.ajax('wordfence_saveCacheOptions', {
1266
  allowHTTPSCaching: (jQuery('#wfallowHTTPSCaching').is(':checked') ? 1 : 0),
1267
- addCacheComment: (jQuery('#wfaddCacheComment').is(':checked') ? 1 : 0)
 
1268
  }, function(res){
1269
  if(res.updateErr){
1270
  self.colorbox('400px', "You need to manually update your .htaccess", res.updateErr + "<br />Your option was updated but you need to change the Wordfence code in your .htaccess to the following:<br /><textarea style='width: 300px; height: 120px;'>" + jQuery('<div/>').text(res.code).html() + '</textarea>');
@@ -1582,7 +1583,9 @@ window['wordfenceAdmin'] = {
1582
  patternType: patternType,
1583
  pattern: pattern
1584
  }, function(res){
1585
- window.location.reload(true);
 
 
1586
  });
1587
  },
1588
  loadCacheExclusions: function(){
1264
  var self = this;
1265
  this.ajax('wordfence_saveCacheOptions', {
1266
  allowHTTPSCaching: (jQuery('#wfallowHTTPSCaching').is(':checked') ? 1 : 0),
1267
+ addCacheComment: (jQuery('#wfaddCacheComment').is(':checked') ? 1 : 0),
1268
+ clearCacheSched: (jQuery('#wfclearCacheSched').is(':checked') ? 1 : 0)
1269
  }, function(res){
1270
  if(res.updateErr){
1271
  self.colorbox('400px', "You need to manually update your .htaccess", res.updateErr + "<br />Your option was updated but you need to change the Wordfence code in your .htaccess to the following:<br /><textarea style='width: 300px; height: 120px;'>" + jQuery('<div/>').text(res.code).html() + '</textarea>');
1583
  patternType: patternType,
1584
  pattern: pattern
1585
  }, function(res){
1586
+ if(res.ok){ //Otherwise errorMsg will get caught
1587
+ window.location.reload(true);
1588
+ }
1589
  });
1590
  },
1591
  loadCacheExclusions: function(){
lib/email_genericAlert.php CHANGED
@@ -1,10 +1,25 @@
1
- This alert was generated by Wordfence on "<?php echo $blogName; ?>" at <?php echo $date; ?>
2
 
3
  The Wordfence administrative URL for this site is: <?php echo $adminURL; ?>admin.php?page=Wordfence
4
 
5
  <?php echo $alertMsg; ?>
6
  <?php if($IPMsg){ echo "\n$IPMsg\n"; } ?>
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  --
9
  To change your alert options for Wordfence, visit:
10
  <?php echo $myOptionsURL; ?>
1
+ This email was sent from your website "<?php echo $blogName; ?>" by the Wordfence plugin at <?php echo $date; ?>
2
 
3
  The Wordfence administrative URL for this site is: <?php echo $adminURL; ?>admin.php?page=Wordfence
4
 
5
  <?php echo $alertMsg; ?>
6
  <?php if($IPMsg){ echo "\n$IPMsg\n"; } ?>
7
 
8
+ <?php if(! $isPaid){ ?>
9
+ NOTE: You are using the free version of Wordfence. Upgrading to the paid version of Wordfence gives you
10
+ two factor authentication (sign-in via cellphone) and country blocking which are both effective methods to block attacks.
11
+ A Premium Wordfence license also includes remote scanning with each scan of your site which can detect
12
+ several additional website infections. Premium members can also schedule when website scans occur and
13
+ can scan more than once per day.
14
+
15
+ As a Premium member you also get access to our priority support system located at http://support.wordfence.com/ and can file
16
+ priority support tickets using our ticketing system.
17
+
18
+ Click here to sign-up for the Premium version of Wordfence now.
19
+ https://www.wordfence.com/wordfence-signup/
20
+
21
+ <?php } ?>
22
+
23
  --
24
  To change your alert options for Wordfence, visit:
25
  <?php echo $myOptionsURL; ?>
lib/email_newIssues.php CHANGED
@@ -1,3 +1,5 @@
 
 
1
  Wordfence found the following new issues on "<?php echo get_bloginfo('name', 'raw'); ?>".
2
 
3
  Alert generated at <?php echo wfUtils::localHumanDate(); ?>
@@ -19,5 +21,20 @@ Warnings:
19
  <?php } } } ?>
20
 
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
 
1
+ This email was sent from your website "<?php echo get_bloginfo('name', 'raw'); ?>" by the Wordfence plugin.
2
+
3
  Wordfence found the following new issues on "<?php echo get_bloginfo('name', 'raw'); ?>".
4
 
5
  Alert generated at <?php echo wfUtils::localHumanDate(); ?>
21
  <?php } } } ?>
22
 
23
 
24
+ <?php if(! $isPaid){ ?>
25
+ NOTE: You are using the free version of Wordfence. Upgrading to the paid version of Wordfence gives you
26
+ two factor authentication (sign-in via cellphone) and country blocking which are both effective methods to block attacks.
27
+ A Premium Wordfence license also includes remote scanning with each scan of your site which can detect
28
+ several additional website infections. Premium members can also schedule when website scans occur and
29
+ can scan more than once per day.
30
+
31
+ As a Premium member you also get access to our priority support system located at http://support.wordfence.com/ and can file
32
+ priority support tickets using our ticketing system.
33
+
34
+ Click here to sign-up for the Premium version of Wordfence now.
35
+ https://www.wordfence.com/wordfence-signup/
36
+
37
+ <?php } ?>
38
+
39
 
40
 
lib/menu_options.php CHANGED
@@ -244,6 +244,7 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
244
  <tr><th>Don't let WordPress reveal valid users in login errors</th><td><input type="checkbox" id="loginSec_maskLoginErrors" class="wfConfigElem" name="loginSec_maskLoginErrors" <?php $w->cb('loginSec_maskLoginErrors'); ?> /></td></tr>
245
  <tr><th>Prevent users registering 'admin' username if it doesn't exist</th><td><input type="checkbox" id="loginSec_blockAdminReg" class="wfConfigElem" name="loginSec_blockAdminReg" <?php $w->cb('loginSec_blockAdminReg'); ?> /></td></tr>
246
  <tr><th>Prevent discovery of usernames through '?/author=N' scans</th><td><input type="checkbox" id="loginSec_disableAuthorScan" class="wfConfigElem" name="loginSec_disableAuthorScan" <?php $w->cb('loginSec_disableAuthorScan'); ?> /></td></tr>
 
247
  <tr><td colspan="2">
248
  <div class="wfMarker" id="wfMarkerOtherOptions"></div>
249
  <h3 class="wfConfigHeading">Other Options</h3>
244
  <tr><th>Don't let WordPress reveal valid users in login errors</th><td><input type="checkbox" id="loginSec_maskLoginErrors" class="wfConfigElem" name="loginSec_maskLoginErrors" <?php $w->cb('loginSec_maskLoginErrors'); ?> /></td></tr>
245
  <tr><th>Prevent users registering 'admin' username if it doesn't exist</th><td><input type="checkbox" id="loginSec_blockAdminReg" class="wfConfigElem" name="loginSec_blockAdminReg" <?php $w->cb('loginSec_blockAdminReg'); ?> /></td></tr>
246
  <tr><th>Prevent discovery of usernames through '?/author=N' scans</th><td><input type="checkbox" id="loginSec_disableAuthorScan" class="wfConfigElem" name="loginSec_disableAuthorScan" <?php $w->cb('loginSec_disableAuthorScan'); ?> /></td></tr>
247
+ <tr><th>Immediately block the IP of users who try to sign in as these usernames</th><td><input type="text" name="loginSec_userBlacklist" id="loginSec_userBlacklist" value="<?php echo $w->getHTML('loginSec_userBlacklist'); ?>" size="40" />&nbsp;(Comma separated. Existing users won't be blocked.)</td></tr>
248
  <tr><td colspan="2">
249
  <div class="wfMarker" id="wfMarkerOtherOptions"></div>
250
  <h3 class="wfConfigHeading">Other Options</h3>
lib/menu_sitePerf.php CHANGED
@@ -18,6 +18,7 @@ $w = new wfConfig();
18
  <table border="0">
19
  <tr><td>Allow SSL (secure HTTPS pages) to be cached:</td><td><input type="checkbox" id="wfallowHTTPSCaching" value="1" <?php $w->cb('allowHTTPSCaching'); ?> />We recommend you leave this disabled unless your<br />site uses HTTPS but does not receive/send sensitive user info.</td></tr>
20
  <tr><td>Add hidden debugging data to the bottom of the HTML source of cached pages:</td><td><input type="checkbox" id="wfaddCacheComment" value="1" <?php $w->cb('addCacheComment'); ?> />Message appears as an HTML comment below the closing HTML tag.</td></tr>
 
21
  </table>
22
  <br />
23
  <input type="button" id="button1" name="button1" class="button-primary" value="Save Changes to the the caching options above" onclick="WFAD.saveCacheOptions();" />
@@ -32,15 +33,19 @@ $w = new wfConfig();
32
  of the actions that will automatically clear the cache are:<br />
33
  Publishing a post, creating a new page, updating general settings, creating a new category, updating menus, updating widgets and installing a new plugin.
34
  </p>
35
- <h2>You can add URLs to exclude from caching</h2>
36
  <p style="width: 500px; white-space:nowrap;">
37
- If a URL
38
  <select id="wfPatternType">
39
- <option value="s">Starts with</option>
40
- <option value="e">Ends with</option>
41
- <option value="c">Contains</option>
 
 
 
 
42
  </select>
43
- this text then don't cache it:
44
  <input type="text" id="wfPattern" value="" size="20" maxlength="1000" />e.g. /my/dynamic/page/
45
  <input type="button" class="button-primary" value="Add exclusion" onclick="WFAD.addCacheExclusion(jQuery('#wfPatternType').val(), jQuery('#wfPattern').val()); return false;" />
46
  </p>
@@ -52,17 +57,29 @@ $w = new wfConfig();
52
  </div>
53
  <script type="text/x-jquery-template" id="wfCacheExclusionTmpl">
54
  <div>
55
- If the URL
56
  <strong style="color: #0A0;">
57
  {{if pt == 's'}}
58
- STARTS WITH
59
  {{else pt == 'e'}}
60
- ENDS WITH
61
  {{else pt =='c'}}
62
- CONTAINS
 
 
 
 
 
 
 
 
 
 
 
 
63
  {{/if}}
64
  </strong>
65
- the text (without quotes):
66
  <strong style="color: #F00;">
67
  "${p}"
68
  </strong>
18
  <table border="0">
19
  <tr><td>Allow SSL (secure HTTPS pages) to be cached:</td><td><input type="checkbox" id="wfallowHTTPSCaching" value="1" <?php $w->cb('allowHTTPSCaching'); ?> />We recommend you leave this disabled unless your<br />site uses HTTPS but does not receive/send sensitive user info.</td></tr>
20
  <tr><td>Add hidden debugging data to the bottom of the HTML source of cached pages:</td><td><input type="checkbox" id="wfaddCacheComment" value="1" <?php $w->cb('addCacheComment'); ?> />Message appears as an HTML comment below the closing HTML tag.</td></tr>
21
+ <tr><td>Clear cache when a scheduled post is published</td><td><input type="checkbox" id="wfclearCacheSched" value="1" <?php $w->cb('clearCacheSched'); ?> />The entire Falcon cache will be cleared when WordPress publishes a post you've scheduled to be published in future.</td></tr>
22
  </table>
23
  <br />
24
  <input type="button" id="button1" name="button1" class="button-primary" value="Save Changes to the the caching options above" onclick="WFAD.saveCacheOptions();" />
33
  of the actions that will automatically clear the cache are:<br />
34
  Publishing a post, creating a new page, updating general settings, creating a new category, updating menus, updating widgets and installing a new plugin.
35
  </p>
36
+ <h2>You can add items like URLs, cookies and browsers (user-agents) to exclude from caching</h2>
37
  <p style="width: 500px; white-space:nowrap;">
38
+ If a
39
  <select id="wfPatternType">
40
+ <option value="s">URL Starts with</option>
41
+ <option value="e">URL Ends with</option>
42
+ <option value="c">URL Contains</option>
43
+ <option value="eq">URL Exactly Matches</option>
44
+ <option value="uac">User-Agent Contains</option>
45
+ <option value="uaeq">User-Agent Exactly Matches</option>
46
+ <option value="cc">Cookie Name Contains</option>
47
  </select>
48
+ this value then don't cache it:
49
  <input type="text" id="wfPattern" value="" size="20" maxlength="1000" />e.g. /my/dynamic/page/
50
  <input type="button" class="button-primary" value="Add exclusion" onclick="WFAD.addCacheExclusion(jQuery('#wfPatternType').val(), jQuery('#wfPattern').val()); return false;" />
51
  </p>
57
  </div>
58
  <script type="text/x-jquery-template" id="wfCacheExclusionTmpl">
59
  <div>
60
+ If the
61
  <strong style="color: #0A0;">
62
  {{if pt == 's'}}
63
+ URL starts with
64
  {{else pt == 'e'}}
65
+ URL ends with
66
  {{else pt =='c'}}
67
+ URL contains
68
+ {{else pt == 'eq'}}
69
+ URL equals
70
+ {{else pt == 'uac'}}
71
+ User-Agent contains
72
+ {{else pt == 'uaeq'}}
73
+ User-Agent equals
74
+ {{else pt == 'cc'}}
75
+ Cookie Name contains
76
+ {{else pt == 'ceq'}}
77
+ Cookie Name equals
78
+ {{else pt == 'ipeq'}}
79
+ IP Address equals
80
  {{/if}}
81
  </strong>
82
+ (without quotes):
83
  <strong style="color: #F00;">
84
  "${p}"
85
  </strong>
lib/wfCache.php CHANGED
@@ -83,7 +83,7 @@ class wfCache {
83
  return false;
84
  }
85
  if($_SERVER['REQUEST_METHOD'] != 'GET'){ return false; } //Only cache GET's
86
- if(strlen($_SERVER['QUERY_STRING']) > 0 && (! preg_match('/^\d+=\d+$/', $_SERVER['QUERY_STRING'])) ){ //Don't cache query strings unless they are /?123132423=123123234 DDoS style.
87
  return false;
88
  }
89
  //wordpress_logged_in_[hash] cookies indicates logged in
@@ -98,9 +98,19 @@ class wfCache {
98
  if($ex){
99
  $ex = unserialize($ex);
100
  foreach($ex as $v){
101
- if($v['pt'] == 's'){ if(strpos($uri, $v['p']) === 0){ return false; } }
102
- if($v['pt'] == 'e'){ if(strpos($uri, $v['p']) === (strlen($uri) - strlen($v['p'])) ){ return false; } }
103
- if($v['pt'] == 'c'){ if(strpos($uri, $v['p']) !== false){ return false; } }
 
 
 
 
 
 
 
 
 
 
104
  }
105
  }
106
  return true;
@@ -417,6 +427,23 @@ class wfCache {
417
  if(wfConfig::get('allowHTTPSCaching')){
418
  $sslString = "";
419
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  $code = <<<EOT
421
  #WFCACHECODE - Do not remove this line. Disable Web Caching in Wordfence to remove this data.
422
  <IfModule mod_deflate.c>
@@ -453,7 +480,7 @@ class wfCache {
453
  RewriteCond %{QUERY_STRING} ^(?:\d+=\d+)?$
454
  RewriteCond %{REQUEST_URI} (?:\/|\.html)$ [NC]
455
  RewriteCond %{HTTP_COOKIE} !(comment_author|wp\-postpass|wf_logout|wordpress_logged_in|wptouch_switch_toggle|wpmp_switcher) [NC]
456
-
457
  RewriteCond %{REQUEST_URI} \/*([^\/]*)\/*([^\/]*)\/*([^\/]*)\/*([^\/]*)\/*([^\/]*)(.*)$
458
  RewriteCond "%{DOCUMENT_ROOT}{$pathPrefix}/wp-content/wfcache/%{HTTP_HOST}_%1/%2~%3~%4~%5~%6_wfcache%{ENV:WRDFNC_HTTPS}.html%{ENV:WRDFNC_ENC}" -f
459
  RewriteRule \/*([^\/]*)\/*([^\/]*)\/*([^\/]*)\/*([^\/]*)\/*([^\/]*)(.*)$ "{$pathPrefix}/wp-content/wfcache/%{HTTP_HOST}_{$matchCaps}_wfcache%{ENV:WRDFNC_HTTPS}.html%{ENV:WRDFNC_ENC}" [L]
@@ -462,6 +489,9 @@ class wfCache {
462
  EOT;
463
  return $code;
464
  }
 
 
 
465
  public static function scheduleUpdateBlockedIPs(){
466
  wp_clear_scheduled_hook('wordfence_update_blocked_IPs');
467
  if(wfConfig::get('cacheType') != 'falcon'){
83
  return false;
84
  }
85
  if($_SERVER['REQUEST_METHOD'] != 'GET'){ return false; } //Only cache GET's
86
+ if(isset($_SERVER['QUERY_STRING']) && strlen($_SERVER['QUERY_STRING']) > 0 && (! preg_match('/^\d+=\d+$/', $_SERVER['QUERY_STRING'])) ){ //Don't cache query strings unless they are /?123132423=123123234 DDoS style.
87
  return false;
88
  }
89
  //wordpress_logged_in_[hash] cookies indicates logged in
98
  if($ex){
99
  $ex = unserialize($ex);
100
  foreach($ex as $v){
101
+ if($v['pt'] == 'eq'){ if(strtolower($uri) == strtolower($v['p'])){ return false; } }
102
+ if($v['pt'] == 's'){ if(stripos($uri, $v['p']) === 0){ return false; } }
103
+ if($v['pt'] == 'e'){ if(stripos($uri, $v['p']) === (strlen($uri) - strlen($v['p'])) ){ return false; } }
104
+ if($v['pt'] == 'c'){ if(stripos($uri, $v['p']) !== false){ return false; } }
105
+ if($v['pt'] == 'uac'){ if(stripos($_SERVER['HTTP_USER_AGENT'], $v['p']) !== false){ return false; } } //User-agent contains
106
+ if($v['pt'] == 'uaeq'){ if(strtolower($_SERVER['HTTP_USER_AGENT']) == strtolower($v['p'])){ return false; } } //user-agent equals
107
+ if($v['pt'] == 'cc'){
108
+ foreach($_COOKIE as $cookieName){
109
+ if(stripos($cookieName, $v['p']) !== false){ //Cookie name contains pattern
110
+ return false;
111
+ }
112
+ }
113
+ }
114
  }
115
  }
116
  return true;
427
  if(wfConfig::get('allowHTTPSCaching')){
428
  $sslString = "";
429
  }
430
+ $otherRewriteConds = "";
431
+ $ex = wfConfig::get('cacheExclusions', false);
432
+ if($ex){
433
+ $ex = unserialize($ex);
434
+ foreach($ex as $v){
435
+ if($v['pt'] == 'uac'){
436
+ $otherRewriteConds .= "\n\tRewriteCond %{HTTP_USER_AGENT} !" . self::regexSpaceFix(preg_quote($v['p'])) . " [NC]";
437
+ }
438
+ if($v['pt'] == 'uaeq'){
439
+ $otherRewriteConds .= "\n\tRewriteCond %{HTTP_USER_AGENT} !^" . self::regexSpaceFix(preg_quote($v['p'])) . "$ [NC]";
440
+ }
441
+ if($v['pt'] == 'cc'){
442
+ $otherRewriteConds .= "\n\tRewriteCond %{HTTP_COOKIE} !" . self::regexSpaceFix(preg_quote($v['p'])) . " [NC]";
443
+ }
444
+ }
445
+ }
446
+
447
  $code = <<<EOT
448
  #WFCACHECODE - Do not remove this line. Disable Web Caching in Wordfence to remove this data.
449
  <IfModule mod_deflate.c>
480
  RewriteCond %{QUERY_STRING} ^(?:\d+=\d+)?$
481
  RewriteCond %{REQUEST_URI} (?:\/|\.html)$ [NC]
482
  RewriteCond %{HTTP_COOKIE} !(comment_author|wp\-postpass|wf_logout|wordpress_logged_in|wptouch_switch_toggle|wpmp_switcher) [NC]
483
+ {$otherRewriteConds}
484
  RewriteCond %{REQUEST_URI} \/*([^\/]*)\/*([^\/]*)\/*([^\/]*)\/*([^\/]*)\/*([^\/]*)(.*)$
485
  RewriteCond "%{DOCUMENT_ROOT}{$pathPrefix}/wp-content/wfcache/%{HTTP_HOST}_%1/%2~%3~%4~%5~%6_wfcache%{ENV:WRDFNC_HTTPS}.html%{ENV:WRDFNC_ENC}" -f
486
  RewriteRule \/*([^\/]*)\/*([^\/]*)\/*([^\/]*)\/*([^\/]*)\/*([^\/]*)(.*)$ "{$pathPrefix}/wp-content/wfcache/%{HTTP_HOST}_{$matchCaps}_wfcache%{ENV:WRDFNC_HTTPS}.html%{ENV:WRDFNC_ENC}" [L]
489
  EOT;
490
  return $code;
491
  }
492
+ private static function regexSpaceFix($str){
493
+ return str_replace(' ', '\\s', $str);
494
+ }
495
  public static function scheduleUpdateBlockedIPs(){
496
  wp_clear_scheduled_hook('wordfence_update_blocked_IPs');
497
  if(wfConfig::get('cacheType') != 'falcon'){
lib/wfConfig.php CHANGED
@@ -61,7 +61,7 @@ class wfConfig {
61
  ),
62
  "otherParams" => array(
63
  'securityLevel' => '0',
64
- "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0,
65
  "neverBlockBG" => "neverBlockVerified",
66
  "loginSec_countFailMins" => "5",
67
  "loginSec_lockoutMins" => "5",
@@ -136,7 +136,7 @@ class wfConfig {
136
  ),
137
  "otherParams" => array(
138
  'securityLevel' => '1',
139
- "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0,
140
  "neverBlockBG" => "neverBlockVerified",
141
  "loginSec_countFailMins" => "5",
142
  "loginSec_lockoutMins" => "5",
@@ -211,7 +211,7 @@ class wfConfig {
211
  ),
212
  "otherParams" => array(
213
  'securityLevel' => '2',
214
- "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0,
215
  "neverBlockBG" => "neverBlockVerified",
216
  "loginSec_countFailMins" => "240",
217
  "loginSec_lockoutMins" => "240",
@@ -286,7 +286,7 @@ class wfConfig {
286
  ),
287
  "otherParams" => array(
288
  'securityLevel' => '3',
289
- "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0,
290
  "neverBlockBG" => "neverBlockVerified",
291
  "loginSec_countFailMins" => "1440",
292
  "loginSec_lockoutMins" => "1440",
@@ -361,7 +361,7 @@ class wfConfig {
361
  ),
362
  "otherParams" => array(
363
  'securityLevel' => '4',
364
- "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0,
365
  "neverBlockBG" => "neverBlockVerified",
366
  "loginSec_countFailMins" => "1440",
367
  "loginSec_lockoutMins" => "1440",
@@ -483,10 +483,14 @@ class wfConfig {
483
  if(is_file($cacheFile)){
484
  //require($cacheFile); //will only require the file on first parse through this code. But we dynamically update the var and update the file with each get
485
  try {
486
- wfConfig::$diskCache = @unserialize(@file_get_contents($cacheFile));
487
- if(isset(wfConfig::$diskCache) && is_array(wfConfig::$diskCache) && isset(wfConfig::$diskCache[$key])){
488
- return wfConfig::$diskCache[$key];
489
- }
 
 
 
 
490
  } catch(Exception $err){ } //file_get or unserialize may fail, so just fail quietly.
491
  }
492
  }
@@ -494,7 +498,7 @@ class wfConfig {
494
  if(self::$diskCacheDisabled){ return $val; }
495
  wfConfig::$diskCache[$key] = isset($val) ? $val : '';
496
  try {
497
- $bytesWritten = @file_put_contents($cacheFile, serialize(wfConfig::$diskCache), LOCK_EX);
498
  } catch(Exception $err2){}
499
  if(! $bytesWritten){
500
  self::$diskCacheDisabled = true;
61
  ),
62
  "otherParams" => array(
63
  'securityLevel' => '0',
64
+ "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
65
  "neverBlockBG" => "neverBlockVerified",
66
  "loginSec_countFailMins" => "5",
67
  "loginSec_lockoutMins" => "5",
136
  ),
137
  "otherParams" => array(
138
  'securityLevel' => '1',
139
+ "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
140
  "neverBlockBG" => "neverBlockVerified",
141
  "loginSec_countFailMins" => "5",
142
  "loginSec_lockoutMins" => "5",
211
  ),
212
  "otherParams" => array(
213
  'securityLevel' => '2',
214
+ "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
215
  "neverBlockBG" => "neverBlockVerified",
216
  "loginSec_countFailMins" => "240",
217
  "loginSec_lockoutMins" => "240",
286
  ),
287
  "otherParams" => array(
288
  'securityLevel' => '3',
289
+ "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
290
  "neverBlockBG" => "neverBlockVerified",
291
  "loginSec_countFailMins" => "1440",
292
  "loginSec_lockoutMins" => "1440",
361
  ),
362
  "otherParams" => array(
363
  'securityLevel' => '4',
364
+ "alertEmails" => "", "liveTraf_ignoreUsers" => "", "liveTraf_ignoreIPs" => "", "liveTraf_ignoreUA" => "", "apiKey" => "", "maxMem" => '256', 'scan_exclude' => '', 'whitelisted' => '', 'maxExecutionTime' => '', 'howGetIPs' => '', 'actUpdateInterval' => '', 'alert_maxHourly' => 0, 'loginSec_userBlacklist' => '',
365
  "neverBlockBG" => "neverBlockVerified",
366
  "loginSec_countFailMins" => "1440",
367
  "loginSec_lockoutMins" => "1440",
483
  if(is_file($cacheFile)){
484
  //require($cacheFile); //will only require the file on first parse through this code. But we dynamically update the var and update the file with each get
485
  try {
486
+ $cont = @file_get_contents($cacheFile);
487
+ if(strpos($cont, '<?php') === 0){ //"<?php die() XX"
488
+ $cont = substr($cont, strlen(self::$tmpFileHeader));
489
+ wfConfig::$diskCache = @unserialize($cont);
490
+ if(isset(wfConfig::$diskCache) && is_array(wfConfig::$diskCache) && isset(wfConfig::$diskCache[$key])){
491
+ return wfConfig::$diskCache[$key];
492
+ }
493
+ } //Else don't return a cached value because this is an old file without the php header so we're going to rewrite it.
494
  } catch(Exception $err){ } //file_get or unserialize may fail, so just fail quietly.
495
  }
496
  }
498
  if(self::$diskCacheDisabled){ return $val; }
499
  wfConfig::$diskCache[$key] = isset($val) ? $val : '';
500
  try {
501
+ $bytesWritten = @file_put_contents($cacheFile, self::$tmpFileHeader . serialize(wfConfig::$diskCache), LOCK_EX);
502
  } catch(Exception $err2){}
503
  if(! $bytesWritten){
504
  self::$diskCacheDisabled = true;
lib/wfLog.php CHANGED
@@ -45,10 +45,18 @@ class wfLog {
45
  );
46
  }
47
  public function logLogin($action, $fail, $username){
 
 
 
48
  $user = get_user_by('login', $username);
49
  $userID = 0;
50
  if($user){
51
  $userID = $user->ID;
 
 
 
 
 
52
  }
53
  $this->getDB()->queryWrite("insert into " . $this->loginsTable . " (ctime, fail, action, username, userID, IP, UA) values (%f, %d, '%s', '%s', %s, %s, '%s')",
54
  sprintf('%.6f', microtime(true)),
@@ -767,7 +775,7 @@ class wfLog {
767
  return;
768
  }
769
  }
770
- private function do503($secsToGo, $reason){
771
  wfUtils::doNotCache();
772
  header('HTTP/1.1 503 Service Temporarily Unavailable');
773
  header('Status: 503 Service Temporarily Unavailable');
45
  );
46
  }
47
  public function logLogin($action, $fail, $username){
48
+ if(! $username){
49
+ return;
50
+ }
51
  $user = get_user_by('login', $username);
52
  $userID = 0;
53
  if($user){
54
  $userID = $user->ID;
55
+ if(! $userID){
56
+ return;
57
+ }
58
+ } else {
59
+ return;
60
  }
61
  $this->getDB()->queryWrite("insert into " . $this->loginsTable . " (ctime, fail, action, username, userID, IP, UA) values (%f, %d, '%s', '%s', %s, %s, '%s')",
62
  sprintf('%.6f', microtime(true)),
775
  return;
776
  }
777
  }
778
+ public function do503($secsToGo, $reason){
779
  wfUtils::doNotCache();
780
  header('HTTP/1.1 503 Service Temporarily Unavailable');
781
  header('Status: 503 Service Temporarily Unavailable');
lib/wfScanEngine.php CHANGED
@@ -124,7 +124,7 @@ class wfScanEngine {
124
  if($this->i->totalIssues > 0){
125
  $this->status(10, 'info', "SUM_FINAL:Scan complete. You have " . $this->i->totalIssues . " new issues to fix. See below.");
126
  } else {
127
- $this->status(10, 'info', "SUM_FINAL:Scan complete. Congratulations, there were no problems found.");
128
  }
129
  return;
130
  }
@@ -187,6 +187,7 @@ class wfScanEngine {
187
  }
188
  $includeInKnownFilesScan = array();
189
  foreach($baseContents as $file){ //Only include base files less than a meg that are files.
 
190
  $fullFile = rtrim(ABSPATH, '/') . '/' . $file;
191
  if($scanOutside){
192
  $includeInKnownFilesScan[] = $file;
124
  if($this->i->totalIssues > 0){
125
  $this->status(10, 'info', "SUM_FINAL:Scan complete. You have " . $this->i->totalIssues . " new issues to fix. See below.");
126
  } else {
127
+ $this->status(10, 'info', "SUM_FINAL:Scan complete. Congratulations, no problems found.");
128
  }
129
  return;
130
  }
187
  }
188
  $includeInKnownFilesScan = array();
189
  foreach($baseContents as $file){ //Only include base files less than a meg that are files.
190
+ if($file == '.' || $file == '..'){ continue; }
191
  $fullFile = rtrim(ABSPATH, '/') . '/' . $file;
192
  if($scanOutside){
193
  $includeInKnownFilesScan[] = $file;
lib/wordfenceClass.php CHANGED
@@ -373,6 +373,7 @@ class wordfence {
373
  add_action('profile_update', 'wordfence::profileUpdateAction', '99', 2);
374
  add_action('validate_password_reset', 'wordfence::validatePassword', 10, 2 );
375
  }
 
376
 
377
  //For debugging
378
  //add_filter( 'cron_schedules', 'wordfence::cronAddSchedules' );
@@ -416,7 +417,7 @@ class wordfence {
416
  }
417
  */
418
  public static function wpRedirectFilter($URL, $status){
419
- if(isset($_GET['author']) && preg_match('/^https?:\/\/[^\/]+\/author\/.+/i', $URL) && wfConfig::get('loginSec_disableAuthorScan') ){ //author query variable is present and we're about to redirect to a URL that starts with http://blah/author/...
420
  return home_url(); //Send the user to the home URL (as opposed to site_url() which is not the home page on some sites)
421
  }
422
  return $URL;
@@ -452,13 +453,13 @@ class wordfence {
452
  $UA = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
453
  $isCrawler = false;
454
  if($UA){
455
- $b = $browscap->getBrowser($res['UA']);
456
  if($b['Crawler']){
457
  $isCrawler = true;
458
  }
459
  }
460
 
461
- ob_end_clean();
462
  if(! headers_sent()){
463
  header('Content-type: text/javascript');
464
  header("Connection: close");
@@ -502,6 +503,11 @@ class wordfence {
502
  die(json_encode($returnArr));
503
  exit;
504
  }
 
 
 
 
 
505
  public static function validateProfileUpdate($errors, $update, $userData){
506
  wordfence::validatePassword($errors, $userData);
507
  }
@@ -779,9 +785,22 @@ class wordfence {
779
 
780
  }
781
  if($secEnabled){
782
- if(is_wp_error($authResult) && $authResult->get_error_code() == 'invalid_username' && wfConfig::get('loginSec_lockInvalidUsers')){
783
- self::lockOutIP($IP, "Used an invalid username '" . $_POST['log'] . "' to try to sign in.");
784
- require('wfLockedOut.php');
 
 
 
 
 
 
 
 
 
 
 
 
 
785
  }
786
  $tKey = 'wflginfl_' . wfUtils::inet_aton($IP);
787
  if(is_wp_error($authResult) && ($authResult->get_error_code() == 'invalid_username' || $authResult->get_error_code() == 'incorrect_password') ){
@@ -1297,6 +1316,7 @@ class wordfence {
1297
  }
1298
  wfConfig::set('allowHTTPSCaching', $_POST['allowHTTPSCaching'] == '1' ? 1 : 0);
1299
  wfConfig::set('addCacheComment', $_POST['addCacheComment'] == 1 ? '1' : 0);
 
1300
  if($changed && wfConfig::get('cacheType', false) == 'falcon'){
1301
  $err = wfCache::addHtaccessCode('add');
1302
  if($err){
@@ -1472,6 +1492,11 @@ class wordfence {
1472
  );
1473
  wfConfig::set('cacheExclusions', serialize($ex));
1474
  wfCache::scheduleCacheClear();
 
 
 
 
 
1475
  return array('ok' => 1);
1476
  }
1477
  public static function ajax_removeCacheExclusion_callback(){
@@ -1481,13 +1506,20 @@ class wordfence {
1481
  return array('ok' => 1);
1482
  }
1483
  $ex = unserialize($ex);
 
1484
  for($i = 0; $i < sizeof($ex); $i++){
1485
  if((string)$ex[$i]['id'] == (string)$id){
 
 
 
1486
  array_splice($ex, $i, 1);
1487
  //Dont break in case of dups
1488
  }
1489
  }
1490
  wfConfig::set('cacheExclusions', serialize($ex));
 
 
 
1491
  return array('ok' => 1);
1492
  }
1493
  public static function ajax_loadCacheExclusions_callback(){
@@ -1554,6 +1586,19 @@ class wordfence {
1554
  }
1555
  }
1556
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
1557
  $opts['apiKey'] = trim($opts['apiKey']);
1558
  if($opts['apiKey'] && (! preg_match('/^[a-fA-F0-9]+$/', $opts['apiKey'])) ){ //User entered something but it's garbage.
1559
  return array('errorMsg' => "You entered an API key but it is not in a valid format. It must consist only of characters A to F and 0 to 9.");
373
  add_action('profile_update', 'wordfence::profileUpdateAction', '99', 2);
374
  add_action('validate_password_reset', 'wordfence::validatePassword', 10, 2 );
375
  }
376
+ add_action('publish_future_post', 'wordfence::publishFuturePost');
377
 
378
  //For debugging
379
  //add_filter( 'cron_schedules', 'wordfence::cronAddSchedules' );
417
  }
418
  */
419
  public static function wpRedirectFilter($URL, $status){
420
+ if(isset($_GET['author']) && preg_match('/\/author\/.+/i', $URL) && wfConfig::get('loginSec_disableAuthorScan') ){ //author query variable is present and we're about to redirect to a URL that starts with http://blah/author/...
421
  return home_url(); //Send the user to the home URL (as opposed to site_url() which is not the home page on some sites)
422
  }
423
  return $URL;
453
  $UA = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
454
  $isCrawler = false;
455
  if($UA){
456
+ $b = $browscap->getBrowser($UA);
457
  if($b['Crawler']){
458
  $isCrawler = true;
459
  }
460
  }
461
 
462
+ @ob_end_clean();
463
  if(! headers_sent()){
464
  header('Content-type: text/javascript');
465
  header("Connection: close");
503
  die(json_encode($returnArr));
504
  exit;
505
  }
506
+ public static function publishFuturePost($id){
507
+ if(wfConfig::get('clearCacheSched')){
508
+ wfCache::scheduleCacheClear();
509
+ }
510
+ }
511
  public static function validateProfileUpdate($errors, $update, $userData){
512
  wordfence::validatePassword($errors, $userData);
513
  }
785
 
786
  }
787
  if($secEnabled){
788
+ if(is_wp_error($authResult) && $authResult->get_error_code() == 'invalid_username'){
789
+ if($blacklist = wfConfig::get('loginSec_userBlacklist')){
790
+ $users = explode(',', $blacklist);
791
+ foreach($users as $user){
792
+ if(strtolower($_POST['log']) == strtolower($user)){
793
+ self::getLog()->blockIP($IP, "Blocked by login security setting.");
794
+ $secsToGo = wfConfig::get('blockedTime');
795
+ self::getLog()->do503($secsToGo, "Blocked by login security setting.");
796
+ break;
797
+ }
798
+ }
799
+ }
800
+ if(wfConfig::get('loginSec_lockInvalidUsers')){
801
+ self::lockOutIP($IP, "Used an invalid username '" . $_POST['log'] . "' to try to sign in.");
802
+ require('wfLockedOut.php');
803
+ }
804
  }
805
  $tKey = 'wflginfl_' . wfUtils::inet_aton($IP);
806
  if(is_wp_error($authResult) && ($authResult->get_error_code() == 'invalid_username' || $authResult->get_error_code() == 'incorrect_password') ){
1316
  }
1317
  wfConfig::set('allowHTTPSCaching', $_POST['allowHTTPSCaching'] == '1' ? 1 : 0);
1318
  wfConfig::set('addCacheComment', $_POST['addCacheComment'] == 1 ? '1' : 0);
1319
+ wfConfig::set('clearCacheSched', $_POST['clearCacheSched'] == 1 ? '1' : 0);
1320
  if($changed && wfConfig::get('cacheType', false) == 'falcon'){
1321
  $err = wfCache::addHtaccessCode('add');
1322
  if($err){
1492
  );
1493
  wfConfig::set('cacheExclusions', serialize($ex));
1494
  wfCache::scheduleCacheClear();
1495
+ if(wfConfig::get('cacheType', false) == 'falcon' && preg_match('/^(?:uac|uaeq|cc)$/', $_POST['patternType'])){
1496
+ if(wfCache::addHtaccessCode('add')){ //rewrites htaccess rules
1497
+ return array('errorMsg' => "We added the rule you requested but could not modify your .htaccess file. Please delete this rule, check the permissions on your .htaccess file and then try again.");
1498
+ }
1499
+ }
1500
  return array('ok' => 1);
1501
  }
1502
  public static function ajax_removeCacheExclusion_callback(){
1506
  return array('ok' => 1);
1507
  }
1508
  $ex = unserialize($ex);
1509
+ $rewriteHtaccess = false;
1510
  for($i = 0; $i < sizeof($ex); $i++){
1511
  if((string)$ex[$i]['id'] == (string)$id){
1512
+ if(wfConfig::get('cacheType', false) == 'falcon' && preg_match('/^(?:uac|uaeq|cc)$/', $ex[$i]['pt'])){
1513
+ $rewriteHtaccess = true;
1514
+ }
1515
  array_splice($ex, $i, 1);
1516
  //Dont break in case of dups
1517
  }
1518
  }
1519
  wfConfig::set('cacheExclusions', serialize($ex));
1520
+ if($rewriteHtaccess && wfCache::addHtaccessCode('add')){ //rewrites htaccess rules
1521
+ return array('errorMsg', "We removed that rule but could not rewrite your .htaccess file. You're going to have to manually remove this rule from your .htaccess file. Please reload this page now.");
1522
+ }
1523
  return array('ok' => 1);
1524
  }
1525
  public static function ajax_loadCacheExclusions_callback(){
1586
  }
1587
  }
1588
  }
1589
+ $userBlacklist = array();
1590
+ foreach(explode(',', $opts['loginSec_userBlacklist']) as $user){
1591
+ $user = trim($user);
1592
+ if(strlen($user) > 0){
1593
+ $userBlacklist[] = $user;
1594
+ }
1595
+ }
1596
+ if(sizeof($userBlacklist) > 0){
1597
+ $opts['loginSec_userBlacklist'] = implode(',', $userBlacklist);
1598
+ } else {
1599
+ $opts['loginSec_userBlacklist'] = '';
1600
+ }
1601
+
1602
  $opts['apiKey'] = trim($opts['apiKey']);
1603
  if($opts['apiKey'] && (! preg_match('/^[a-fA-F0-9]+$/', $opts['apiKey'])) ){ //User entered something but it's garbage.
1604
  return array('errorMsg' => "You entered an API key but it is not in a valid format. It must consist only of characters A to F and 0 to 9.");
lib/wordfenceHash.php CHANGED
@@ -117,6 +117,7 @@ class wordfenceHash {
117
  $this->engine = $engine;
118
  $files = scandir($this->path);
119
  foreach($files as $file){
 
120
  if(sizeof($this->only) > 0 && (! in_array($file, $this->only))){
121
  continue;
122
  }
117
  $this->engine = $engine;
118
  $files = scandir($this->path);
119
  foreach($files as $file){
120
+ if($file == '.' || $file == '..'){ continue; }
121
  if(sizeof($this->only) > 0 && (! in_array($file, $this->only))){
122
  continue;
123
  }
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: mmaunder
3
  Tags: wordpress, security, performance, speed, caching, cache, caching plugin, wordpress cache, wordpress caching, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure, two factor, cellphone sign-in, cellphone signin, cellphone, twofactor, security, secure, htaccess, login, log, users, login alerts, lock, chmod, maintenance, plugin, private, privacy, protection, permissions, 503, base64, injection, code, encode, script, attack, hack, hackers, block, blocked, prevent, prevention, RFI, XSS, CRLF, CSRF, SQL Injection, vulnerability, website security, WordPress security, security log, logging, HTTP log, error log, login security, personal security, infrastructure security, firewall security, front-end security, web server security, proxy security, reverse proxy security, secure website, secure login, two factor security, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm
4
  Requires at least: 3.3.1
5
- Tested up to: 3.9
6
- Stable tag: 5.0.6
7
 
8
  Wordfence Security is a free enterprise class security and performance plugin that makes your site up to 50 times faster and more secure.
9
 
@@ -162,6 +162,19 @@ cause a security hole on your site.
162
 
163
  == Changelog ==
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  = 5.0.6 =
166
  * Feature: Prevent discovery of usernames through '?/author=N' scans. New option under login security which you can enable.
167
  * Fix: Introduced new global hash whitelist on our servers that drastically reduces false positives in all scans especially theme and plugin scans.
2
  Contributors: mmaunder
3
  Tags: wordpress, security, performance, speed, caching, cache, caching plugin, wordpress cache, wordpress caching, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure, two factor, cellphone sign-in, cellphone signin, cellphone, twofactor, security, secure, htaccess, login, log, users, login alerts, lock, chmod, maintenance, plugin, private, privacy, protection, permissions, 503, base64, injection, code, encode, script, attack, hack, hackers, block, blocked, prevent, prevention, RFI, XSS, CRLF, CSRF, SQL Injection, vulnerability, website security, WordPress security, security log, logging, HTTP log, error log, login security, personal security, infrastructure security, firewall security, front-end security, web server security, proxy security, reverse proxy security, secure website, secure login, two factor security, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm
4
  Requires at least: 3.3.1
5
+ Tested up to: 3.9.1
6
+ Stable tag: 5.0.7
7
 
8
  Wordfence Security is a free enterprise class security and performance plugin that makes your site up to 50 times faster and more secure.
9
 
162
 
163
  == Changelog ==
164
 
165
+ = 5.0.7 =
166
+ * Feature: Immediately block IP if hacker tries any of the following usernames. (Comma separated list that you can specify on the Wordfence options page)
167
+ * Feature: Exclude exact URL's from caching. Specifically, this allows you to exclude the home page which was not possible before.
168
+ * Feature: Exclude browsers or partial browser matches and specific cookies from caching.
169
+ * Fix: Fixed issue where /.. dirs would be included in certain scandir operations.
170
+ * Fix: logHuman function was not analyzing user-agent strings correctly which would allow some crawlers that execute JS to be logged as humans.
171
+ * Fix: Removed ob_end_clean warnings about empty buffers when a human is being logged.
172
+ * Fix: Removed warning in lib/wfCache.php caused by unset $_SERVER['QUERY_STRING'] when we check it.
173
+ * Fix: Fixed "logged out as ''" blank username logout messages.
174
+ * Fix: Improved security of config cache by adding a PHP header to file that we strip. Already secure because we have a .htaccess denying access, but more is better.
175
+ * Fix: Falcon Engine option to clear Falcon cache when a post scheduled to be published in future is published.
176
+ * Fix: Fixed Heartbleed scans hanging.
177
+
178
  = 5.0.6 =
179
  * Feature: Prevent discovery of usernames through '?/author=N' scans. New option under login security which you can enable.
180
  * Fix: Introduced new global hash whitelist on our servers that drastically reduces false positives in all scans especially theme and plugin scans.
wordfence.php CHANGED
@@ -2,15 +2,15 @@
2
  /*
3
  Plugin Name: Wordfence Security
4
  Plugin URI: http://www.wordfence.com/
5
- Description: Wordfence Security - Anti-virus, Firewal and Site Speedup
6
  Author: Wordfence
7
- Version: 5.0.6
8
  Author URI: http://www.wordfence.com/
9
  */
10
  if(defined('WP_INSTALLING') && WP_INSTALLING){
11
  return;
12
  }
13
- define('WORDFENCE_VERSION', '5.0.6');
14
  if(get_option('wordfenceActivated') != 1){
15
  add_action('activated_plugin','wordfence_save_activation_error'); function wordfence_save_activation_error(){ update_option('wf_plugin_act_error', ob_get_contents()); }
16
  }
2
  /*
3
  Plugin Name: Wordfence Security
4
  Plugin URI: http://www.wordfence.com/
5
+ Description: Wordfence Security - Anti-virus, Firewall and Site Speedup
6
  Author: Wordfence
7
+ Version: 5.0.7
8
  Author URI: http://www.wordfence.com/
9
  */
10
  if(defined('WP_INSTALLING') && WP_INSTALLING){
11
  return;
12
  }
13
+ define('WORDFENCE_VERSION', '5.0.7');
14
  if(get_option('wordfenceActivated') != 1){
15
  add_action('activated_plugin','wordfence_save_activation_error'); function wordfence_save_activation_error(){ update_option('wf_plugin_act_error', ob_get_contents()); }
16
  }