Wordfence Security – Firewall & Malware Scan - Version 6.0.6

Version Description

  • Improvement: Handled uncaught exception when noc1 is not available in 2FA.
  • Improvement: Fixed issue with limit-logins mu-plugin on GoDaddy counting first login attempt in 2FA against total allowed login attempts.
  • Fix: Fixed bug with IPs not resolving to countries when printable IP passed to logBlockedIP.
  • Fix: Fixed issue with free users country blocking redirects working after downgrade.
  • Fix: Encoded URL field in country blocking options.
  • Fix: Added a check to verify field has not already been altered prior to calling ALTER in runInstall.
  • Fix: Fixed issue with scan_options method being called after method has been removed.
  • Fix: Fixed bug in scan when dns_get_record fails and error condition was not handled.
  • Fix: Fixed PHP notice when 'Crawler' not included in browser pcap result.
Download this release

Release Info

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

Code changes from version 6.0.5 to 6.0.6

js/admin.js CHANGED
@@ -1684,7 +1684,7 @@
1684
  }
1685
  },
1686
  invalidCountryURLMsg: function(URL) {
1687
- this.colorbox('400px', "Invalid URL", "URL's that you provide for bypassing country blocking must start with '/' or 'http://' without quotes. The URL that is invalid is: " + URL);
1688
  return;
1689
  },
1690
  confirmSaveCountryBlocking: function() {
@@ -2032,6 +2032,15 @@
2032
  }
2033
  // Older versions of Opera
2034
  return this._windowHasFocus;
 
 
 
 
 
 
 
 
 
2035
  }
2036
  };
2037
  window['WFAD'] = window['wordfenceAdmin'];
1684
  }
1685
  },
1686
  invalidCountryURLMsg: function(URL) {
1687
+ this.colorbox('400px', "Invalid URL", "URL's that you provide for bypassing country blocking must start with '/' or 'http://' without quotes. The URL that is invalid is: " + this.htmlEscape(URL));
1688
  return;
1689
  },
1690
  confirmSaveCountryBlocking: function() {
2032
  }
2033
  // Older versions of Opera
2034
  return this._windowHasFocus;
2035
+ },
2036
+
2037
+ htmlEscape: function(html) {
2038
+ return String(html)
2039
+ .replace(/&/g, '&')
2040
+ .replace(/"/g, '"')
2041
+ .replace(/'/g, ''')
2042
+ .replace(/</g, '&lt;')
2043
+ .replace(/>/g, '&gt;');
2044
  }
2045
  };
2046
  window['WFAD'] = window['wordfenceAdmin'];
lib/email_genericAlert.php CHANGED
@@ -16,7 +16,7 @@ As a Premium member you also get access to our priority support system located a
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
 
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/zz1/wordfence-signup/
20
 
21
  <?php } ?>
22
 
lib/email_newIssues.php CHANGED
@@ -35,7 +35,7 @@ can scan more than once per day.</p>
35
  priority support tickets using our ticketing system. </p>
36
 
37
  <p>Click here to sign-up for the Premium version of Wordfence now.<br>
38
- <a href="https://www.wordfence.com/wordfence-signup/">https://www.wordfence.com/wordfence-signup/</a></p>
39
 
40
  <?php } ?>
41
 
35
  priority support tickets using our ticketing system. </p>
36
 
37
  <p>Click here to sign-up for the Premium version of Wordfence now.<br>
38
+ <a href="https://www.wordfence.com/zz2/wordfence-signup/">https://www.wordfence.com/zz2/wordfence-signup/</a></p>
39
 
40
  <?php } ?>
41
 
lib/email_passwdChanged.php CHANGED
@@ -20,4 +20,4 @@ You can sign in here:
20
 
21
  Thank you.
22
 
23
- Email generated by Wordfence. Learn more at http://www.wordfence.com/
20
 
21
  Thank you.
22
 
23
+ Email generated by Wordfence. Learn more at http://www.wordfence.com/zz3/
lib/email_pleaseChangePasswd.php CHANGED
@@ -20,4 +20,4 @@ numbers and symbols in your password.
20
 
21
  Thank you.
22
 
23
- Email generated by Wordfence. Learn more at http://www.wordfence.com/
20
 
21
  Thank you.
22
 
23
+ Email generated by Wordfence. Learn more at http://www.wordfence.com/zz4/
lib/menu_countryBlocking.php CHANGED
@@ -12,7 +12,7 @@ WFAD.countryMap = <?php echo json_encode($wfBulkCountries); ?>;
12
  <div class="wfPaidOnlyNotice">
13
  <strong>Country Blocking is only available to Premium Members at this time</strong><br /><br />
14
  Country Blocking is a premium feature because we have licensed a very accurate commercial geolocation database to provide this feature. If you would like to
15
- activate this feature, simply <a href="https://www.wordfence.com/wordfence-signup/" target="_blank">click here and get a premium Wordfence API Key</a>, and then copy and paste it into your options page. You can <a href="http://docs.wordfence.com/en/Country_blocking" target="_blank">learn more about Country Blocking on our documentation website</a>.
16
  </div>
17
  <?php } ?>
18
  <?php if(wfConfig::get('cacheType') == 'falcon'){ ?>
@@ -52,7 +52,7 @@ WFAD.countryMap = <?php echo json_encode($wfBulkCountries); ?>;
52
  </th></tr>
53
  <tr><th colspan="2">
54
  If user who is allowed to access the site views the URL
55
- <input type="text" id="wfBypassViewURL" value="<?php echo wp_kses(wfConfig::get('cbl_bypassViewURL', ""), array()); ?>" size="20" />
56
  then set a cookie that will bypass country blocking in future in case that user hits the site from a blocked country.
57
  </th></tr>
58
 
@@ -113,7 +113,7 @@ if(wfConfig::get('isPaid')){
113
  } else {
114
  ?>
115
  If you would like access to this premium feature, please
116
- <a href="https://www.wordfence.com/wordfence-signup/" target="_blank">upgrade to our premium version</a>.
117
  </p>
118
  <?php
119
  }
12
  <div class="wfPaidOnlyNotice">
13
  <strong>Country Blocking is only available to Premium Members at this time</strong><br /><br />
14
  Country Blocking is a premium feature because we have licensed a very accurate commercial geolocation database to provide this feature. If you would like to
15
+ activate this feature, simply <a href="https://www.wordfence.com/gnl1countryBlock1/wordfence-signup/" target="_blank">click here and get a premium Wordfence API Key</a>, and then copy and paste it into your options page. You can <a href="http://docs.wordfence.com/en/Country_blocking" target="_blank">learn more about Country Blocking on our documentation website</a>.
16
  </div>
17
  <?php } ?>
