Wordfence Security – Firewall & Malware Scan - Version 3.2.3

Version Description

  • Improved country blocking to make bulk adding/deleting of countries much easier.
  • Fixed bug that caused Google feed fetcher and other Google UA bots to get blocked if blocking of unverified Googlebots was enabled.
  • Fixed issue where Locked out users were shown having the same expiry time as Blocked IP's.
  • Fixed issue where Locked out users were not shown in the locked out list, but were still locked out if Blocked IP and Locked out expiry was different.
  • Improved performance of whitelisting so if whitelisted, all rules are bypassed.
  • Fixed issue that caused twentyten and twentyeleven themes to be shown as missing core files if they have been removed and theme scanning is enabled.
  • Fixed issue that made it impossible to end the tour for Firefox users.
Download this release

Release Info

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

Code changes from version 3.2.1 to 3.2.3

js/admin.js CHANGED
@@ -31,6 +31,8 @@ window['wordfenceAdmin'] = {
31
  ownCountry: "",
32
  schedStartHour: false,
33
  currentPointer: false,
 
 
34
  init: function(){
35
  this.nonce = WordfenceAdminVars.firstNonce;
36
  this.debugOn = WordfenceAdminVars.debugOn == '1' ? true : false;
@@ -86,7 +88,6 @@ window['wordfenceAdmin'] = {
86
  } else if(jQuery('#wordfenceMode_countryBlocking').length > 0){
87
  this.mode = 'countryBlocking';
88
  startTicker = false;
89
- this.drawBlockedCountries();
90
  if(! this.tourClosed){
91
  var self = this;
92
  this.tour('wfWelcomeContentCntBlk', 'wfHeading', 'top', 'left', "Learn how to Schedule Scans", function(){ self.tourRedir('WordfenceScanSchedule'); });
@@ -134,7 +135,8 @@ window['wordfenceAdmin'] = {
134
  buttons: function(event, t){
135
  var buttonElem = jQuery('<div id="wfTourButCont"><a id="pointer-close" style="margin-left:5px" class="button-secondary">End the Tour</a></div><div><a id="wfRateLink" href="http://wordpress.org/extend/plugins/wordfence/" target="_blank" style="font-size: 10px; font-family: Verdana;">Help spread the word by rating us 5&#9733; on WordPress.org</a></div>');
136
  buttonElem.find('#pointer-close').bind('click.pointer', function (evtObj) {
137
- if(evtObj.srcElement.id == 'wfRateLink'){
 
138
  return true;
139
  }
140
  self.tourFinish();
@@ -948,78 +950,46 @@ window['wordfenceAdmin'] = {
948
  setOwnCountry: function(code){
949
  this.ownCountry = (code + "").toUpperCase();
950
  },
951
- addBlockedCountry: function(code, name){
952
- code = (code + "").toUpperCase();
953
- if(code == this.ownCountry){
954
- this.colorbox('400px', "Please confirm blocking yourself", "You are about to block your own country. This could lead to you being locked out. Please make sure that your user profile on this machine has a current and valid email address and make sure you know what it is. That way if you are locked out, you can send yourself an unlock email. If you're sure you want to block your own country, click 'Confirm' below, otherwise click 'Cancel'.<br />" +
955
- '<input type="button" name="but1" value="Confirm" onclick="jQuery.colorbox.close(); WFAD.addBlockedCountryConfirm(\'' + code + '\',\'' + name + '\');" />&nbsp;<input type="button" name="but1" value="Cancel" onclick="jQuery.colorbox.close();" />');
956
- } else {
957
- this.addBlockedCountryConfirm(code, name);
958
- }
959
- },
960
- addBlockedCountryConfirm: function(code, name){
961
- var exists = false;
962
- for(var i = 0; i < this.blockedCountriesPending.length; i++){
963
- if(this.blockedCountriesPending[i][0] == code){
964
- return;
965
- }
966
- }
967
- this.blockedCountriesPending.push([code, name]);
968
- this.drawBlockedCountries();
969
- },
970
  loadBlockedCountries: function(str){
971
  var codes = str.split(',');
972
- var self = this;
973
- jQuery("#wfBlockedCountry > option").each(function() {
974
- for(var i = 0; i < codes.length; i++){
975
- if(codes[i] == this.value){
976
- self.addBlockedCountryConfirm(this.value, this.text);
977
- }
978
- }
979
- });
980
- this.drawBlockedCountries();
981
  },
982
- drawBlockedCountries: function(){
983
- var html = "";
984
- var self = this;
985
- if(this.blockedCountriesPending.length < 1){
986
- jQuery('#wfCountryList').html('<span style="color: #999;">There are no countries currently blocked.</span>');
987
  return;
988
  }
989
- jQuery("#wfBlockedCountry > option").each(function() {
990
- for(var i = 0; i < self.blockedCountriesPending.length; i++){
991
- if(self.blockedCountriesPending[i][0] == this.value){
992
- html += "Blocking: " + this.text + '&nbsp;&nbsp;<a href="#" onclick="WFAD.removeBlockedCountry(\'' + this.value + '\'); return false;">[remove]</a><br />';
 
 
 
 
 
993
  }
994
  }
995
  });
996
- jQuery('#wfCountryList').html(html);
997
-
998
- },
999
- removeBlockedCountry: function(code){
1000
- var newArr = [];
1001
- for(var i = 0; i < this.blockedCountriesPending.length; i++){
1002
- if(this.blockedCountriesPending[i][0] != code){
1003
- newArr.push(this.blockedCountriesPending[i]);
1004
- }
1005
  }
1006
- this.blockedCountriesPending = newArr;
1007
- this.drawBlockedCountries();
1008
  },
1009
- saveCountryBlocking: function(){
1010
  var action = jQuery('#wfBlockAction').val();
1011
  var redirURL = jQuery('#wfRedirURL').val();
1012
- if(action == 'redir' && (! /^https?:\/\/[^\/]+/i.test(redirURL))){
1013
- this.colorbox('400px', "Please enter a URL for redirection", "You have chosen to redirect blocked countries to a specific page. You need to enter a URL in the text box provided that starts with http:// or https://");
1014
- return;
1015
- }
1016
  var loggedInBlocked = jQuery('#wfLoggedInBlocked').is(':checked') ? '1' : '0';
1017
  var loginFormBlocked = jQuery('#wfLoginFormBlocked').is(':checked') ? '1' : '0';
1018
- var codesArr = [];
1019
- for(var i = 0; i < this.blockedCountriesPending.length; i++){
1020
- codesArr.push(this.blockedCountriesPending[i][0]);
1021
- }
1022
- var codes = codesArr.join(',');
1023
  jQuery('.wfAjax24').show();
1024
  var self = this;
1025
  this.ajax('wordfence_saveCountryBlocking', {
@@ -1027,7 +997,7 @@ window['wordfenceAdmin'] = {
1027
  redirURL: redirURL,
1028
  loggedInBlocked: loggedInBlocked,
1029
  loginFormBlocked: loginFormBlocked,
1030
- codes: codes
1031
  }, function(res){
1032
  jQuery('.wfAjax24').hide();
1033
  self.pulse('.wfSavedMsg');
@@ -1116,6 +1086,7 @@ window['wordfenceAdmin'] = {
1116
  self.pulse('.wfSaveMsg');
1117
  });
1118
  }
 
1119
  };
1120
  window['WFAD'] = window['wordfenceAdmin'];
1121
  }
31
  ownCountry: "",
32
  schedStartHour: false,
33
  currentPointer: false,
34
+ countryMap: false,
35
+ countryCodesToSave: "",
36
  init: function(){
37
  this.nonce = WordfenceAdminVars.firstNonce;
38
  this.debugOn = WordfenceAdminVars.debugOn == '1' ? true : false;
88
  } else if(jQuery('#wordfenceMode_countryBlocking').length > 0){
89
  this.mode = 'countryBlocking';
90
  startTicker = false;
 
91
  if(! this.tourClosed){
92
  var self = this;
93
  this.tour('wfWelcomeContentCntBlk', 'wfHeading', 'top', 'left', "Learn how to Schedule Scans", function(){ self.tourRedir('WordfenceScanSchedule'); });
135
  buttons: function(event, t){
136
  var buttonElem = jQuery('<div id="wfTourButCont"><a id="pointer-close" style="margin-left:5px" class="button-secondary">End the Tour</a></div><div><a id="wfRateLink" href="http://wordpress.org/extend/plugins/wordfence/" target="_blank" style="font-size: 10px; font-family: Verdana;">Help spread the word by rating us 5&#9733; on WordPress.org</a></div>');
137
  buttonElem.find('#pointer-close').bind('click.pointer', function (evtObj) {
138
+ var evtSourceElem = evtObj.srcElement ? evtObj.srcElement : evtObj.target;
139
+ if(evtSourceElem.id == 'wfRateLink'){
140
  return true;
141
  }
142
  self.tourFinish();
950
  setOwnCountry: function(code){
951
  this.ownCountry = (code + "").toUpperCase();
952
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
953
  loadBlockedCountries: function(str){
954
  var codes = str.split(',');
955
+ for(var i = 0; i < codes.length; i++){
956
+ jQuery('#wfCountryCheckbox_' + codes[i]).prop('checked', true);
957
+ }
 
 
 
 
 
 
958
  },
959
+ saveCountryBlocking: function(){
960
+ var action = jQuery('#wfBlockAction').val();
961
+ var redirURL = jQuery('#wfRedirURL').val();
962
+ if(action == 'redir' && (! /^https?:\/\/[^\/]+/i.test(redirURL))){
963
+ this.colorbox('400px', "Please enter a URL for redirection", "You have chosen to redirect blocked countries to a specific page. You need to enter a URL in the text box provided that starts with http:// or https://");
964
  return;
965
  }
966
+ var codesArr = [];
967
+ var ownCountryBlocked = false;
968
+ var self = this;
969
+ jQuery('.wfCountryCheckbox').each(function(idx, elem){
970
+ if(jQuery(elem).is(':checked')){
971
+ var code = jQuery(elem).val();
972
+ codesArr.push(code);
973
+ if(code == self.ownCountry){
974
+ ownCountryBlocked = true;
975
  }
976
  }
977
  });
978
+ var codes = codesArr.join(',');
979
+ this.countryCodesToSave = codes;
980
+ if(ownCountryBlocked){
981
+ this.colorbox('400px', "Please confirm blocking yourself", "You are about to block your own country. This could lead to you being locked out. Please make sure that your user profile on this machine has a current and valid email address and make sure you know what it is. That way if you are locked out, you can send yourself an unlock email. If you're sure you want to block your own country, click 'Confirm' below, otherwise click 'Cancel'.<br />" +
982
+ '<input type="button" name="but1" value="Confirm" onclick="jQuery.colorbox.close(); WFAD.confirmSaveCountryBlocking();" />&nbsp;<input type="button" name="but1" value="Cancel" onclick="jQuery.colorbox.close();" />');
983
+ } else {
984
+ this.confirmSaveCountryBlocking();
 
 
985
  }
 
 
986
  },
987
+ confirmSaveCountryBlocking: function(){
988
  var action = jQuery('#wfBlockAction').val();
989
  var redirURL = jQuery('#wfRedirURL').val();
 
 
 
 
990
  var loggedInBlocked = jQuery('#wfLoggedInBlocked').is(':checked') ? '1' : '0';
991
  var loginFormBlocked = jQuery('#wfLoginFormBlocked').is(':checked') ? '1' : '0';
992
+
 
 
 
 
993
  jQuery('.wfAjax24').show();
994
  var self = this;
995
  this.ajax('wordfence_saveCountryBlocking', {
997
  redirURL: redirURL,
998
  loggedInBlocked: loggedInBlocked,
999
  loginFormBlocked: loginFormBlocked,
1000
+ codes: this.countryCodesToSave
1001
  }, function(res){
1002
  jQuery('.wfAjax24').hide();
1003
  self.pulse('.wfSavedMsg');
1086
  self.pulse('.wfSaveMsg');
1087
  });
1088
  }
1089
+
1090
  };
1091
  window['WFAD'] = window['wordfenceAdmin'];
1092
  }
lib/menu_countryBlocking.php CHANGED
@@ -1,3 +1,9 @@
 
 
 
 
 
 
1
  <div class="wordfenceModeElem" id="wordfenceMode_countryBlocking"></div>
2
  <div class="wrap" id="paidWrap">
3
  <div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2 id="wfHeading">Block specific countries from accessing your site</h2>
@@ -13,32 +19,40 @@
13
  <tr><th>URL to redirect blocked users to:</th><td><input type="text" id="wfRedirURL" value="<?php if(wfConfig::get('cbl_redirURL')){ echo htmlspecialchars(wfConfig::get('cbl_redirURL')); } ?>" /></td></tr>
14
  <tr><th>Block countries even if they are logged in:</th><td><input type="checkbox" id="wfLoggedInBlocked" value="1" <?php if(wfConfig::get('cbl_loggedInBlocked')){ echo 'checked'; } ?> /></td></tr>
15
  <tr><th>Block access to the login form too:</th><td><input type="checkbox" id="wfLoginFormBlocked" value="1" <?php if(wfConfig::get('cbl_loginFormBlocked')){ echo 'checked'; } ?> /></td></tr>
16
- <tr><td colspan="2" style="padding-top: 10px;" >
17
- <h2>Select which countries to block</h2>
18
- </td></tr>
19
- <tr><th>Select individual countries to block and hit "Add":</th><td><select name="country" id="wfBlockedCountry">
20
- <?php require('wfCountrySelect.php'); ?>
21
- </select><input type="button" name="but3" class="button-primary" value="Add Country" onclick="var cVal = jQuery('#wfBlockedCountry').val(); WFAD.addBlockedCountry(cVal, jQuery('#wfBlockedCountry option[value=\'' + cVal + '\']').text());" /></td></tr>
22
- <tr><td colspan="2">
23
- <div id="wfCountryList" style="width: 350px; height: 200px; border: 1px solid #999; padding: 5px; margin: 5px; overflow: auto;">
24
- </div>
25
- <b>Changes to the country list will only take effect once you hit the save button below.</b>
26
- </td></tr>
27
- <tr><td colspan="2">
28
- <table border="0" cellpadding="0" cellspacing="0"><tr>
29
- <td><input type="button" name="but4" class="button-primary" value="Save blocking options and country list" onclick="WFAD.saveCountryBlocking();" /></td>
30
- <td style="height: 24px;"><div class="wfAjax24"></div><span class="wfSavedMsg">&nbsp;Your changes have been saved!</span></td></tr></table>
31
- </td></tr>
 
 
 
 
 
 
 
 
32
  </table>
33
  <span style="font-size: 10px;">Note that we use an IP to country database that is 99.5% accurate to identify which country a visitor is from.</span>
34
  </div>
35
  </div>
36
  <script type="text/javascript">
37
- WFAD.setOwnCountry('<?php echo wfUtils::IP2Country(wfUtils::getIP()); ?>');
38
  <?php
39
  if(wfConfig::get('cbl_countries')){
40
  ?>
41
- WFAD.loadBlockedCountries('<?php echo wfConfig::get('cbl_countries'); ?>');
42
  <?php
43
  }
44
  ?>
1
+ <?php
2
+ require('wfBulkCountries.php');
3
+ ?>
4
+ <script type="text/javascript">
5
+ WFAD.countryMap = <?php echo json_encode($wfBulkCountries); ?>;
6
+ </script>
7
  <div class="wordfenceModeElem" id="wordfenceMode_countryBlocking"></div>
8
  <div class="wrap" id="paidWrap">
9
  <div class="wordfence-lock-icon wordfence-icon32"><br /></div><h2 id="wfHeading">Block specific countries from accessing your site</h2>
19
  <tr><th>URL to redirect blocked users to:</th><td><input type="text" id="wfRedirURL" value="<?php if(wfConfig::get('cbl_redirURL')){ echo htmlspecialchars(wfConfig::get('cbl_redirURL')); } ?>" /></td></tr>
20
  <tr><th>Block countries even if they are logged in:</th><td><input type="checkbox" id="wfLoggedInBlocked" value="1" <?php if(wfConfig::get('cbl_loggedInBlocked')){ echo 'checked'; } ?> /></td></tr>
21
  <tr><th>Block access to the login form too:</th><td><input type="checkbox" id="wfLoginFormBlocked" value="1" <?php if(wfConfig::get('cbl_loginFormBlocked')){ echo 'checked'; } ?> /></td></tr>
22
+ </table>
23
+ <h2>Select which countries to block</h2>
24
+ <div id="wfBulkBlockingContainer" style="margin-bottom: 10px;">
25
+ <a href="#" onclick="jQuery('.wfCountryCheckbox').prop('checked', true); return false;">Select All</a>&nbsp;&nbsp;
26
+ <a href="#" onclick="jQuery('.wfCountryCheckbox').prop('checked', false); return false;">Deselect All</a>&nbsp;&nbsp;
27
+ <table border="0" cellpadding="0" cellspacing="0">
28
+ <tr>
29
+ <?php
30
+ $counter = 0;
31
+ asort($wfBulkCountries);
32
+ foreach($wfBulkCountries as $code => $name){
33
+ echo '<td style=""><input class="wfCountryCheckbox" id="wfCountryCheckbox_' . $code . '" type="checkbox" value="' . $code . '" />&nbsp;' . $name . '&nbsp;&nbsp;&nbsp;</td>';
34
+ $counter++;
35
+ if($counter % 5 == 0){
36
+ echo "</tr><tr>\n";
37
+ }
38
+ }
39
+ ?>
40
+ </tr>
41
+ </table>
42
+ </div>
43
+ <table border="0" cellpadding="0" cellspacing="0"><tr>
44
+ <td><input type="button" name="but4" class="button-primary" value="Save blocking options and country list" onclick="WFAD.saveCountryBlocking();" /></td>
45
+ <td style="height: 24px;"><div class="wfAjax24"></div><span class="wfSavedMsg">&nbsp;Your changes have been saved!</span></td></tr>
46
  </table>
47
  <span style="font-size: 10px;">Note that we use an IP to country database that is 99.5% accurate to identify which country a visitor is from.</span>
48
  </div>
49
  </div>
50
  <script type="text/javascript">
51
+ jQuery(function(){ WFAD.setOwnCountry('<?php echo wfUtils::IP2Country(wfUtils::getIP()); ?>'); });
52
  <?php
53
  if(wfConfig::get('cbl_countries')){
54
  ?>
55
+ jQuery(function(){ WFAD.loadBlockedCountries('<?php echo wfConfig::get('cbl_countries'); ?>'); });
56
  <?php
57
  }
58
  ?>
lib/wfBulkCountries.php ADDED
@@ -0,0 +1,253 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $wfBulkCountries = array(
3
+ "AD" => "Andorra",
4
+ "AE" => "United Arab Emirates",
5
+ "AF" => "Afghanistan",
6
+ "AG" => "Antigua and Barbuda",
7
+ "AI" => "Anguilla",
8
+ "AL" => "Albania",
9
+ "AM" => "Armenia",
10
+ "AO" => "Angola",
11
+ "AQ" => "Antarctica",
12
+ "AR" => "Argentina",
13
+ "AS" => "American Samoa",
14
+ "AT" => "Austria",
15
+ "AU" => "Australia",
16
+ "AW" => "Aruba",
17
+ "AX" => "Aland Islands",
18
+ "AZ" => "Azerbaijan",
19
+ "BA" => "Bosnia and Herzegovina",
20
+ "BB" => "Barbados",
21
+ "BD" => "Bangladesh",
22
+ "BE" => "Belgium",
23
+ "BF" => "Burkina Faso",
24
+ "BG" => "Bulgaria",
25
+ "BH" => "Bahrain",
26
+ "BI" => "Burundi",
27
+ "BJ" => "Benin",
28
+ "BL" => "Saint Bartelemey",
29
+ "BM" => "Bermuda",
30
+ "BN" => "Brunei Darussalam",
31
+ "BO" => "Bolivia",
32
+ "BQ" => "Bonaire, Saint Eustatius and Saba",
33
+ "BR" => "Brazil",
34
+ "BS" => "Bahamas",
35
+ "BT" => "Bhutan",
36
+ "BV" => "Bouvet Island",
37
+ "BW" => "Botswana",
38
+ "BY" => "Belarus",
39
+ "BZ" => "Belize",
40
+ "CA" => "Canada",
41
+ "CC" => "Cocos (Keeling) Islands",
42
+ "CD" => "Congo, The Democratic Republic of the",
43
+ "CF" => "Central African Republic",
44
+ "CG" => "Congo",
45
+ "CH" => "Switzerland",
46
+ "CI" => "Cote dIvoire",
47
+ "CK" => "Cook Islands",
48
+ "CL" => "Chile",
49
+ "CM" => "Cameroon",
50
+ "CN" => "China",
51
+ "CO" => "Colombia",
52
+ "CR" => "Costa Rica",
53
+ "CU" => "Cuba",
54
+ "CV" => "Cape Verde",
55
+ "CW" => "Curacao",
56
+ "CX" => "Christmas Island",
57
+ "CY" => "Cyprus",
58
+ "CZ" => "Czech Republic",
59
+ "DE" => "Germany",
60
+ "DJ" => "Djibouti",
61
+ "DK" => "Denmark",
62
+ "DM" => "Dominica",
63
+ "DO" => "Dominican Republic",
64
+ "DZ" => "Algeria",
65
+ "EC" => "Ecuador",
66
+ "EE" => "Estonia",
67
+ "EG" => "Egypt",
68
+ "EH" => "Western Sahara",
69
+ "ER" => "Eritrea",
70
+ "ES" => "Spain",
71
+ "ET" => "Ethiopia",
72
+ "EU" => "Europe",
73
+ "FI" => "Finland",
74
+ "FJ" => "Fiji",
75
+ "FK" => "Falkland Islands (Malvinas)",
76
+ "FM" => "Micronesia, Federated States of",
77
+ "FO" => "Faroe Islands",
78
+ "FR" => "France",
79
+ "GA" => "Gabon",
80
+ "GB" => "United Kingdom",
81
+ "GD" => "Grenada",
82
+ "GE" => "Georgia",
83
+ "GF" => "French Guiana",
84
+ "GG" => "Guernsey",
85
+ "GH" => "Ghana",
86
+ "GI" => "Gibraltar",
87
+ "GL" => "Greenland",
88
+ "GM" => "Gambia",
89
+ "GN" => "Guinea",
90
+ "GP" => "Guadeloupe",
91
+ "GQ" => "Equatorial Guinea",
92
+ "GR" => "Greece",
93
+ "GS" => "South Georgia and the South Sandwich Islands",
94
+ "GT" => "Guatemala",
95
+ "GU" => "Guam",
96
+ "GW" => "Guinea-Bissau",
97
+ "GY" => "Guyana",
98
+ "HK" => "Hong Kong",
99
+ "HM" => "Heard Island and McDonald Islands",
100
+ "HN" => "Honduras",
101
+ "HR" => "Croatia",
102
+ "HT" => "Haiti",
103
+ "HU" => "Hungary",
104
+ "ID" => "Indonesia",
105
+ "IE" => "Ireland",
106
+ "IL" => "Israel",
107
+ "IM" => "Isle of Man",
108
+ "IN" => "India",
109
+ "IO" => "British Indian Ocean Territory",
110
+ "IQ" => "Iraq",
111
+ "IR" => "Iran, Islamic Republic of",
112
+ "IS" => "Iceland",
113
+ "IT" => "Italy",
114
+ "JE" => "Jersey",
115
+ "JM" => "Jamaica",
116
+ "JO" => "Jordan",
117
+ "JP" => "Japan",
118
+ "KE" => "Kenya",
119
+ "KG" => "Kyrgyzstan",
120
+ "KH" => "Cambodia",
121
+ "KI" => "Kiribati",
122
+ "KM" => "Comoros",
123
+ "KN" => "Saint Kitts and Nevis",
124
+ "KP" => "Korea, Democratic Peoples Republic of",
125
+ "KR" => "Korea, Republic of",
126
+ "KW" => "Kuwait",
127
+ "KY" => "Cayman Islands",
128
+ "KZ" => "Kazakhstan",
129
+ "LA" => "Lao Peoples Democratic Republic",
130
+ "LB" => "Lebanon",
131
+ "LC" => "Saint Lucia",
132
+ "LI" => "Liechtenstein",
133
+ "LK" => "Sri Lanka",
134
+ "LR" => "Liberia",
135
+ "LS" => "Lesotho",
136
+ "LT" => "Lithuania",
137
+ "LU" => "Luxembourg",
138
+ "LV" => "Latvia",
139
+ "LY" => "Libyan Arab Jamahiriya",
140
+ "MA" => "Morocco",
141
+ "MC" => "Monaco",
142
+ "MD" => "Moldova, Republic of",
143
+ "ME" => "Montenegro",
144
+ "MF" => "Saint Martin",
145
+ "MG" => "Madagascar",
146
+ "MH" => "Marshall Islands",
147
+ "MK" => "Macedonia",
148
+ "ML" => "Mali",
149
+ "MM" => "Myanmar",
150
+ "MN" => "Mongolia",
151
+ "MO" => "Macao",
152
+ "MP" => "Northern Mariana Islands",
153
+ "MQ" => "Martinique",
154
+ "MR" => "Mauritania",
155
+ "MS" => "Montserrat",
156
+ "MT" => "Malta",
157
+ "MU" => "Mauritius",
158
+ "MV" => "Maldives",
159
+ "MW" => "Malawi",
160
+ "MX" => "Mexico",
161
+ "MY" => "Malaysia",
162
+ "MZ" => "Mozambique",
163
+ "NA" => "Namibia",
164
+ "NC" => "New Caledonia",
165
+ "NE" => "Niger",
166
+ "NF" => "Norfolk Island",
167
+ "NG" => "Nigeria",
168
+ "NI" => "Nicaragua",
169
+ "NL" => "Netherlands",
170
+ "NO" => "Norway",
171
+ "NP" => "Nepal",
172
+ "NR" => "Nauru",
173
+ "NU" => "Niue",
174
+ "NZ" => "New Zealand",
175
+ "OM" => "Oman",
176
+ "PA" => "Panama",
177
+ "PE" => "Peru",
178
+ "PF" => "French Polynesia",
179
+ "PG" => "Papua New Guinea",
180
+ "PH" => "Philippines",
181
+ "PK" => "Pakistan",
182
+ "PL" => "Poland",
183
+ "PM" => "Saint Pierre and Miquelon",
184
+ "PN" => "Pitcairn",
185
+ "PR" => "Puerto Rico",
186
+ "PS" => "Palestinian Territory",
187
+ "PT" => "Portugal",
188
+ "PW" => "Palau",
189
+ "PY" => "Paraguay",
190
+ "QA" => "Qatar",
191
+ "RE" => "Reunion",
192
+ "RO" => "Romania",
193
+ "RS" => "Serbia",
194
+ "RU" => "Russian Federation",
195
+ "RW" => "Rwanda",
196
+ "SA" => "Saudi Arabia",
197
+ "SB" => "Solomon Islands",
198
+ "SC" => "Seychelles",
199
+ "SD" => "Sudan",
200
+ "SE" => "Sweden",
201
+ "SG" => "Singapore",
202
+ "SH" => "Saint Helena",
203
+ "SI" => "Slovenia",
204
+ "SJ" => "Svalbard and Jan Mayen",
205
+ "SK" => "Slovakia",
206
+ "SL" => "Sierra Leone",
207
+ "SM" => "San Marino",
208
+ "SN" => "Senegal",
209
+ "SO" => "Somalia",
210
+ "SR" => "Suriname",
211
+ "ST" => "Sao Tome and Principe",
212
+ "SV" => "El Salvador",
213
+ "SX" => "Sint Maarten",
214
+ "SY" => "Syrian Arab Republic",
215
+ "SZ" => "Swaziland",
216
+ "TC" => "Turks and Caicos Islands",
217
+ "TD" => "Chad",
218
+ "TF" => "French Southern Territories",
219
+ "TG" => "Togo",
220
+ "TH" => "Thailand",
221
+ "TJ" => "Tajikistan",
222
+ "TK" => "Tokelau",
223
+ "TL" => "Timor-Leste",
224
+ "TM" => "Turkmenistan",
225
+ "TN" => "Tunisia",
226
+ "TO" => "Tonga",
227
+ "TR" => "Turkey",
228
+ "TT" => "Trinidad and Tobago",
229
+ "TV" => "Tuvalu",
230
+ "TW" => "Taiwan",
231
+ "TZ" => "Tanzania, United Republic of",
232
+ "UA" => "Ukraine",
233
+ "UG" => "Uganda",
234
+ "UM" => "United States Minor Outlying Islands",
235
+ "US" => "United States",
236
+ "UY" => "Uruguay",
237
+ "UZ" => "Uzbekistan",
238
+ "VA" => "Holy See (Vatican City State)",
239
+ "VC" => "Saint Vincent and the Grenadines",
240
+ "VE" => "Venezuela",
241
+ "VG" => "Virgin Islands, British",
242
+ "VI" => "Virgin Islands, U.S.",
243
+ "VN" => "Vietnam",
244
+ "VU" => "Vanuatu",
245
+ "WF" => "Wallis and Futuna",
246
+ "WS" => "Samoa",
247
+ "YE" => "Yemen",
248
+ "YT" => "Mayotte",
249
+ "ZA" => "South Africa",
250
+ "ZM" => "Zambia",
251
+ "ZW" => "Zimbabwe"
252
+ );
253
+ ?>
lib/wfCountrySelect.php DELETED
@@ -1,256 +0,0 @@
1
- <option value="AD">Andorra</option>
2
- <option value="AE">United Arab Emirates</option>
3
- <option value="AF">Afghanistan</option>
4
- <option value="AG">Antigua and Barbuda</option>
5
- <option value="AI">Anguilla</option>
6
- <option value="AL">Albania</option>
7
- <option value="AM">Armenia</option>
8
- <option value="AO">Angola</option>
9
- <?php // <option value="AP">Asia/Pacific Region</option>
10
- ?>
11
- <option value="AQ">Antarctica</option>
12
- <option value="AR">Argentina</option>
13
- <option value="AS">American Samoa</option>
14
- <option value="AT">Austria</option>
15
- <option value="AU">Australia</option>
16
- <option value="AW">Aruba</option>
17
- <option value="AX">Aland Islands</option>
18
- <option value="AZ">Azerbaijan</option>
19
- <option value="BA">Bosnia and Herzegovina</option>
20
- <option value="BB">Barbados</option>
21
- <option value="BD">Bangladesh</option>
22
- <option value="BE">Belgium</option>
23
- <option value="BF">Burkina Faso</option>
24
- <option value="BG">Bulgaria</option>
25
- <option value="BH">Bahrain</option>
26
- <option value="BI">Burundi</option>
27
- <option value="BJ">Benin</option>
28
- <option value="BL">Saint Bartelemey</option>
29
- <option value="BM">Bermuda</option>
30
- <option value="BN">Brunei Darussalam</option>
31
- <option value="BO">Bolivia</option>
32
- <option value="BQ">Bonaire, Saint Eustatius and Saba</option>
33
- <option value="BR">Brazil</option>
34
- <option value="BS">Bahamas</option>
35
- <option value="BT">Bhutan</option>
36
- <option value="BV">Bouvet Island</option>
37
- <option value="BW">Botswana</option>
38
- <option value="BY">Belarus</option>
39
- <option value="BZ">Belize</option>
40
- <option value="CA">Canada</option>
41
- <option value="CC">Cocos (Keeling) Islands</option>
42
- <option value="CD">Congo, The Democratic Republic of the</option>
43
- <option value="CF">Central African Republic</option>
44
- <option value="CG">Congo</option>
45
- <option value="CH">Switzerland</option>
46
- <option value="CI">Cote dIvoire</option>
47
- <option value="CK">Cook Islands</option>
48
- <option value="CL">Chile</option>
49
- <option value="CM">Cameroon</option>
50
- <option value="CN">China</option>
51
- <option value="CO">Colombia</option>
52
- <option value="CR">Costa Rica</option>
53
- <option value="CU">Cuba</option>
54
- <option value="CV">Cape Verde</option>
55
- <option value="CW">Curacao</option>
56
- <option value="CX">Christmas Island</option>
57
- <option value="CY">Cyprus</option>
58
- <option value="CZ">Czech Republic</option>
59
- <option value="DE">Germany</option>
60
- <option value="DJ">Djibouti</option>
61
- <option value="DK">Denmark</option>
62
- <option value="DM">Dominica</option>
63
- <option value="DO">Dominican Republic</option>
64
- <option value="DZ">Algeria</option>
65
- <option value="EC">Ecuador</option>
66
- <option value="EE">Estonia</option>
67
- <option value="EG">Egypt</option>
68
- <option value="EH">Western Sahara</option>
69
- <option value="ER">Eritrea</option>
70
- <option value="ES">Spain</option>
71
- <option value="ET">Ethiopia</option>
72
- <option value="EU">Europe</option>
73
- <option value="FI">Finland</option>
74
- <option value="FJ">Fiji</option>
75
- <option value="FK">Falkland Islands (Malvinas)</option>
76
- <option value="FM">Micronesia, Federated States of</option>
77
- <option value="FO">Faroe Islands</option>
78
- <option value="FR">France</option>
79
- <option value="GA">Gabon</option>
80
- <option value="GB">United Kingdom</option>
81
- <option value="GD">Grenada</option>
82
- <option value="GE">Georgia</option>
83
- <option value="GF">French Guiana</option>
84
- <option value="GG">Guernsey</option>
85
- <option value="GH">Ghana</option>
86
- <option value="GI">Gibraltar</option>
87
- <option value="GL">Greenland</option>
88
- <option value="GM">Gambia</option>
89
- <option value="GN">Guinea</option>
90
- <option value="GP">Guadeloupe</option>
91
- <option value="GQ">Equatorial Guinea</option>
92
- <option value="GR">Greece</option>
93
- <option value="GS">South Georgia and the South Sandwich Islands</option>
94
- <option value="GT">Guatemala</option>
95
- <option value="GU">Guam</option>
96
- <option value="GW">Guinea-Bissau</option>
97
- <option value="GY">Guyana</option>
98
- <option value="HK">Hong Kong</option>
99
- <option value="HM">Heard Island and McDonald Islands</option>
100
- <option value="HN">Honduras</option>
101
- <option value="HR">Croatia</option>
102
- <option value="HT">Haiti</option>
103
- <option value="HU">Hungary</option>
104
- <option value="ID">Indonesia</option>
105
- <option value="IE">Ireland</option>
106
- <option value="IL">Israel</option>
107
- <option value="IM">Isle of Man</option>
108
- <option value="IN">India</option>
109
- <option value="IO">British Indian Ocean Territory</option>
110
- <option value="IQ">Iraq</option>
111
- <option value="IR">Iran, Islamic Republic of</option>
112
- <option value="IS">Iceland</option>
113
- <option value="IT">Italy</option>
114
- <option value="JE">Jersey</option>
115
- <option value="JM">Jamaica</option>
116
- <option value="JO">Jordan</option>
117
- <option value="JP">Japan</option>
118
- <option value="KE">Kenya</option>
119
- <option value="KG">Kyrgyzstan</option>
120
- <option value="KH">Cambodia</option>
121
- <option value="KI">Kiribati</option>
122
- <option value="KM">Comoros</option>
123
- <option value="KN">Saint Kitts and Nevis</option>
124
- <option value="KP">Korea, Democratic Peoples Republic of</option>
125
- <option value="KR">Korea, Republic of</option>
126
- <option value="KW">Kuwait</option>
127
- <option value="KY">Cayman Islands</option>
128
- <option value="KZ">Kazakhstan</option>
129
- <option value="LA">Lao Peoples Democratic Republic</option>
130
- <option value="LB">Lebanon</option>
131
- <option value="LC">Saint Lucia</option>
132
- <option value="LI">Liechtenstein</option>
133
- <option value="LK">Sri Lanka</option>
134
- <option value="LR">Liberia</option>
135
- <option value="LS">Lesotho</option>
136
- <option value="LT">Lithuania</option>
137
- <option value="LU">Luxembourg</option>
138
- <option value="LV">Latvia</option>
139
- <option value="LY">Libyan Arab Jamahiriya</option>
140
- <option value="MA">Morocco</option>
141
- <option value="MC">Monaco</option>
142
- <option value="MD">Moldova, Republic of</option>
143
- <option value="ME">Montenegro</option>
144
- <option value="MF">Saint Martin</option>
145
- <option value="MG">Madagascar</option>
146
- <option value="MH">Marshall Islands</option>
147
- <option value="MK">Macedonia</option>
148
- <option value="ML">Mali</option>
149
- <option value="MM">Myanmar</option>
150
- <option value="MN">Mongolia</option>
151
- <option value="MO">Macao</option>
152
- <option value="MP">Northern Mariana Islands</option>
153
- <option value="MQ">Martinique</option>
154
- <option value="MR">Mauritania</option>
155
- <option value="MS">Montserrat</option>
156
- <option value="MT">Malta</option>
157
- <option value="MU">Mauritius</option>
158
- <option value="MV">Maldives</option>
159
- <option value="MW">Malawi</option>
160
- <option value="MX">Mexico</option>
161
- <option value="MY">Malaysia</option>
162
- <option value="MZ">Mozambique</option>
163
- <option value="NA">Namibia</option>
164
- <option value="NC">New Caledonia</option>
165
- <option value="NE">Niger</option>
166
- <option value="NF">Norfolk Island</option>
167
- <option value="NG">Nigeria</option>
168
- <option value="NI">Nicaragua</option>
169
- <option value="NL">Netherlands</option>
170
- <option value="NO">Norway</option>
171
- <option value="NP">Nepal</option>
172
- <option value="NR">Nauru</option>
173
- <option value="NU">Niue</option>
174
- <option value="NZ">New Zealand</option>
175
- <option value="OM">Oman</option>
176
- <option value="PA">Panama</option>
177
- <option value="PE">Peru</option>
178
- <option value="PF">French Polynesia</option>
179
- <option value="PG">Papua New Guinea</option>
180
- <option value="PH">Philippines</option>
181
- <option value="PK">Pakistan</option>
182
- <option value="PL">Poland</option>
183
- <option value="PM">Saint Pierre and Miquelon</option>
184
- <option value="PN">Pitcairn</option>
185
- <option value="PR">Puerto Rico</option>
186
- <option value="PS">Palestinian Territory</option>
187
- <option value="PT">Portugal</option>
188
- <option value="PW">Palau</option>
189
- <option value="PY">Paraguay</option>
190
- <option value="QA">Qatar</option>
191
- <option value="RE">Reunion</option>
192
- <option value="RO">Romania</option>
193
- <option value="RS">Serbia</option>
194
- <option value="RU">Russian Federation</option>
195
- <option value="RW">Rwanda</option>
196
- <option value="SA">Saudi Arabia</option>
197
- <option value="SB">Solomon Islands</option>
198
- <option value="SC">Seychelles</option>
199
- <option value="SD">Sudan</option>
200
- <option value="SE">Sweden</option>
201
- <option value="SG">Singapore</option>
202
- <option value="SH">Saint Helena</option>
203
- <option value="SI">Slovenia</option>
204
- <option value="SJ">Svalbard and Jan Mayen</option>
205
- <option value="SK">Slovakia</option>
206
- <option value="SL">Sierra Leone</option>
207
- <option value="SM">San Marino</option>
208
- <option value="SN">Senegal</option>
209
- <option value="SO">Somalia</option>
210
- <option value="SR">Suriname</option>
211
- <option value="ST">Sao Tome and Principe</option>
212
- <option value="SV">El Salvador</option>
213
- <option value="SX">Sint Maarten</option>
214
- <option value="SY">Syrian Arab Republic</option>
215
- <option value="SZ">Swaziland</option>
216
- <option value="TC">Turks and Caicos Islands</option>
217
- <option value="TD">Chad</option>
218
- <option value="TF">French Southern Territories</option>
219
- <option value="TG">Togo</option>
220
- <option value="TH">Thailand</option>
221
- <option value="TJ">Tajikistan</option>
222
- <option value="TK">Tokelau</option>
223
- <option value="TL">Timor-Leste</option>
224
- <option value="TM">Turkmenistan</option>
225
- <option value="TN">Tunisia</option>
226
- <option value="TO">Tonga</option>
227
- <option value="TR">Turkey</option>
228
- <option value="TT">Trinidad and Tobago</option>
229
- <option value="TV">Tuvalu</option>
230
- <option value="TW">Taiwan</option>
231
- <option value="TZ">Tanzania, United Republic of</option>
232
- <option value="UA">Ukraine</option>
233
- <option value="UG">Uganda</option>
234
- <option value="UM">United States Minor Outlying Islands</option>
235
- <option value="US">United States</option>
236
- <option value="UY">Uruguay</option>
237
- <option value="UZ">Uzbekistan</option>
238
- <option value="VA">Holy See (Vatican City State)</option>
239
- <option value="VC">Saint Vincent and the Grenadines</option>
240
- <option value="VE">Venezuela</option>
241
- <option value="VG">Virgin Islands, British</option>
242
- <option value="VI">Virgin Islands, U.S.</option>
243
- <option value="VN">Vietnam</option>
244
- <option value="VU">Vanuatu</option>
245
- <option value="WF">Wallis and Futuna</option>
246
- <option value="WS">Samoa</option>
247
- <option value="YE">Yemen</option>
248
- <option value="YT">Mayotte</option>
249
- <option value="ZA">South Africa</option>
250
- <option value="ZM">Zambia</option>
251
- <option value="ZW">Zimbabwe</option>
252
- <?php /*
253
- <option value="A1">Anonymous Proxy</option>
254
- <option value="A2">Satellite Provider</option>
255
- <option value="O1">Other Country</option>
256
- */ ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/wfCrawl.php CHANGED
@@ -70,6 +70,13 @@ class wfCrawl {
70
  '@^msnbot/1\\.0.*$@',
71
  '@^msnbot/1\\.1.*$@'
72
  );
 
 
 
 
 
 
 
73
  public static function isGoogleCrawler(){
74
  $UA = $_SERVER['HTTP_USER_AGENT'];
75
  foreach(self::$googPat as $pat){
70
  '@^msnbot/1\\.0.*$@',
71
  '@^msnbot/1\\.1.*$@'
72
  );
73
+ public static function isGooglebot(){
74
+ $UA = $_SERVER['HTTP_USER_AGENT'];
75
+ if(preg_match('/Googlebot\/\d\.\d/', $UA)){ // UA: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html) or (rarely used): Googlebot/2.1 (+http://www.google.com/bot.html)
76
+ return true;
77
+ }
78
+ return false;
79
+ }
80
  public static function isGoogleCrawler(){
81
  $UA = $_SERVER['HTTP_USER_AGENT'];
82
  foreach(self::$googPat as $pat){
lib/wfLog.php CHANGED
@@ -50,6 +50,10 @@ class wfLog {
50
  return $pagename;
51
  }
52
  public function logLeechAndBlock($type){ //404 or hit
 
 
 
 
53
  if($type == '404'){
54
  $table = $this->scanTable;
55
  } else if($type == 'hit'){
@@ -58,12 +62,11 @@ class wfLog {
58
  wordfence::status(1, 'error', "Invalid type to logLeechAndBlock(): $type");
59
  return;
60
  }
61
- $IP = wfUtils::getIP();
62
  $this->getDB()->query("insert into $table (eMin, IP, hits) values (floor(unix_timestamp() / 60), %s, 1) ON DUPLICATE KEY update hits = IF(@wfcurrenthits := hits + 1, hits + 1, hits + 1)", wfUtils::inet_aton($IP));
63
  $hitsPerMinute = $this->getDB()->querySingle("select @wfcurrenthits");
64
  if(wfConfig::get('firewallEnabled')){
65
  if(wfConfig::get('blockFakeBots')){
66
- if(wfCrawl::isGoogleCrawler() && (! wfCrawl::verifyCrawlerPTR($this->googlePattern, $IP) )){
67
  wordfence::status(2, 'info', "Blocking fake Googlebot at IP $IP");
68
  $this->blockIP($IP, "Fake Google crawler automatically blocked");
69
  }
@@ -219,7 +222,7 @@ class wfLog {
219
  return $results;
220
  }
221
  public function getLockedOutIPs(){
222
- $res = $this->getDB()->query("select IP, unix_timestamp() - blockedTime as createdAgo, reason, unix_timestamp() - lastAttempt as lastAttemptAgo, lastAttempt, blockedHits, (blockedTime + %s) - unix_timestamp() as blockedFor from " . $this->lockOutTable . " where blockedTime + %s > unix_timestamp() order by blockedTime desc", wfConfig::get('blockedTime'), wfConfig::get('blockedTime'));
223
  $results = array();
224
  while($elem = mysql_fetch_assoc($res)){
225
  $elem['lastAttemptAgo'] = $elem['lastAttempt'] ? wfUtils::makeTimeAgo($elem['lastAttemptAgo']) : '';
@@ -573,11 +576,16 @@ class wfLog {
573
  } else if($nb == 'neverBlockUA' || $nb == 'neverBlockVerified'){
574
  if(wfCrawl::isGoogleCrawler()){ //Check the UA using regex
575
  if($nb == 'neverBlockVerified'){
576
- if(wfCrawl::verifyCrawlerPTR($this->googlePattern, wfUtils::getIP())){ //UA check passed, now verify using PTR if configured to
577
- self::$gbSafeCache[$cacheKey] = false; //This is a verified Google crawler, so no we can't block it
578
- } else {
579
- self::$gbSafeCache[$cacheKey] = true; //This is a crawler claiming to be Google but it did not verify
 
 
 
 
580
  }
 
581
  } else { //neverBlockUA
582
  self::$gbSafeCache[$cacheKey] = false; //User configured us to only do a UA check and this claims to be google so don't block
583
  }
50
  return $pagename;
51
  }
52
  public function logLeechAndBlock($type){ //404 or hit
53
+ $IP = wfUtils::getIP();
54
+ if($this->isWhitelisted($IP)){
55
+ return;
56
+ }
57
  if($type == '404'){
58
  $table = $this->scanTable;
59
  } else if($type == 'hit'){
62
  wordfence::status(1, 'error', "Invalid type to logLeechAndBlock(): $type");
63
  return;
64
  }
 
65
  $this->getDB()->query("insert into $table (eMin, IP, hits) values (floor(unix_timestamp() / 60), %s, 1) ON DUPLICATE KEY update hits = IF(@wfcurrenthits := hits + 1, hits + 1, hits + 1)", wfUtils::inet_aton($IP));
66
  $hitsPerMinute = $this->getDB()->querySingle("select @wfcurrenthits");
67
  if(wfConfig::get('firewallEnabled')){
68
  if(wfConfig::get('blockFakeBots')){
69
+ if(wfCrawl::isGooglebot() && (! wfCrawl::verifyCrawlerPTR($this->googlePattern, $IP) )){
70
  wordfence::status(2, 'info', "Blocking fake Googlebot at IP $IP");
71
  $this->blockIP($IP, "Fake Google crawler automatically blocked");
72
  }
222
  return $results;
223
  }
224
  public function getLockedOutIPs(){
225
+ $res = $this->getDB()->query("select IP, unix_timestamp() - blockedTime as createdAgo, reason, unix_timestamp() - lastAttempt as lastAttemptAgo, lastAttempt, blockedHits, (blockedTime + %s) - unix_timestamp() as blockedFor from " . $this->lockOutTable . " where blockedTime + %s > unix_timestamp() order by blockedTime desc", wfConfig::get('loginSec_lockoutMins'), wfConfig::get('loginSec_lockoutMins'));
226
  $results = array();
227
  while($elem = mysql_fetch_assoc($res)){
228
  $elem['lastAttemptAgo'] = $elem['lastAttempt'] ? wfUtils::makeTimeAgo($elem['lastAttemptAgo']) : '';
576
  } else if($nb == 'neverBlockUA' || $nb == 'neverBlockVerified'){
577
  if(wfCrawl::isGoogleCrawler()){ //Check the UA using regex
578
  if($nb == 'neverBlockVerified'){
579
+ if(wfCrawl::isGooglebot()){ //UA is the one, the only, the original Googlebot
580
+ if(wfCrawl::verifyCrawlerPTR($this->googlePattern, wfUtils::getIP())){ //UA check passed, now verify using PTR if configured to
581
+ self::$gbSafeCache[$cacheKey] = false; //This is a verified Google crawler, so no we can't block it
582
+ } else {
583
+ self::$gbSafeCache[$cacheKey] = true; //This is a crawler claiming to be Google but it did not verify
584
+ }
585
+ } else { //UA isGoogleCrawler, but is not Googlebot itself. E.g. feedreader, google-site-verification, etc.
586
+ self::$gbSafeCache[$cacheKey] = false; //This is a crawler with a google UA, but it's not Googlebot, so we don't block for safety. We can't verify these because they don't have a PTR record. e.g. Feedreader.
587
  }
588
+
589
  } else { //neverBlockUA
590
  self::$gbSafeCache[$cacheKey] = false; //User configured us to only do a UA check and this claims to be google so don't block
591
  }
lib/wordfenceClass.php CHANGED
@@ -94,7 +94,9 @@ class wordfence {
94
  for($i = 0; $i < $len; $i += 4){
95
  list($ipLong) = array_values(unpack('N', substr($resp['data'], $i, 4)));
96
  $IPStr = long2ip($ipLong);
97
- self::getLog()->blockIP($IPStr, $reason, true);
 
 
98
  }
99
  }
100
  }
@@ -225,6 +227,8 @@ class wordfence {
225
  $db->queryIgnoreError("alter table $prefix"."wfStatus modify column msg varchar(1000) NOT NULL");
226
  //3.1.2 to 3.1.4
227
  $db->queryIgnoreError("alter table $prefix"."wfBlocks modify column blockedTime bigint signed NOT NULL");
 
 
228
 
229
  //Must be the final line
230
  }
@@ -300,7 +304,11 @@ class wordfence {
300
  die(json_encode($returnArr));
301
  }
302
  public static function lostPasswordPost(){
303
- if(self::isLockedOut(wfUtils::getIP())){
 
 
 
 
304
  require('wfLockedOut.php');
305
  }
306
  $email = $_POST['user_login'];
@@ -308,11 +316,11 @@ class wordfence {
308
  $user = get_user_by('email', $_POST['user_login']);
309
  if($user){
310
  if(wfConfig::get('alertOn_lostPasswdForm')){
311
- wordfence::alert("Password recovery attempted", "Someone tried to recover the password for user with email address: $email", wfUtils::getIP());
312
  }
313
  }
314
  if(wfConfig::get('loginSecurityEnabled')){
315
- $tKey = 'wffgt_' . wfUtils::inet_aton(wfUtils::getIP());
316
  $forgotAttempts = get_transient($tKey);
317
  if($forgotAttempts){
318
  $forgotAttempts++;
@@ -320,7 +328,7 @@ class wordfence {
320
  $forgotAttempts = 1;
321
  }
322
  if($forgotAttempts >= wfConfig::get('loginSec_maxForgotPasswd')){
323
- self::lockOutIP(wfUtils::getIP(), "Exceeded the maximum number of tries to recover their password which is set at: " . wfConfig::get('loginSec_maxForgotPasswd'));
324
  require('wfLockedOut.php');
325
  }
326
  set_transient($tKey, $forgotAttempts, wfConfig::get('loginSec_countFailMins') * 60);
@@ -432,12 +440,16 @@ class wordfence {
432
  }
433
  }
434
  public static function authenticateFilter($authResult){
 
 
 
 
435
  if(wfConfig::get('loginSecurityEnabled')){
436
  if(is_wp_error($authResult) && $authResult->get_error_code() == 'invalid_username' && wfConfig::get('loginSec_lockInvalidUsers')){
437
- self::lockOutIP(wfUtils::getIP(), "Used an invalid username to try to sign in.");
438
  require('wfLockedOut.php');
439
  }
440
- $tKey = 'wflginfl_' . wfUtils::inet_aton(wfUtils::getIP());
441
  if(is_wp_error($authResult) && ($authResult->get_error_code() == 'invalid_username' || $authResult->get_error_code() == 'incorrect_password') ){
442
  $tries = get_transient($tKey);
443
  if($tries){
@@ -446,7 +458,7 @@ class wordfence {
446
  $tries = 1;
447
  }
448
  if($tries >= wfConfig::get('loginSec_maxFailures')){
449
- self::lockOutIP(wfUtils::getIP(), "Exceeded the maximum number of login failures which is: " . wfConfig::get('loginSec_maxFailures'));
450
  require('wfLockedOut.php');
451
  }
452
  set_transient($tKey, $tries, wfConfig::get('loginSec_countFailMins') * 60);
94
  for($i = 0; $i < $len; $i += 4){
95
  list($ipLong) = array_values(unpack('N', substr($resp['data'], $i, 4)));
96
  $IPStr = long2ip($ipLong);
97
+ if(! self::getLog()->isWhitelisted($IPStr)){
98
+ self::getLog()->blockIP($IPStr, $reason, true);
99
+ }
100
  }
101
  }
102
  }
227
  $db->queryIgnoreError("alter table $prefix"."wfStatus modify column msg varchar(1000) NOT NULL");
228
  //3.1.2 to 3.1.4
229
  $db->queryIgnoreError("alter table $prefix"."wfBlocks modify column blockedTime bigint signed NOT NULL");
230
+ //3.2.1 to 3.2.2
231
+ $db->queryIgnoreError("alter table $prefix"."wfLockedOut modify column blockedTime bigint signed NOT NULL");
232
 
233
  //Must be the final line
234
  }
304
  die(json_encode($returnArr));
305
  }
306
  public static function lostPasswordPost(){
307
+ $IP = wfUtils::getIP();
308
+ if(self::getLog()->isWhitelisted($IP)){
309
+ return;
310
+ }
311
+ if(self::isLockedOut($IP)){
312
  require('wfLockedOut.php');
313
  }
314
  $email = $_POST['user_login'];
316
  $user = get_user_by('email', $_POST['user_login']);
317
  if($user){
318
  if(wfConfig::get('alertOn_lostPasswdForm')){
319
+ wordfence::alert("Password recovery attempted", "Someone tried to recover the password for user with email address: $email", $IP);
320
  }
321
  }
322
  if(wfConfig::get('loginSecurityEnabled')){
323
+ $tKey = 'wffgt_' . wfUtils::inet_aton($IP);
324
  $forgotAttempts = get_transient($tKey);
325
  if($forgotAttempts){
326
  $forgotAttempts++;
328
  $forgotAttempts = 1;
329
  }
330
  if($forgotAttempts >= wfConfig::get('loginSec_maxForgotPasswd')){
331
+ self::lockOutIP($IP, "Exceeded the maximum number of tries to recover their password which is set at: " . wfConfig::get('loginSec_maxForgotPasswd'));
332
  require('wfLockedOut.php');
333
  }
334
  set_transient($tKey, $forgotAttempts, wfConfig::get('loginSec_countFailMins') * 60);
440
  }
441
  }
442
  public static function authenticateFilter($authResult){
443
+ $IP = wfUtils::getIP();
444
+ if(self::getLog()->isWhitelisted($IP)){
445
+ return $authResult;
446
+ }
447
  if(wfConfig::get('loginSecurityEnabled')){
448
  if(is_wp_error($authResult) && $authResult->get_error_code() == 'invalid_username' && wfConfig::get('loginSec_lockInvalidUsers')){
449
+ self::lockOutIP($IP, "Used an invalid username to try to sign in.");
450
  require('wfLockedOut.php');
451
  }
452
+ $tKey = 'wflginfl_' . wfUtils::inet_aton($IP);
453
  if(is_wp_error($authResult) && ($authResult->get_error_code() == 'invalid_username' || $authResult->get_error_code() == 'incorrect_password') ){
454
  $tries = get_transient($tKey);
455
  if($tries){
458
  $tries = 1;
459
  }
460
  if($tries >= wfConfig::get('loginSec_maxFailures')){
461
+ self::lockOutIP($IP, "Exceeded the maximum number of login failures which is: " . wfConfig::get('loginSec_maxFailures'));
462
  require('wfLockedOut.php');
463
  }
464
  set_transient($tKey, $tries, wfConfig::get('loginSec_countFailMins') * 60);
lib/wordfenceConstants.php CHANGED
@@ -1,5 +1,5 @@
1
  <?php
2
- define('WORDFENCE_API_VERSION', '2.0');
3
  define('WORDFENCE_API_URL_SEC', 'https://noc1.wordfence.com/');
4
  define('WORDFENCE_API_URL_NONSEC', 'http://noc1.wordfence.com/');
5
  define('WORDFENCE_MAX_SCAN_TIME', 600);
1
  <?php
2
+ define('WORDFENCE_API_VERSION', '2.1');
3
  define('WORDFENCE_API_URL_SEC', 'https://noc1.wordfence.com/');
4
  define('WORDFENCE_API_URL_NONSEC', 'http://noc1.wordfence.com/');
5
  define('WORDFENCE_MAX_SCAN_TIME', 600);
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
3
  Tags: wordpress, security, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure
4
  Requires at least: 3.3.1
5
  Tested up to: 3.4.1
6
- Stable tag: 3.2.1
7
 
8
  Wordfence Security is a free enterprise class security plugin that includes a firewall, virus scanning, real-time traffic with geolocation and more.
9
 
@@ -153,6 +153,15 @@ or a theme, because often these have been updated to fix a security hole.
153
  5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
154
 
155
  == Changelog ==
 
 
 
 
 
 
 
 
 
156
  = 3.2.1 =
157
  * Theme and plugin scanning is now free. Woohoo!
158
  * Added introductory tour for Wordfence.
3
  Tags: wordpress, security, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure
4
  Requires at least: 3.3.1
5
  Tested up to: 3.4.1
6
+ Stable tag: 3.2.3
7
 
8
  Wordfence Security is a free enterprise class security plugin that includes a firewall, virus scanning, real-time traffic with geolocation and more.
9
 
153
  5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
154
 
155
  == Changelog ==
156
+ = 3.2.3 =
157
+ * Improved country blocking to make bulk adding/deleting of countries much easier.
158
+ * Fixed bug that caused Google feed fetcher and other Google UA bots to get blocked if blocking of unverified Googlebots was enabled.
159
+ * Fixed issue where Locked out users were shown having the same expiry time as Blocked IP's.
160
+ * Fixed issue where Locked out users were not shown in the locked out list, but were still locked out if Blocked IP and Locked out expiry was different.
161
+ * Improved performance of whitelisting so if whitelisted, all rules are bypassed.
162
+ * Fixed issue that caused twentyten and twentyeleven themes to be shown as missing core files if they have been removed and theme scanning is enabled.
163
+ * Fixed issue that made it impossible to end the tour for Firefox users.
164
+
165
  = 3.2.1 =
166
  * Theme and plugin scanning is now free. Woohoo!
167
  * Added introductory tour for Wordfence.
wordfence.php CHANGED
@@ -4,10 +4,10 @@ Plugin Name: Wordfence Security
4
  Plugin URI: http://wordfence.com/
5
  Description: Wordfence Security - Anti-virus and Firewall security plugin for WordPress
6
  Author: Mark Maunder
7
- Version: 3.2.1
8
  Author URI: http://wordfence.com/
9
  */
10
- define('WORDFENCE_VERSION', '3.2.1');
11
  if(! defined('WORDFENCE_VERSIONONLY_MODE')){
12
  if((int) @ini_get('memory_limit') < 64){
13
  @ini_set('memory_limit', '64M'); //Some hosts have ini set at as little as 32 megs. 64 is the min sane amount of memory.
4
  Plugin URI: http://wordfence.com/
5
  Description: Wordfence Security - Anti-virus and Firewall security plugin for WordPress
6
  Author: Mark Maunder
7
+ Version: 3.2.3
8
  Author URI: http://wordfence.com/
9
  */
10
+ define('WORDFENCE_VERSION', '3.2.3');
11
  if(! defined('WORDFENCE_VERSIONONLY_MODE')){
12
  if((int) @ini_get('memory_limit') < 64){
13
  @ini_set('memory_limit', '64M'); //Some hosts have ini set at as little as 32 megs. 64 is the min sane amount of memory.