18
  <?php if(wfConfig::get('cacheType') == 'falcon'){ ?>
52
  </th></tr>
53
  <tr><th colspan="2">
54
  If user who is allowed to access the site views the URL
55
+ <input type="text" id="wfBypassViewURL" value="<?php echo esc_attr(wfConfig::get('cbl_bypassViewURL', ""), array()); ?>" size="20" />
56
  then set a cookie that will bypass country blocking in future in case that user hits the site from a blocked country.
57
  </th></tr>
58
 
113
  } else {
114
  ?>
115
  If you would like access to this premium feature, please
116
+ <a href="https://www.wordfence.com/gnl1countryBlock2/wordfence-signup/" target="_blank">upgrade to our premium version</a>.
117
  </p>
118
  <?php
119
  }
lib/menu_options.php CHANGED
@@ -38,7 +38,7 @@ $w = new wfConfig();
38
  The currently active API Key is a Premium Key. <span style="font-weight: bold; color: #0A0;">Premium scanning enabled!</span>
39
  <?php } else { ?>
40
  The currently active API Key is a <span style="color: #F00; font-weight: bold;">Free Key</span>. <a
41
- href="https://www.wordfence.com/wordfence-signup/" target="_blank">Click Here to Upgrade to
42
  Wordfence Premium now.</a>
43
  <?php } ?>
44
  </td>
@@ -48,7 +48,7 @@ $w = new wfConfig();
48
  <?php if ( wfConfig::get( 'isPaid' ) ) { ?>
49
  <table border="0">
50
  <tr>
51
- <td><a href="https://www.wordfence.com/manage-wordfence-api-keys/"
52
  target="_blank"><input type="button" value="Renew your premium license"/></a>
53
  </td>
54
  <td>&nbsp;</td>
@@ -411,7 +411,7 @@ $w = new wfConfig();
411
  <th style="color: #F00;">Scan public facing site for vulnerabilities?<a
412
  href="http://docs.wordfence.com/en/Wordfence_options#Scan_public_facing_site"
413
  target="_blank" class="wfhelp"></a>(<a
414
- href="https://www.wordfence.com/wordfence-signup/" target="_blank">Paid members only</a>)
415
  </th>
416
  <td><input type="checkbox" id="scansEnabled_public" class="wfConfigElem"
417
  name="scansEnabled_public" value="1" DISABLED /></td>
@@ -1074,7 +1074,7 @@ $w = new wfConfig();
1074
  <p>
1075
  If you use the free edition of Wordfence, you don't need to worry about entering an API key in the "API Key"
1076
  field above. One is automatically created for you. If you choose to <a
1077
- href="https://www.wordfence.com/wordfence-signup/" target="_blank">upgrade to Wordfence Premium
1078
  edition</a>, you will receive an API key. You will need to copy and paste that key into the "API Key"
1079
  field above and hit "Save" to activate your key.
1080
  </p>
38
  The currently active API Key is a Premium Key. <span style="font-weight: bold; color: #0A0;">Premium scanning enabled!</span>
39
  <?php } else { ?>
40
  The currently active API Key is a <span style="color: #F00; font-weight: bold;">Free Key</span>. <a
41
+ href="https://www.wordfence.com/gnl1optAPIKey1/wordfence-signup/" target="_blank">Click Here to Upgrade to
42
  Wordfence Premium now.</a>
43
  <?php } ?>
44
  </td>
48
  <?php if ( wfConfig::get( 'isPaid' ) ) { ?>
49
  <table border="0">
50
  <tr>
51
+ <td><a href="https://www.wordfence.com/gnl1optMngKys/manage-wordfence-api-keys/"
52
  target="_blank"><input type="button" value="Renew your premium license"/></a>
53
  </td>
54
  <td>&nbsp;</td>
411
  <th style="color: #F00;">Scan public facing site for vulnerabilities?<a
412
  href="http://docs.wordfence.com/en/Wordfence_options#Scan_public_facing_site"
413
  target="_blank" class="wfhelp"></a>(<a
414
+ href="https://www.wordfence.com/gnl1optPdOnly1/wordfence-signup/" target="_blank">Paid members only</a>)
415
  </th>
416
  <td><input type="checkbox" id="scansEnabled_public" class="wfConfigElem"
417
  name="scansEnabled_public" value="1" DISABLED /></td>
1074
  <p>
1075
  If you use the free edition of Wordfence, you don't need to worry about entering an API key in the "API Key"
1076
  field above. One is automatically created for you. If you choose to <a
1077
+ href="https://www.wordfence.com/gnl1optUpg1/wordfence-signup/" target="_blank">upgrade to Wordfence Premium
1078
  edition</a>, you will receive an API key. You will need to copy and paste that key into the "API Key"
1079
  field above and hit "Save" to activate your key.
1080
  </p>
lib/menu_passwd.php CHANGED
@@ -12,7 +12,7 @@
12
  We securely simulate a high-performance password cracking attack on your password database and will alert you to weak passwords.
13
  We then provide a way to change weak passwords or alert members that they need to improve their password strength.
14
  To activate this feature, simply
15
- <a href="https://www.wordfence.com/wordfence-signup/" target="_blank">click here and get a premium Wordfence API Key</a>, and then copy and paste it into your options page. You can
16
  <a href="http://docs.wordfence.com/en/Wordfence_Password_Auditing" target="_blank">learn more about Password Auditing on our Documentation Website</a>.
17
  </div>
18
  <?php } ?>
@@ -177,7 +177,7 @@
177
  } else {
178
  ?>
179
  If you would like access to this premium feature, please
180
- <a href="https://www.wordfence.com/wordfence-signup/" target="_blank">upgrade to our premium version</a>.
181
  </p>
182
  <?php
183
  }
12
  We securely simulate a high-performance password cracking attack on your password database and will alert you to weak passwords.
13
  We then provide a way to change weak passwords or alert members that they need to improve their password strength.
14
  To activate this feature, simply
15
+ <a href="https://www.wordfence.com/gnl1pwAuditUp1/wordfence-signup/" target="_blank">click here and get a premium Wordfence API Key</a>, and then copy and paste it into your options page. You can
16
  <a href="http://docs.wordfence.com/en/Wordfence_Password_Auditing" target="_blank">learn more about Password Auditing on our Documentation Website</a>.
17
  </div>
18
  <?php } ?>
177
  } else {
178
  ?>
179
  If you would like access to this premium feature, please
180
+ <a href="https://www.wordfence.com/gnl1pwAuditUp2/wordfence-signup/" target="_blank">upgrade to our premium version</a>.
181
  </p>
182
  <?php
183
  }
lib/menu_scan.php CHANGED
@@ -12,7 +12,7 @@
12
  </td>
13
  <td>
14
  <div style="border: 1px solid #CCC; padding: 4px;">
15
- <a href="http://docs.wordfence.com/en/Wordfence_scanning" target="_blank" class="wfhelp"></a><a href="http://docs.wordfence.com/en/Wordfence_scanning" target="_blank">Read our scanning documentation</a>. You can also <a href="#" onclick="WFAD.startTourAgain(); return false;">start the tour again</a>, <a href="http://www.wordfence.com/subscribe-to-the-wordfence-email-list/" target="_blank">subscribe to get WordPress Security Alerts and Product News</a> or <a target="_blank" href="http://support.wordfence.com/">visit our support website help.</a> Love Wordfence? You can help by doing two simple things: <a href="http://wordpress.org/extend/plugins/wordfence/" target="_blank">Go to WordPress.org now and give this plugin a 5&#9733; rating</a>. Blog about Wordfence and link to the <a href="http://wordpress.org/extend/plugins/wordfence/" target="_blank">plugin page</a> or <a href="http://www.wordfence.com/" target="_blank">www.wordfence.com</a>. Spreading the word helps us keep the best features free.
16
  </div>
17
  </td>
18
  </tr>
@@ -39,7 +39,7 @@
39
  </div>
40
  <?php } else { ?>
41
  <div style="margin: 0 0 20px 5px; width: 795px;">
42
- <strong style="color: #F00;">How to upgrade:</strong> If you would like access to our <a href="http://support.wordfence.com/" target="_blank">Premium Support help system</a> and features like Cellphone Sign-in, Country Blocking, external site scanning and the ability to schedule scans, simply <a href="https://www.wordfence.com/wordfence-signup/" target="_blank">visit our Wordfence Premium sign-up page</a> and sign up for a Premium Wordfence API key. Then go to the Wordfence options page on this site and replace your free API key with your new premium key. You will immediately be upgraded to Wordfence Premium with all the features it includes and you will have instant access to our ticketing system on <a href="http://support.wordfence.com/" target="_blank">support.wordfence.com</a>.
43
  </div>
44
 
45
  <?php } ?>
12
  </td>
13
  <td>
14
  <div style="border: 1px solid #CCC; padding: 4px;">
15
+ <a href="http://docs.wordfence.com/en/Wordfence_scanning" target="_blank" class="wfhelp"></a><a href="http://docs.wordfence.com/en/Wordfence_scanning" target="_blank">Read our scanning documentation</a>. You can also <a href="#" onclick="WFAD.startTourAgain(); return false;">start the tour again</a>, <a href="http://www.wordfence.com/gnl1listSubscr/subscribe-to-the-wordfence-email-list/" target="_blank">subscribe to get WordPress Security Alerts and Product News</a> or <a target="_blank" href="http://support.wordfence.com/">visit our support website help.</a> Love Wordfence? You can help by doing two simple things: <a href="http://wordpress.org/extend/plugins/wordfence/" target="_blank">Go to WordPress.org now and give this plugin a 5&#9733; rating</a>. Blog about Wordfence and link to the <a href="http://wordpress.org/extend/plugins/wordfence/" target="_blank">plugin page</a> or <a href="http://www.wordfence.com/gnl1scanTopHome/" target="_blank">www.wordfence.com</a>. Spreading the word helps us keep the best features free.
16
  </div>
17
  </td>
18
  </tr>
39
  </div>
40
  <?php } else { ?>
41
  <div style="margin: 0 0 20px 5px; width: 795px;">
42
+ <strong style="color: #F00;">How to upgrade:</strong> If you would like access to our <a href="http://support.wordfence.com/" target="_blank">Premium Support help system</a> and features like Cellphone Sign-in, Country Blocking, external site scanning and the ability to schedule scans, simply <a href="https://www.wordfence.com/gnl1scanUpgrade/wordfence-signup/" target="_blank">visit our Wordfence Premium sign-up page</a> and sign up for a Premium Wordfence API key. Then go to the Wordfence options page on this site and replace your free API key with your new premium key. You will immediately be upgraded to Wordfence Premium with all the features it includes and you will have instant access to our ticketing system on <a href="http://support.wordfence.com/" target="_blank">support.wordfence.com</a>.
43
  </div>
44
 
45
  <?php } ?>
lib/menu_scanSchedule.php CHANGED
@@ -6,7 +6,7 @@
6
  <div class="wfPaidOnlyNotice">
7
  <strong>Scan Scheduling is only available to Premium Members at this time</strong><br /><br />
8
  Scan Scheduling is a premium feature because it places additional load on our scanning servers. If you would like to
9
- activate this feature, simply <a href="https://www.wordfence.com/wordfence-signup/" target="_blank">click here and get a premium Wordfence API Key</a>, and then copy and paste it into your options
10
  page.
11
  </div>
12
  <?php } ?>
@@ -92,7 +92,7 @@ if(wfConfig::get('isPaid')){
92
  } else {
93
  ?>
94
  If you would like access to this premium feature, please
95
- <a href="https://www.wordfence.com/wordfence-signup/" target="_blank">upgrade to our Premium version</a>.
96
  </p>
97
  <?php
98
  }
6
  <div class="wfPaidOnlyNotice">
7
  <strong>Scan Scheduling is only available to Premium Members at this time</strong><br /><br />
8
  Scan Scheduling is a premium feature because it places additional load on our scanning servers. If you would like to
9
+ activate this feature, simply <a href="https://www.wordfence.com/gnl1scanSched1/wordfence-signup/" target="_blank">click here and get a premium Wordfence API Key</a>, and then copy and paste it into your options
10
  page.
11
  </div>
12
  <?php } ?>
92
  } else {
93
  ?>
94
  If you would like access to this premium feature, please
95
+ <a href="https://www.wordfence.com/gnl1scanSched2/wordfence-signup/" target="_blank">upgrade to our Premium version</a>.
96
  </p>
97
  <?php
98
  }
lib/menu_twoFactor.php CHANGED
@@ -6,7 +6,7 @@
6
  <div class="wfPaidOnlyNotice">
7
  <strong>Cellphone Sign-in is only available to Premium Members at this time</strong><br /><br />
8
  Cellphone Sign-in is a premium feature because we are charged per SMS we send when a user signs in. If you would like to
9
- activate this feature, simply <a href="https://www.wordfence.com/wordfence-signup/" target="_blank">click here and get a premium Wordfence API Key</a>, and then copy and paste it into your options page.
10
  <br /><br />
11
  Wordfence's Cellphone Sign-in uses a technique called "Two Factor Authentication" which is used by banks, government agencies and military world-wide as one of the most secure forms of remote system authentication. It's now available from Wordfence for your WordPress website. We recommend you enable Cellphone Sign-in for all Administrator level accounts. You can <a href="http://docs.wordfence.com/en/Cellphone_sign-in" target="_blank">learn more about Cellphone Sign-in on our documentation website</a>.
12
  </div>
@@ -78,7 +78,7 @@ if(wfConfig::get('isPaid')){
78
  } else {
79
  ?>
80
  If you would like access to this premium feature, please
81
- <a href="https://www.wordfence.com/wordfence-signup/" target="_blank">upgrade to our premium version</a>.
82
  <?php
83
  }
84
  ?>
6
  <div class="wfPaidOnlyNotice">
7
  <strong>Cellphone Sign-in is only available to Premium Members at this time</strong><br /><br />
8
  Cellphone Sign-in is a premium feature because we are charged per SMS we send when a user signs in. If you would like to
9
+ activate this feature, simply <a href="https://www.wordfence.com/gnl1twoFac1/wordfence-signup/" target="_blank">click here and get a premium Wordfence API Key</a>, and then copy and paste it into your options page.
10
  <br /><br />
11
  Wordfence's Cellphone Sign-in uses a technique called "Two Factor Authentication" which is used by banks, government agencies and military world-wide as one of the most secure forms of remote system authentication. It's now available from Wordfence for your WordPress website. We recommend you enable Cellphone Sign-in for all Administrator level accounts. You can <a href="http://docs.wordfence.com/en/Cellphone_sign-in" target="_blank">learn more about Cellphone Sign-in on our documentation website</a>.
12
  </div>
78
  } else {
79
  ?>
80
  If you would like access to this premium feature, please
81
+ <a href="https://www.wordfence.com/gnl1twoFac2/wordfence-signup/" target="_blank">upgrade to our premium version</a>.
82
  <?php
83
  }
84
  ?>
lib/wfActivityReport.php CHANGED
@@ -345,9 +345,11 @@ SQL
345
  /** @var wpdb $wpdb */
346
  global $wpdb;
347
 
348
- $is_bin_ip = !wfUtils::isValidIP($ip_address);
349
- if (!$is_bin_ip) {
350
- $ip_address = wfUtils::inet_pton($ip_address);
 
 
351
  }
352
 
353
  $blocked_table = "{$wpdb->base_prefix}wfBlockedIPLog";
@@ -357,14 +359,14 @@ SQL
357
  $unixday_insert = absint($unixday);
358
  }
359
 
360
- $country = wfUtils::IP2Country($is_bin_ip ? wfUtils::inet_ntop($ip_address) : $ip_address);
361
 
362
  $wpdb->query($wpdb->prepare(<<<SQL
363
  INSERT INTO $blocked_table (IP, countryCode, blockCount, unixday)
364
  VALUES (%s, %s, 1, $unixday_insert)
365
  ON DUPLICATE KEY UPDATE blockCount = blockCount + 1
366
  SQL
367
- , $ip_address, $country));
368
  }
369
 
370
  /**
345
  /** @var wpdb $wpdb */
346
  global $wpdb;
347
 
348
+ if (wfUtils::isValidIP($ip_address)) {
349
+ $ip_bin = wfUtils::inet_pton($ip_address);
350
+ } else {
351
+ $ip_bin = $ip_address;
352
+ $ip_address = wfUtils::inet_ntop($ip_bin);
353
  }
354
 
355
  $blocked_table = "{$wpdb->base_prefix}wfBlockedIPLog";
359
  $unixday_insert = absint($unixday);
360
  }
361
 
362
+ $country = wfUtils::IP2Country($ip_address);
363
 
364
  $wpdb->query($wpdb->prepare(<<<SQL
365
  INSERT INTO $blocked_table (IP, countryCode, blockCount, unixday)
366
  VALUES (%s, %s, 1, $unixday_insert)
367
  ON DUPLICATE KEY UPDATE blockCount = blockCount + 1
368
  SQL
369
+ , $ip_bin, $country));
370
  }
371
 
372
  /**
lib/wfLog.php CHANGED
@@ -790,57 +790,60 @@ class wfLog {
790
  }
791
  //End range/UA blocking
792
 
793
- $blockedCountries = wfConfig::get('cbl_countries', false);
794
- $bareRequestURI = wfUtils::extractBareURI($_SERVER['REQUEST_URI']);
795
- $bareBypassRedirURI = wfUtils::extractBareURI(wfConfig::get('cbl_bypassRedirURL', ''));
796
- $skipCountryBlocking = false;
 
 
797
 
798
- if($bareBypassRedirURI && $bareRequestURI == $bareBypassRedirURI){ //Run this before country blocking because even if the user isn't blocked we need to set the bypass cookie so they can bypass future blocks.
799
- $bypassRedirDest = wfConfig::get('cbl_bypassRedirDest', '');
800
- if($bypassRedirDest){
 
 
 
 
 
 
801
  self::setCBLCookieBypass();
802
- $this->redirect($bypassRedirDest); //exits
803
  }
804
- }
805
- $bareBypassViewURI = wfUtils::extractBareURI(wfConfig::get('cbl_bypassViewURL', ''));
806
- if($bareBypassViewURI && $bareBypassViewURI == $bareRequestURI){
807
- self::setCBLCookieBypass();
808
- $skipCountryBlocking = true;
809
- }
810
-
811
- if((! $skipCountryBlocking) && $blockedCountries && wfConfig::get('isPaid') && (! self::isCBLBypassCookieSet()) ){
812
- if(is_user_logged_in() && (! wfConfig::get('cbl_loggedInBlocked', false)) ){ //User is logged in and we're allowing logins
813
- //Do nothing
814
- } else if(strpos($_SERVER['REQUEST_URI'], '/wp-login.php') !== false && (! wfConfig::get('cbl_loginFormBlocked', false)) ){ //It's the login form and we're allowing that
815
- //Do nothing
816
- } else if(strpos($_SERVER['REQUEST_URI'], '/wp-login.php') === false && (! wfConfig::get('cbl_restOfSiteBlocked', false)) ){ //It's the rest of the site and we're allowing that
817
- //Do nothing
818
- } else {
819
- if($country = wfUtils::IP2Country($IP) ){
820
- foreach(explode(',', $blockedCountries) as $blocked){
821
- if(strtoupper($blocked) == strtoupper($country)){ //At this point we know the user has been blocked
822
- if(wfConfig::get('cbl_action') == 'redir'){
823
- $redirURL = wfConfig::get('cbl_redirURL');
824
- $eRedirHost = wfUtils::extractHostname($redirURL);
825
- $isExternalRedir = false;
826
- if($eRedirHost && $eRedirHost != wfUtils::extractHostname(home_url())){ //It's an external redirect...
827
- $isExternalRedir = true;
828
- }
829
- if( (! $isExternalRedir) && wfUtils::extractBareURI($redirURL) == $bareRequestURI){ //Is this the URI we want to redirect to, then don't block it
830
- //Do nothing
831
- /* Uncomment the following if page components aren't loading for the page we redirect to.
832
- Uncommenting is not recommended because it means that anyone from a blocked country
833
- can crawl your site by sending the page blocked users are redirected to as the referer for every request.
834
- But it's your call.
835
- } else if(wfUtils::extractBareURI($_SERVER['HTTP_REFERER']) == $redirURL){ //If the referer the page we want to redirect to? Then this might be loading as a component so don't block.
836
- //Do nothing
837
- */
838
  } else {
839
- $this->redirect(wfConfig::get('cbl_redirURL'));
 
840
  }
841
- } else {
842
- $this->do503(3600, "Access from your area has been temporarily limited for security reasons");
843
- wfConfig::inc('totalCountryBlocked');
844
  }
845
  }
846
  }
790
  }
791
  //End range/UA blocking
792
 
793
+ // Country blocking
794
+ if (wfConfig::get('isPaid')) {
795
+ $blockedCountries = wfConfig::get('cbl_countries', false);
796
+ $bareRequestURI = wfUtils::extractBareURI($_SERVER['REQUEST_URI']);
797
+ $bareBypassRedirURI = wfUtils::extractBareURI(wfConfig::get('cbl_bypassRedirURL', ''));
798
+ $skipCountryBlocking = false;
799
 
800
+ if($bareBypassRedirURI && $bareRequestURI == $bareBypassRedirURI){ //Run this before country blocking because even if the user isn't blocked we need to set the bypass cookie so they can bypass future blocks.
801
+ $bypassRedirDest = wfConfig::get('cbl_bypassRedirDest', '');
802
+ if($bypassRedirDest){
803
+ self::setCBLCookieBypass();
804
+ $this->redirect($bypassRedirDest); //exits
805
+ }
806
+ }
807
+ $bareBypassViewURI = wfUtils::extractBareURI(wfConfig::get('cbl_bypassViewURL', ''));
808
+ if($bareBypassViewURI && $bareBypassViewURI == $bareRequestURI){
809
  self::setCBLCookieBypass();
810
+ $skipCountryBlocking = true;
811
  }
812
+
813
+ if((! $skipCountryBlocking) && $blockedCountries && (! self::isCBLBypassCookieSet()) ){
814
+ if(is_user_logged_in() && (! wfConfig::get('cbl_loggedInBlocked', false)) ){ //User is logged in and we're allowing logins
815
+ //Do nothing
816
+ } else if(strpos($_SERVER['REQUEST_URI'], '/wp-login.php') !== false && (! wfConfig::get('cbl_loginFormBlocked', false)) ){ //It's the login form and we're allowing that
817
+ //Do nothing
818
+ } else if(strpos($_SERVER['REQUEST_URI'], '/wp-login.php') === false && (! wfConfig::get('cbl_restOfSiteBlocked', false)) ){ //It's the rest of the site and we're allowing that
819
+ //Do nothing
820
+ } else {
821
+ if($country = wfUtils::IP2Country($IP) ){
822
+ foreach(explode(',', $blockedCountries) as $blocked){
823
+ if(strtoupper($blocked) == strtoupper($country)){ //At this point we know the user has been blocked
824
+ if(wfConfig::get('cbl_action') == 'redir'){
825
+ $redirURL = wfConfig::get('cbl_redirURL');
826
+ $eRedirHost = wfUtils::extractHostname($redirURL);
827
+ $isExternalRedir = false;
828
+ if($eRedirHost && $eRedirHost != wfUtils::extractHostname(home_url())){ //It's an external redirect...
829
+ $isExternalRedir = true;
830
+ }
831
+ if( (! $isExternalRedir) && wfUtils::extractBareURI($redirURL) == $bareRequestURI){ //Is this the URI we want to redirect to, then don't block it
832
+ //Do nothing
833
+ /* Uncomment the following if page components aren't loading for the page we redirect to.
834
+ Uncommenting is not recommended because it means that anyone from a blocked country
835
+ can crawl your site by sending the page blocked users are redirected to as the referer for every request.
836
+ But it's your call.
837
+ } else if(wfUtils::extractBareURI($_SERVER['HTTP_REFERER']) == $redirURL){ //If the referer the page we want to redirect to? Then this might be loading as a component so don't block.
838
+ //Do nothing
839
+ */
840
+ } else {
841
+ $this->redirect(wfConfig::get('cbl_redirURL'));
842
+ }
 
 
 
843
  } else {
844
+ $this->do503(3600, "Access from your area has been temporarily limited for security reasons");
845
+ wfConfig::inc('totalCountryBlocked');
846
  }
 
 
 
847
  }
848
  }
849
  }
lib/wfScanEngine.php CHANGED
@@ -67,11 +67,13 @@ class wfScanEngine {
67
  $this->jobList[] = 'knownFiles_init';
68
  $this->jobList[] = 'knownFiles_main';
69
  $this->jobList[] = 'knownFiles_finish';
70
- foreach(array('knownFiles', 'fileContents', 'database', 'posts', 'comments', 'passwds', 'dns', 'diskSpace', 'oldVersions') as $scanType){
71
- if(wfConfig::get('scansEnabled_' . $scanType)){
72
- if(method_exists($this, 'scan_' . $scanType . '_init')){
73
- foreach(array('init', 'main', 'finish') as $op){ $this->jobList[] = $scanType . '_' . $op; };
74
- } else {
 
 
75
  $this->jobList[] = $scanType;
76
  }
77
  }
@@ -123,7 +125,10 @@ class wfScanEngine {
123
  while(sizeof($this->jobList) > 0){
124
  self::checkForKill();
125
  $jobName = $this->jobList[0];
126
- call_user_func(array($this, 'scan_' . $jobName));
 
 
 
127
  array_shift($this->jobList); //only shift once we're done because we may pause halfway through a job and need to pick up where we left off
128
  self::checkForKill();
129
  if($this->forkRequested){
@@ -811,16 +816,19 @@ class wfScanEngine {
811
  $host = strtolower($matches[1]);
812
  $this->status(2, 'info', "Starting DNS scan for $host");
813
 
814
- $cnameArrRec = dns_get_record($host, DNS_CNAME);
815
  $cnameArr = array();
816
  $cnamesWeMustTrack = array();
817
- foreach($cnameArrRec as $elem){
818
- $this->status(2, 'info', "Scanning CNAME DNS record for " . $elem['host']);
819
- if($elem['host'] == $host){
820
- $cnameArr[] = $elem;
821
- $cnamesWeMustTrack[] = $elem['target'];
822
- }
 
 
823
  }
 
824
  function wfAnonFunc1($a){ return $a['host'] . ' points to ' . $a['target']; }
825
  $cnameArr = array_map('wfAnonFunc1', $cnameArr);
826
  sort($cnameArr, SORT_STRING);
67
  $this->jobList[] = 'knownFiles_init';
68
  $this->jobList[] = 'knownFiles_main';
69
  $this->jobList[] = 'knownFiles_finish';
70
+ foreach (array('knownFiles', 'fileContents', 'database', 'posts', 'comments', 'passwds', 'dns', 'diskSpace', 'oldVersions') as $scanType) {
71
+ if (wfConfig::get('scansEnabled_' . $scanType)) {
72
+ if (method_exists($this, 'scan_' . $scanType . '_init')) {
73
+ foreach (array('init', 'main', 'finish') as $op) {
74
+ $this->jobList[] = $scanType . '_' . $op;
75
+ };
76
+ } else if (method_exists($this, 'scan_' . $scanType)) {
77
  $this->jobList[] = $scanType;
78
  }
79
  }
125
  while(sizeof($this->jobList) > 0){
126
  self::checkForKill();
127
  $jobName = $this->jobList[0];
128
+ $callback = array($this, 'scan_' . $jobName);
129
+ if (is_callable($callback)) {
130
+ call_user_func($callback);
131
+ }
132
  array_shift($this->jobList); //only shift once we're done because we may pause halfway through a job and need to pick up where we left off
133
  self::checkForKill();
134
  if($this->forkRequested){
816
  $host = strtolower($matches[1]);
817
  $this->status(2, 'info', "Starting DNS scan for $host");
818
 
819
+ $cnameArrRec = @dns_get_record($host, DNS_CNAME);
820
  $cnameArr = array();
821
  $cnamesWeMustTrack = array();
822
+ if ($cnameArrRec) {
823
+ foreach($cnameArrRec as $elem){
824
+ $this->status(2, 'info', "Scanning CNAME DNS record for " . $elem['host']);
825
+ if($elem['host'] == $host){
826
+ $cnameArr[] = $elem;
827
+ $cnamesWeMustTrack[] = $elem['target'];
828
+ }
829
+ }
830
  }
831
+
832
  function wfAnonFunc1($a){ return $a['host'] . ' points to ' . $a['target']; }
833
  $cnameArr = array_map('wfAnonFunc1', $cnameArr);
834
  sort($cnameArr, SORT_STRING);
lib/wordfenceClass.php CHANGED
@@ -328,8 +328,12 @@ class wordfence {
328
  $db->queryWriteIgnoreError("alter table $prefix"."wfLockedOut modify column blockedTime bigint signed NOT NULL");
329
  $db->queryWriteIgnoreError("drop table if exists $prefix"."wfFileQueue");
330
  $db->queryWriteIgnoreError("drop table if exists $prefix"."wfFileChanges");
331
- //Adding primary key to this table because some backup apps use primary key during backup.
332
- $db->queryWriteIgnoreError("alter table {$prefix}wfStatus add id bigint UNSIGNED NOT NULL auto_increment PRIMARY KEY");
 
 
 
 
333
 
334
  $optScanEnabled = $db->querySingle("select val from $prefix"."wfConfig where name='scansEnabled_options'");
335
  if($optScanEnabled != '0' && $optScanEnabled != '1'){
@@ -387,6 +391,15 @@ class wordfence {
387
  ))");
388
  }
389
 
 
 
 
 
 
 
 
 
 
390
  //Must be the final line
391
  }
392
  private static function doEarlyAccessLogging(){
@@ -504,8 +517,7 @@ class wordfence {
504
  add_filter('registration_errors', 'wordfence::registrationFilter', 99, 3);
505
 
506
  // Change GoDaddy's limit login mu-plugin since it can interfere with the two factor auth message.
507
- if (defined('GD_SYSTEM_PLUGIN_DIR') && file_exists(GD_SYSTEM_PLUGIN_DIR . 'limit-login-attempts/limit-login-attempts.php')
508
- && defined('LIMIT_LOGIN_DIRECT_ADDR')) {
509
  add_action('login_errors', array('wordfence', 'fixGDLimitLoginsErrors'), 11);
510
  }
511
 
@@ -584,7 +596,7 @@ class wordfence {
584
  $isCrawler = false;
585
  if($UA){
586
  $b = $browscap->getBrowser($UA);
587
- if($b['Crawler']){
588
  $isCrawler = true;
589
  }
590
  }
@@ -878,18 +890,25 @@ class wordfence {
878
  //Do nothing and allow user to sign in. Their passwd has already been modified to be the passwd without the code.
879
  } else if($_POST['wordfence_authFactor'] == $t[2]){
880
  $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
881
- $codeResult = $api->call('twoFactor_verification', array(), array('phone' => $t[1]) );
882
- if(isset($codeResult['notPaid']) && $codeResult['notPaid']){
883
- break; //Let them sign in without two factor
884
- }
885
- if(isset($codeResult['ok']) && $codeResult['ok']){
886
- $t[2] = $codeResult['code'];
887
- $t[4] = time() + 1800; //30 minutes until code expires
888
- wfConfig::set_ser('twoFactorUsers', $twoFactorUsers); //save the code the user needs to enter and return an error.
889
- self::$authError = new WP_Error('twofactor_required', __('<strong>CODE EXPIRED. CHECK YOUR PHONE:</strong> The code you entered has expired. Codes are only valid for 30 minutes for security reasons. We have sent you a new code. Please sign in using your username and your password followed by a space and the new code we sent you.'));
890
- return self::$authError;
891
- } else {
892
- break; //No new code was received. Let them sign in with the expired code.
 
 
 
 
 
 
 
893
  }
894
  } else { //Bad code, so cancel the login and return an error to user.
895
  self::$authError = new WP_Error( 'twofactor_required', __( '<strong>INVALID CODE</strong>: You need to enter your password followed by a space and the code we sent to your phone. The code should start with \'wf\' and should be four characters. e.g. wfAB12. In this case you would enter your password as: \'mypassword wfAB12\' without quotes.'));
@@ -901,15 +920,35 @@ class wordfence {
901
  foreach($twoFactorUsers as &$t){
902
  if($t[0] == $userDat->ID && $t[3] == 'activated'){ //Yup, enabled, so lets send the code
903
  $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
904
- $codeResult = $api->call('twoFactor_verification', array(), array('phone' => $t[1]) );
905
- if(isset($codeResult['notPaid']) && $codeResult['notPaid']){
906
- break; //Let them sign in without two factor if their API key has expired or they're not paid and for some reason they have this set up.
 
 
 
 
 
907
  }
908
-
909
  if(isset($codeResult['ok']) && $codeResult['ok']){
910
  $t[2] = $codeResult['code'];
911
  $t[4] = time() + 1800; //30 minutes until code expires
912
  wfConfig::set_ser('twoFactorUsers', $twoFactorUsers); //save the code the user needs to enter and return an error.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
913
  self::$authError = new WP_Error( 'twofactor_required', __( '<strong>CHECK YOUR PHONE</strong>: A code has been sent to your phone and will arrive within 30 seconds. Please sign in again and add a space and the code to the end of your password.' ) );
914
  return self::$authError;
915
  } else { //oops, our API returned an error.
@@ -3282,6 +3321,18 @@ EOL;
3282
  }
3283
  }
3284
 
 
 
 
 
 
 
 
 
 
 
 
 
3285
  public static function fixGDLimitLoginsErrors($content) {
3286
  if (self::$authError) {
3287
  $content = str_replace(__('<strong>ERROR</strong>: Incorrect username or password.', 'limit-login-attempts') . "<br />\n", '', $content);
328
  $db->queryWriteIgnoreError("alter table $prefix"."wfLockedOut modify column blockedTime bigint signed NOT NULL");
329
  $db->queryWriteIgnoreError("drop table if exists $prefix"."wfFileQueue");
330
  $db->queryWriteIgnoreError("drop table if exists $prefix"."wfFileChanges");
331
+
332
+ $result = $wpdb->get_row("SHOW FIELDS FROM {$prefix}wfStatus where field = 'id'");
333
+ if (!$result || strtolower($result->Key) != 'pri') {
334
+ //Adding primary key to this table because some backup apps use primary key during backup.
335
+ $db->queryWriteIgnoreError("alter table {$prefix}wfStatus add id bigint UNSIGNED NOT NULL auto_increment PRIMARY KEY");
336
+ }
337
 
338
  $optScanEnabled = $db->querySingle("select val from $prefix"."wfConfig where name='scansEnabled_options'");
339
  if($optScanEnabled != '0' && $optScanEnabled != '1'){
391
  ))");
392
  }
393
 
394
+ // Fix the data in the country column.
395
+ // TODO: add version check so this doesn't run on every update.
396
+ $ip_results = $wpdb->get_results("SELECT * FROM `{$prefix}wfBlockedIPLog` GROUP BY IP");
397
+ if ($ip_results) {
398
+ foreach ($ip_results as $ip_row) {
399
+ $wpdb->query($wpdb->prepare("UPDATE `{$prefix}wfBlockedIPLog` SET countryCode = %s WHERE IP = %s", wfUtils::IP2Country(wfUtils::inet_ntop($ip_row->IP)), $ip_row->IP));
400
+ }
401
+ }
402
+
403
  //Must be the final line
404
  }
405
  private static function doEarlyAccessLogging(){
517
  add_filter('registration_errors', 'wordfence::registrationFilter', 99, 3);
518
 
519
  // Change GoDaddy's limit login mu-plugin since it can interfere with the two factor auth message.
520
+ if (self::hasGDLimitLoginsMUPlugin()) {
 
521
  add_action('login_errors', array('wordfence', 'fixGDLimitLoginsErrors'), 11);
522
  }
523
 
596
  $isCrawler = false;
597
  if($UA){
598
  $b = $browscap->getBrowser($UA);
599
+ if(!empty($b['Crawler'])){
600
  $isCrawler = true;
601
  }
602
  }
890
  //Do nothing and allow user to sign in. Their passwd has already been modified to be the passwd without the code.
891
  } else if($_POST['wordfence_authFactor'] == $t[2]){
892
  $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
893
+ try {
894
+ $codeResult = $api->call('twoFactor_verification', array(), array('phone' => $t[1]) );
895
+
896
+ if(isset($codeResult['notPaid']) && $codeResult['notPaid']){
897
+ break; //Let them sign in without two factor
898
+ }
899
+ if(isset($codeResult['ok']) && $codeResult['ok']){
900
+ $t[2] = $codeResult['code'];
901
+ $t[4] = time() + 1800; //30 minutes until code expires
902
+ wfConfig::set_ser('twoFactorUsers', $twoFactorUsers); //save the code the user needs to enter and return an error.
903
+ self::$authError = new WP_Error('twofactor_required', __('<strong>CODE EXPIRED. CHECK YOUR PHONE:</strong> The code you entered has expired. Codes are only valid for 30 minutes for security reasons. We have sent you a new code. Please sign in using your username and your password followed by a space and the new code we sent you.'));
904
+ return self::$authError;
905
+ } else {
906
+ break; //No new code was received. Let them sign in with the expired code.
907
+ }
908
+
909
+ } catch (Exception $e) {
910
+ // Couldn't connect to noc1, let them sign in since the password was correct.
911
+ break;
912
  }
913
  } else { //Bad code, so cancel the login and return an error to user.
914
  self::$authError = new WP_Error( 'twofactor_required', __( '<strong>INVALID CODE</strong>: You need to enter your password followed by a space and the code we sent to your phone. The code should start with \'wf\' and should be four characters. e.g. wfAB12. In this case you would enter your password as: \'mypassword wfAB12\' without quotes.'));
920
  foreach($twoFactorUsers as &$t){
921
  if($t[0] == $userDat->ID && $t[3] == 'activated'){ //Yup, enabled, so lets send the code
922
  $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
923
+ try {
924
+ $codeResult = $api->call('twoFactor_verification', array(), array('phone' => $t[1]) );
925
+ if(isset($codeResult['notPaid']) && $codeResult['notPaid']){
926
+ break; //Let them sign in without two factor if their API key has expired or they're not paid and for some reason they have this set up.
927
+ }
928
+ } catch (Exception $e) {
929
+ // Couldn't connect to noc1, let them sign in since the password was correct.
930
+ break;
931
  }
 
932
  if(isset($codeResult['ok']) && $codeResult['ok']){
933
  $t[2] = $codeResult['code'];
934
  $t[4] = time() + 1800; //30 minutes until code expires
935
  wfConfig::set_ser('twoFactorUsers', $twoFactorUsers); //save the code the user needs to enter and return an error.
936
+
937
+ if (self::hasGDLimitLoginsMUPlugin() && function_exists('limit_login_get_address')) {
938
+ $retries = get_option('limit_login_retries', array());
939
+ $ip = limit_login_get_address();
940
+
941
+ if (!is_array($retries)) {
942
+ $retries = array();
943
+ }
944
+ if (isset($retries[$ip]) && is_int($retries[$ip])) {
945
+ $retries[$ip]--;
946
+ } else {
947
+ $retries[$ip] = 0;
948
+ }
949
+ update_option('limit_login_retries', $retries);
950
+ }
951
+
952
  self::$authError = new WP_Error( 'twofactor_required', __( '<strong>CHECK YOUR PHONE</strong>: A code has been sent to your phone and will arrive within 30 seconds. Please sign in again and add a space and the code to the end of your password.' ) );
953
  return self::$authError;
954
  } else { //oops, our API returned an error.
3321
  }
3322
  }
3323
 
3324
+ /**
3325
+ * @return bool
3326
+ */
3327
+ public static function hasGDLimitLoginsMUPlugin() {
3328
+ return defined('GD_SYSTEM_PLUGIN_DIR') && file_exists(GD_SYSTEM_PLUGIN_DIR . 'limit-login-attempts/limit-login-attempts.php')
3329
+ && defined('LIMIT_LOGIN_DIRECT_ADDR');
3330
+ }
3331
+
3332
+ /**
3333
+ * @param string $content
3334
+ * @return string
3335
+ */
3336
  public static function fixGDLimitLoginsErrors($content) {
3337
  if (self::$authError) {
3338
  $content = str_replace(__('<strong>ERROR</strong>: Incorrect username or password.', 'limit-login-attempts') . "<br />\n", '', $content);
readme.txt CHANGED
@@ -3,7 +3,7 @@ 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, woocommerce support, woocommerce caching, IPv6, IP version 6
4
  Requires at least: 3.9
5
  Tested up to: 4.2.2
6
- Stable tag: 6.0.5
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
 
@@ -172,6 +172,17 @@ fully compatible with both IPv4 and IPv6 whether you run both or only one addres
172
 
173
  == Changelog ==
174
 
 
 
 
 
 
 
 
 
 
 
 
175
  = 6.0.5 =
176
  * Fix: Removed anonymous function to ensure PHP 5.2 compatability.
177
 
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, woocommerce support, woocommerce caching, IPv6, IP version 6
4
  Requires at least: 3.9
5
  Tested up to: 4.2.2
6
+ Stable tag: 6.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
 
172
 
173
  == Changelog ==
174
 
175
+ = 6.0.6 =
176
+ * Improvement: Handled uncaught exception when noc1 is not available in 2FA.
177
+ * Improvement: Fixed issue with limit-logins mu-plugin on GoDaddy counting first login attempt in 2FA against total allowed login attempts.
178
+ * Fix: Fixed bug with IPs not resolving to countries when printable IP passed to logBlockedIP.
179
+ * Fix: Fixed issue with free users country blocking redirects working after downgrade.
180
+ * Fix: Encoded URL field in country blocking options.
181
+ * Fix: Added a check to verify field has not already been altered prior to calling ALTER in runInstall.
182
+ * Fix: Fixed issue with scan_options method being called after method has been removed.
183
+ * Fix: Fixed bug in scan when dns_get_record fails and error condition was not handled.
184
+ * Fix: Fixed PHP notice when 'Crawler' not included in browser pcap result.
185
+
186
  = 6.0.5 =
187
  * Fix: Removed anonymous function to ensure PHP 5.2 compatability.
188
 
views/reports/activity-report-email-inline.php CHANGED
@@ -119,10 +119,10 @@ h6 a:visited { color: purple !important; }
119
  <div style="float: right; text-align: right; line-height: 1.1; color: #666666; font-size: 100%; vertical-align: baseline; margin: 20px 0 0; padding: 0; border: 0;" align="right">
120
  <?php echo $title ?>
121
  </div>
122
- <a href="http://www.wordfence.com/" style="font-size: 100%; vertical-align: baseline; outline: none; color: orange; text-decoration: none; margin: 0; padding: 0; border: 0;"><img src="http://www.wordfence.com/wp-content/themes/parallelus-salutation/wfCustomHome/images/wordfenceLogo.png" alt="" style="font-size: 100%; vertical-align: baseline; -ms-interpolation-mode: bicubic; outline: none; text-decoration: none; margin: 0; padding: 0; border: 0 none;" /></a>
123
 
124
  <p style="font-size: 100%; vertical-align: baseline; margin: 1em 0; padding: 0; border: 0;">
125
- This email was sent from your website <a href="<?php echo site_url() ?>"><?php echo site_url() ?></a> and is a summary of security related activity that Wordfence monitors for the period <?php printf('%s to %s', $report_start, $report_end) ?>. <?php if (!wfConfig::get('isPaid')): ?>NOTE: You are using the free version of Wordfence and are missing out on features like cellphone sign-in, country blocking and detecting if your site IP is sending spam. <a href="http://www.wordfence.com/?utm_source=plugin&utm_medium=UI&utm_campaign=summaryEmail">Click here to upgrade to Wordfence Premium now</a>.<?php endif ?>
126
  </p>
127
 
128
  <h2 style="font-size: 20px; vertical-align: baseline; clear: both; color: #222 !important; margin: 20px 0 4px; padding: 0; border: 0;">
119
  <div style="float: right; text-align: right; line-height: 1.1; color: #666666; font-size: 100%; vertical-align: baseline; margin: 20px 0 0; padding: 0; border: 0;" align="right">
120
  <?php echo $title ?>
121
  </div>
122
+ <a href="http://www.wordfence.com/zz5/" style="font-size: 100%; vertical-align: baseline; outline: none; color: orange; text-decoration: none; margin: 0; padding: 0; border: 0;"><img src="http://www.wordfence.com/wp-content/themes/parallelus-salutation/wfCustomHome/images/wordfenceLogo.png" alt="" style="font-size: 100%; vertical-align: baseline; -ms-interpolation-mode: bicubic; outline: none; text-decoration: none; margin: 0; padding: 0; border: 0 none;" /></a>
123
 
124
  <p style="font-size: 100%; vertical-align: baseline; margin: 1em 0; padding: 0; border: 0;">
125
+ This email was sent from your website <a href="<?php echo site_url() ?>"><?php echo site_url() ?></a> and is a summary of security related activity that Wordfence monitors for the period <?php printf('%s to %s', $report_start, $report_end) ?>. <?php if (!wfConfig::get('isPaid')): ?>NOTE: You are using the free version of Wordfence and are missing out on features like cellphone sign-in, country blocking and detecting if your site IP is sending spam. <a href="http://www.wordfence.com/zz6/">Click here to upgrade to Wordfence Premium now</a>.<?php endif ?>
126
  </p>
127
 
128
  <h2 style="font-size: 20px; vertical-align: baseline; clear: both; color: #222 !important; margin: 20px 0 4px; padding: 0; border: 0;">
views/reports/activity-report-email.php CHANGED
@@ -295,7 +295,7 @@ $title = 'Wordfence Activity for the week of ' . date_i18n(get_option('date_form
295
  <div style="float: right;text-align: right;line-height:1.1;color: #666666;margin:20px 0 0;">
296
  Activity for week of<br> <strong><?php echo date_i18n(get_option('date_format')) ?></strong>
297
  </div>
298
- <a href="http://www.wordfence.com/"><img src="http://www.wordfence.com/wp-content/themes/parallelus-salutation/wfCustomHome/images/wordfenceLogo.png" alt=""/></a>
299
 
300
  <h2>Top 10 IP's Blocked</h2>
301
 
295
  <div style="float: right;text-align: right;line-height:1.1;color: #666666;margin:20px 0 0;">
296
  Activity for week of<br> <strong><?php echo date_i18n(get_option('date_format')) ?></strong>
297
  </div>
298
+ <a href="http://www.wordfence.com/zz7/"><img src="http://www.wordfence.com/wp-content/themes/parallelus-salutation/wfCustomHome/images/wordfenceLogo.png" alt=""/></a>
299
 
300
  <h2>Top 10 IP's Blocked</h2>
301
 
views/reports/activity-report.php CHANGED
@@ -3,7 +3,7 @@
3
  * @var wfActivityReportView $this
4
  */
5
  ?>
6
- <a href="//www.wordfence.com/"><img src="//www.wordfence.com/wp-content/themes/parallelus-salutation/wfCustomHome/images/wordfenceLogo.png" alt=""/></a>
7
 
8
  <h2>Top <?php echo (int) $limit; ?> IP's Blocked</h2>
9
 
3
  * @var wfActivityReportView $this
4
  */
5
  ?>
6
+ <a href="//www.wordfence.com/zz8/"><img src="//www.wordfence.com/wp-content/themes/parallelus-salutation/wfCustomHome/images/wordfenceLogo.png" alt=""/></a>
7
 
8
  <h2>Top <?php echo (int) $limit; ?> IP's Blocked</h2>
9
 
wordfence.php CHANGED
@@ -4,13 +4,13 @@ Plugin Name: Wordfence Security
4
  Plugin URI: http://www.wordfence.com/
5
  Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
6
  Author: Wordfence
7
- Version: 6.0.5
8
  Author URI: http://www.wordfence.com/
9
  */
10
  if(defined('WP_INSTALLING') && WP_INSTALLING){
11
  return;
12
  }
13
- define('WORDFENCE_VERSION', '6.0.5');
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
  }
4
  Plugin URI: http://www.wordfence.com/
5
  Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
6
  Author: Wordfence
7
+ Version: 6.0.6
8
  Author URI: http://www.wordfence.com/
9
  */
10
  if(defined('WP_INSTALLING') && WP_INSTALLING){
11
  return;
12
  }
13
+ define('WORDFENCE_VERSION', '6.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
  }