Wordfence Security – Firewall & Malware Scan - Version 6.2.7

Version Description

  • Improvement: WordPress 4.7 improvements for the Web Application Firewall.
  • Improvement: Updated signatures for hash-based malware detection.
  • Improvement: Automatically attempt to detect when a site is behind a proxy and has IP information in a different field.
  • Improvement: Added additional contextual help links.
  • Improvement: Significant performance improvement for determining the connecting IP.
  • Improvement: Better messaging for two-factor recovery codes.
  • Fix: Adjusted message when trying to block an IP in the whitelist.
  • Fix: Error log download links now work on Windows servers.
  • Fix: Avoid running out of memory when viewing very large activity logs.
  • Fix: Fixed warning that could be logged when following an unlock email link.
  • Fix: Tour popups on options page now scroll into view correctly.
Download this release

Release Info

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

Code changes from version 6.2.6 to 6.2.7

js/admin.js CHANGED
@@ -405,6 +405,10 @@
405
jQuery('#pointer-close').after('<a id="pointer-primary" class="button-primary">' + buttonLabel + '</a>');
406
jQuery('#pointer-primary').click(buttonCallback);
407
}
408
},
409
startTourAgain: function() {
410
var self = this;
@@ -1144,6 +1148,25 @@
1144
});
1145
}
1146
},
1147
fixFPD: function(issueID) {
1148
var self = this;
1149
var title = "Full Path Disclosure";
@@ -2237,9 +2260,10 @@
2237
2238
var message = "Scan the code below with your authenticator app to add this account. Some authenticator apps also allow you to type in the text version instead.<br><div id=\"wfTwoFactorQRCodeTable\"></div><br><strong>Key:</strong> <input type=\"text\" size=\"45\" value=\"" + res.base32Secret + "\" onclick=\"this.select();\" readonly>";
2239
if (res.recoveryCodes.length > 0) {
2240
- message = message + "<br><br><strong>Recovery Codes</strong><br><p>Use these codes to log in if you lose access to your authenticator device. Each one may be used only once.</p><ul id=\"wfTwoFactorRecoveryCodes\">";
2241
2242
var recoveryCodeFileContents = "Cellphone Sign-In Recovery Codes - " + res.homeurl + " (" + res.username + ")\r\n";
2243
var splitter = /.{4}/g;
2244
for (var i = 0; i < res.recoveryCodes.length; i++) {
2245
var code = res.recoveryCodes[i];
@@ -2268,9 +2292,10 @@
2268
self.twoFacStatus('User added! Check the user\'s phone to get the activation code.');
2269
2270
if (res.recoveryCodes.length > 0) {
2271
- var message = "<p>Use these codes to log in if you are unable to access your phone. Each one may be used only once.</p><ul id=\"wfTwoFactorRecoveryCodes\">";
2272
2273
var recoveryCodeFileContents = "Cellphone Sign-In Recovery Codes - " + res.homeurl + " (" + res.username + ")\r\n";
2274
var splitter = /.{4}/g;
2275
for (var i = 0; i < res.recoveryCodes.length; i++) {
2276
var code = res.recoveryCodes[i];
405
jQuery('#pointer-close').after('<a id="pointer-primary" class="button-primary">' + buttonLabel + '</a>');
406
jQuery('#pointer-primary').click(buttonCallback);
407
}
408
+
409
+ $('html, body').animate({
410
+ scrollTop: $('.wp-pointer').offset().top - 100
411
+ }, 1000);
412
},
413
startTourAgain: function() {
414
var self = this;
1148
});
1149
}
1150
},
1151
+ useRecommendedHowGetIPs: function(issueID) {
1152
+ var self = this;
1153
+ this.ajax('wordfence_misconfiguredHowGetIPsChoice', {
1154
+ issueID: issueID,
1155
+ choice: 'yes'
1156
+ }, function(res) {
1157
+ if (res.ok) {
1158
+ jQuery('#wordfenceMisconfiguredHowGetIPsNotice').fadeOut();
1159
+
1160
+ self.loadIssues(function() {
1161
+ self.colorbox('400px', "Success updating option", "The 'How does Wordfence get IPs' option was successfully updated to the recommended value.");
1162
+ });
1163
+ } else if (res.cerrorMsg) {
1164
+ self.loadIssues(function() {
1165
+ self.colorbox('400px', 'An error occurred', res.cerrorMsg);
1166
+ });
1167
+ }
1168
+ });
1169
+ },
1170
fixFPD: function(issueID) {
1171
var self = this;
1172
var title = "Full Path Disclosure";
2260
2261
var message = "Scan the code below with your authenticator app to add this account. Some authenticator apps also allow you to type in the text version instead.<br><div id=\"wfTwoFactorQRCodeTable\"></div><br><strong>Key:</strong> <input type=\"text\" size=\"45\" value=\"" + res.base32Secret + "\" onclick=\"this.select();\" readonly>";
2262
if (res.recoveryCodes.length > 0) {
2263
+ message = message + "<br><br><strong>Recovery Codes</strong><br><p>Use one of these " + res.recoveryCodes.length + " codes to log in if you lose access to your authenticator device. Codes are 16 characters long, plus optional spaces. Each one may be used only once.</p><ul id=\"wfTwoFactorRecoveryCodes\">";
2264
2265
var recoveryCodeFileContents = "Cellphone Sign-In Recovery Codes - " + res.homeurl + " (" + res.username + ")\r\n";
2266
+ recoveryCodeFileContents = recoveryCodeFileContents + "\r\nEach line of 16 letters and numbers is a single recovery code, with optional spaces for readability. When typing your password, enter \"wf\" followed by the entire code like \"mypassword wf1234 5678 90AB CDEF\". If your site shows a separate prompt for entering a code after entering only your username and password, enter only the code like \"1234 5678 90AB CDEF\". Your recovery codes are:\r\n\r\n";
2267
var splitter = /.{4}/g;
2268
for (var i = 0; i < res.recoveryCodes.length; i++) {
2269
var code = res.recoveryCodes[i];
2292
self.twoFacStatus('User added! Check the user\'s phone to get the activation code.');
2293
2294
if (res.recoveryCodes.length > 0) {
2295
+ var message = "<p>Use one of these " + res.recoveryCodes.length + " codes to log in if you are unable to access your phone. Codes are 16 characters long, plus optional spaces. Each one may be used only once.</p><ul id=\"wfTwoFactorRecoveryCodes\">";
2296
2297
var recoveryCodeFileContents = "Cellphone Sign-In Recovery Codes - " + res.homeurl + " (" + res.username + ")\r\n";
2298
+ recoveryCodeFileContents = recoveryCodeFileContents + "\r\nEach line of 16 letters and numbers is a single recovery code, with optional spaces for readability. When typing your password, enter \"wf\" followed by the entire code like \"mypassword wf1234 5678 90AB CDEF\". If your site shows a separate prompt for entering a code after entering only your username and password, enter only the code like \"1234 5678 90AB CDEF\". Your recovery codes are:\r\n\r\n";
2299
var splitter = /.{4}/g;
2300
for (var i = 0; i < res.recoveryCodes.length; i++) {
2301
var code = res.recoveryCodes[i];
js/tourTip.js CHANGED
@@ -49,6 +49,14 @@ window['wordfenceExt'] = {
49
function(){ jQuery('#wordfenceFalconDeprecationWarning').fadeOut(); }
50
);
51
},
52
removeFromCache: function(postID){
53
this.ajax('wordfence_removeFromCache', {
54
id: postID
49
function(){ jQuery('#wordfenceFalconDeprecationWarning').fadeOut(); }
50
);
51
},
52
+ misconfiguredHowGetIPsChoice : function(choice) {
53
+ this.ajax('wordfence_misconfiguredHowGetIPsChoice', {
54
+ choice: choice
55
+ },
56
+ function(res){ jQuery('#wordfenceMisconfiguredHowGetIPsNotice').fadeOut(); },
57
+ function(){ jQuery('#wordfenceMisconfiguredHowGetIPsNotice').fadeOut(); }
58
+ );
59
+ },
60
removeFromCache: function(postID){
61
this.ajax('wordfence_removeFromCache', {
62
id: postID
lib/menu_options.php CHANGED
@@ -439,6 +439,14 @@ $w = new wfConfig();
439
name="scansEnabled_public" value="1" DISABLED /></td>
440
</tr>
441
<?php } ?>
442
<tr>
443
<th>Scan for the HeartBleed vulnerability<a
444
href="http://docs.wordfence.com/en/Wordfence_options#Scan_for_the_HeartBleed_vulnerability"
@@ -625,7 +633,9 @@ $w = new wfConfig();
625
</td>
626
</tr>
627
<tr>
628
- <th>Limit the number of issues sent in the scan results email.</th>
629
<td>
630
<input type="text" name="scan_maxIssues" id="scan_maxIssues"
631
value="<?php $w->f( 'scan_maxIssues' ); ?>"/> 0 or empty means unlimited
439
name="scansEnabled_public" value="1" DISABLED /></td>
440
</tr>
441
<?php } ?>
442
+ <tr>
443
+ <th>Scan for misconfigured How does Wordfence get IPs<a
444
+ href="http://docs.wordfence.com/en/Wordfence_options#Scan_for_misconfigured_How_does_Wordfence_get_IPs"
445
+ target="_blank" class="wfhelp"></a></th>
446
+ <td><input type="checkbox" id="scansEnabled_checkHowGetIPs" class="wfConfigElem"
447
+ name="scansEnabled_checkHowGetIPs" value="1" <?php $w->cb( 'scansEnabled_checkHowGetIPs' ); ?> />
448
+ </td>
449
+ </tr>
450
<tr>
451
<th>Scan for the HeartBleed vulnerability<a
452
href="http://docs.wordfence.com/en/Wordfence_options#Scan_for_the_HeartBleed_vulnerability"
633
</td>
634
</tr>
635
<tr>
636
+ <th>Limit the number of issues sent in the scan results email.<a
637
+ href="https://docs.wordfence.com/en/Wordfence_options#Limit_the_number_of_issues_sent_in_the_scan_results_email"
638
+ target="_blank" class="wfhelp"></a></th>
639
<td>
640
<input type="text" name="scan_maxIssues" id="scan_maxIssues"
641
value="<?php $w->f( 'scan_maxIssues' ); ?>"/> 0 or empty means unlimited
lib/menu_scan.php CHANGED
@@ -1069,6 +1069,40 @@ $sigUpdateTime = wfConfig::get('signatureUpdateTime');
1069
</div>
1070
</div>
1071
</script>
1072
1073
<script type="text/x-jquery-template" id="issueTmpl_spamvertizeCheck">
1074
<div>
1069
</div>
1070
</div>
1071
</script>
1072
+ <script type="text/x-jquery-template" id="issueTmpl_checkHowGetIPs">
1073
+ <div>
1074
+ <div class="wfIssue">
1075
+ <h2>${shortMsg}</h2>
1076
+ <p>
1077
+ <table border="0" class="wfIssue" cellspacing="0" cellpadding="0">
1078
+ <tr><th>Issue first detected:</th><td>${timeAgo} ago.</td></tr>
1079
+ <tr><th>Severity:</th><td>{{if severity == '1'}}Critical{{else}}Warning{{/if}}</td></tr>
1080
+ <tr><th>Status</th><td>
1081
+ {{if status == 'new' }}New{{/if}}
1082
+ {{if status == 'ignoreC' }}This issue will be ignored until it changes.{{/if}}
1083
+ {{if status == 'ignoreP' }}This issue is permanently ignored.{{/if}}
1084
+ </td></tr>
1085
+ </table>
1086
+ </p>
1087
+ <p>
1088
+ {{html longMsg}}
1089
+ </p>
1090
+ <div class="wfIssueOptions">
1091
+ {{if status == 'new'}}
1092
+ <strong>Resolve:</strong>
1093
+ {{if ((typeof data.recommendation !== 'undefined') && data.recommendation)}}
1094
+ <a href="#" onclick="WFAD.useRecommendedHowGetIPs('${id}'); return false;">Use recommended value</a>
1095
+ {{/if}}
1096
+ <a href="#" onclick="WFAD.updateIssueStatus('${id}', 'delete'); return false;">I have fixed this issue</a>
1097
+ <a href="#" onclick="WFAD.updateIssueStatus('${id}', 'ignoreP'); return false;">Ignore this problem</a>
1098
+ {{/if}}
1099
+ {{if status == 'ignoreP' || status == 'ignoreC'}}
1100
+ <a href="#" onclick="WFAD.updateIssueStatus('${id}', 'delete'); return false;">Stop ignoring this issue</a>
1101
+ {{/if}}
1102
+ </div>
1103
+ </div>
1104
+ </div>
1105
+ </script>
1106
1107
<script type="text/x-jquery-template" id="issueTmpl_spamvertizeCheck">
1108
<div>
lib/menu_waf.php CHANGED
@@ -265,7 +265,9 @@ $wafRemoveURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=removeA
265
266
<p id="whitelist-monitor">
267
<strong>Monitor Background Requests for False Positives:</strong><br>
268
- <label><input type="checkbox" id="monitor-front" name="monitor-front" value="1"<?php echo wfConfig::get('ajaxWatcherDisabled_front') ? '' : ' checked'; ?>>Front</label> &nbsp; <label><input type="checkbox" id="monitor-admin" name="monitor-admin" value="1"<?php echo wfConfig::get('ajaxWatcherDisabled_admin') ? '' : ' checked'; ?>>Admin Panel</label>
269
</p>
270
<br>
271
@@ -273,7 +275,9 @@ $wafRemoveURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=removeA
273
274
<p id="waf-advanced-options">
275
<strong>Other Options</strong><br>
276
- <label><input type="checkbox" id="waf-disable-ip-blocking" name="waf-disable-ip-blocking" value="1"<?php echo $config->getConfig('disableWAFIPBlocking') ? ' checked' : ''; ?>>Delay IP and Country blocking until after WordPress and plugins have loaded (only process firewall rules early)</label>
277
</p>
278
279
<?php if (WFWAF_AUTO_PREPEND) : ?>
265
266
<p id="whitelist-monitor">
267
<strong>Monitor Background Requests for False Positives:</strong><br>
268
+ <label><input type="checkbox" id="monitor-front" name="monitor-front" value="1"<?php echo wfConfig::get('ajaxWatcherDisabled_front') ? '' : ' checked'; ?>>Front</label> &nbsp; <label><input type="checkbox" id="monitor-admin" name="monitor-admin" value="1"<?php echo wfConfig::get('ajaxWatcherDisabled_admin') ? '' : ' checked'; ?>>Admin Panel</label> <a
269
+ href="https://docs.wordfence.com/en/WAF#Whitelisted_URLs"
270
+ target="_blank" class="wfhelp"></a>
271
</p>
272
<br>
273
275
276
<p id="waf-advanced-options">
277
<strong>Other Options</strong><br>
278
+ <label><input type="checkbox" id="waf-disable-ip-blocking" name="waf-disable-ip-blocking" value="1"<?php echo $config->getConfig('disableWAFIPBlocking') ? ' checked' : ''; ?>>Delay IP and Country blocking until after WordPress and plugins have loaded (only process firewall rules early)</label> <a
279
+ href="https://docs.wordfence.com/en/WAF#Advanced_Configuration"
280
+ target="_blank" class="wfhelp"></a>
281
</p>
282
283
<?php if (WFWAF_AUTO_PREPEND) : ?>
lib/viewFullActivityLog.php CHANGED
@@ -13,12 +13,17 @@ $db = new wfDB();
13
global $wpdb;
14
$debugOn = wfConfig::get('debugOn', 0);
15
$table = $wpdb->base_prefix . 'wfStatus';
16
- $q = $db->querySelect("select ctime, level, type, msg from $table order by ctime desc");
17
$timeOffset = 3600 * get_option('gmt_offset');
18
- foreach($q as $r){
19
- if($r['level'] < 4 || $debugOn){
20
- echo '<div' . ($r['type'] == 'error' ? ' class="error"' : '') . '>[' . date('M d H:i:s', $r['ctime'] + $timeOffset) . ':' . $r['ctime'] . ':' . $r['level'] . ':' . $r['type'] . ']&nbsp;' . esc_html($r['msg']) . "</div>\n";
21
}
22
}
23
?>
24
</body>
13
global $wpdb;
14
$debugOn = wfConfig::get('debugOn', 0);
15
$table = $wpdb->base_prefix . 'wfStatus';
16
+ $offset = 0;
17
$timeOffset = 3600 * get_option('gmt_offset');
18
+ $q = $db->querySelect("SELECT ctime, level, type, msg FROM {$table} ORDER BY ctime DESC LIMIT %d, 100", $offset);
19
+ while (is_array($q) && count($q) > 0) {
20
+ foreach($q as $r){
21
+ if($r['level'] < 4 || $debugOn){
22
+ echo '<div' . ($r['type'] == 'error' ? ' class="error"' : '') . '>[' . date('M d H:i:s', $r['ctime'] + $timeOffset) . ':' . $r['ctime'] . ':' . $r['level'] . ':' . $r['type'] . ']&nbsp;' . esc_html($r['msg']) . "</div>\n";
23
+ }
24
}
25
+ $offset += count($q);
26
+ $q = $db->querySelect("SELECT ctime, level, type, msg FROM {$table} ORDER BY ctime DESC LIMIT %d, 100", $offset);
27
}
28
?>
29
</body>
lib/wfConfig.php CHANGED
@@ -36,6 +36,7 @@ class wfConfig {
36
"lowResourceScansEnabled" => array('value' => false, 'autoload' => self::AUTOLOAD),
37
"scansEnabled_public" => array('value' => false, 'autoload' => self::AUTOLOAD),
38
"scansEnabled_heartbleed" => array('value' => true, 'autoload' => self::AUTOLOAD),
39
"scansEnabled_core" => array('value' => true, 'autoload' => self::AUTOLOAD),
40
"scansEnabled_themes" => array('value' => false, 'autoload' => self::AUTOLOAD),
41
"scansEnabled_plugins" => array('value' => false, 'autoload' => self::AUTOLOAD),
36
"lowResourceScansEnabled" => array('value' => false, 'autoload' => self::AUTOLOAD),
37
"scansEnabled_public" => array('value' => false, 'autoload' => self::AUTOLOAD),
38
"scansEnabled_heartbleed" => array('value' => true, 'autoload' => self::AUTOLOAD),
39
+ "scansEnabled_checkHowGetIPs" => array('value' => true, 'autoload' => self::AUTOLOAD),
40
"scansEnabled_core" => array('value' => true, 'autoload' => self::AUTOLOAD),
41
"scansEnabled_themes" => array('value' => false, 'autoload' => self::AUTOLOAD),
42
"scansEnabled_plugins" => array('value' => false, 'autoload' => self::AUTOLOAD),
lib/wfLog.php CHANGED
@@ -285,15 +285,23 @@ class wfLog {
285
286
/**
287
* @param string $IP Should be in dot or colon notation (127.0.0.1 or ::1)
288
* @return bool
289
*/
290
- public function isWhitelisted($IP) {
291
foreach (wfUtils::getIPWhitelist() as $subnet) {
292
if ($subnet instanceof wfUserIPRange) {
293
if ($subnet->isIPInRange($IP)) {
294
return true;
295
}
296
} elseif (wfUtils::subnetContainsIP($subnet, $IP)) {
297
return true;
298
}
299
}
285
286
/**
287
* @param string $IP Should be in dot or colon notation (127.0.0.1 or ::1)
288
+ * @param bool $forcedWhitelistEntry If provided, returns whether or not the IP is on a forced whitelist.
289
* @return bool
290
*/
291
+ public function isWhitelisted($IP, &$forcedWhitelistEntry = null) {
292
+ if ($forcedWhitelistEntry !== null) {
293
+ $forcedWhitelistEntry = false;
294
+ }
295
+
296
foreach (wfUtils::getIPWhitelist() as $subnet) {
297
if ($subnet instanceof wfUserIPRange) {
298
if ($subnet->isIPInRange($IP)) {
299
return true;
300
}
301
} elseif (wfUtils::subnetContainsIP($subnet, $IP)) {
302
+ if ($forcedWhitelistEntry !== null) {
303
+ $forcedWhitelistEntry = true;
304
+ }
305
return true;
306
}
307
}
lib/wfScanEngine.php CHANGED
@@ -49,6 +49,8 @@ class wfScanEngine {
49
private $knownFilesLoader;
50
51
private $metrics = array();
52
53
public static function testForFullPathDisclosure($url = null, $filePath = null) {
54
if ($url === null && $filePath === null) {
@@ -73,7 +75,7 @@ class wfScanEngine {
73
}
74
75
public function __sleep(){ //Same order here as above for properties that are included in serialization
76
- return array('hasher', 'jobList', 'i', 'wp_version', 'apiKey', 'startTime', 'maxExecTime', 'publicScanEnabled', 'fileContentsResults', 'scanner', 'scanQueue', 'hoover', 'scanData', 'statusIDX', 'userPasswdQueue', 'passwdHasIssues', 'suspectedFiles', 'dbScanner', 'knownFilesLoader', 'metrics');
77
}
78
public function __construct(){
79
$this->startTime = time();
@@ -91,6 +93,8 @@ class wfScanEngine {
91
$this->jobList[] = 'checkSpamIP';
92
$this->jobList[] = 'checkGSB';
93
$this->jobList[] = 'heartbleed';
94
$this->jobList[] = 'knownFiles_init';
95
$this->jobList[] = 'knownFiles_main';
96
$this->jobList[] = 'knownFiles_finish';
@@ -340,6 +344,57 @@ class wfScanEngine {
340
sleep(2);
341
}
342
}
343
344
private function scan_checkReadableConfig() {
345
$haveIssues = false;
49
private $knownFilesLoader;
50
51
private $metrics = array();
52
+
53
+ private $checkHowGetIPsRequestTime = 0;
54
55
public static function testForFullPathDisclosure($url = null, $filePath = null) {
56
if ($url === null && $filePath === null) {
75
}
76
77
public function __sleep(){ //Same order here as above for properties that are included in serialization
78
+ return array('hasher', 'jobList', 'i', 'wp_version', 'apiKey', 'startTime', 'maxExecTime', 'publicScanEnabled', 'fileContentsResults', 'scanner', 'scanQueue', 'hoover', 'scanData', 'statusIDX', 'userPasswdQueue', 'passwdHasIssues', 'suspectedFiles', 'dbScanner', 'knownFilesLoader', 'metrics', 'checkHowGetIPsRequestTime');
79
}
80
public function __construct(){
81
$this->startTime = time();
93
$this->jobList[] = 'checkSpamIP';
94
$this->jobList[] = 'checkGSB';
95
$this->jobList[] = 'heartbleed';
96
+ $this->jobList[] = 'checkHowGetIPs_init';
97
+ $this->jobList[] = 'checkHowGetIPs_main';
98
$this->jobList[] = 'knownFiles_init';
99
$this->jobList[] = 'knownFiles_main';
100
$this->jobList[] = 'knownFiles_finish';
344
sleep(2);
345
}
346
}
347
+
348
+ private function scan_checkHowGetIPs_init() {
349
+ if (wfConfig::get('scansEnabled_checkHowGetIPs')) {
350
+ $this->statusIDX['checkHowGetIPs'] = wordfence::statusStart("Checking for the most secure way to get IPs");
351
+ $this->checkHowGetIPsRequestTime = time();
352
+ wfUtils::requestDetectProxyCallback();
353
+ }
354
+ else {
355
+ wordfence::statusDisabled("Skipping scan for misconfigured How does Wordfence get IPs");
356
+ }
357
+ }
358
+
359
+ private function scan_checkHowGetIPs_main() {
360
+ if (!defined('WORDFENCE_CHECKHOWGETIPS_TIMEOUT')) { define('WORDFENCE_CHECKHOWGETIPS_TIMEOUT', 30); }
361
+
362
+ if (wfConfig::get('scansEnabled_checkHowGetIPs')) {
363
+ $haveIssues = false;
364
+ $existing = wfConfig::get('howGetIPs', '');
365
+ $recommendation = wfConfig::get('detectProxyRecommendation', '');
366
+ while (empty($recommendation) && (time() - $this->checkHowGetIPsRequestTime) < WORDFENCE_CHECKHOWGETIPS_TIMEOUT) {
367
+ sleep(1);
368
+ $this->forkIfNeeded();
369
+ $recommendation = wfConfig::get('detectProxyRecommendation', '');
370
+ }
371
+
372
+ if ($recommendation == 'UNKNOWN' || empty($recommendation)) {
373
+ $this->addIssue('checkHowGetIPs', 2, 'checkHowGetIPs', 'checkHowGetIPs' . $recommendation . WORDFENCE_VERSION, "Unable to accurately detect IPs", 'Wordfence was unable to validate a test request to your website. This can happen if your website is behind a proxy that does not use one of the standard ways to convey the IP of the request or it is unreachable publicly. IP blocking and live traffic information may not be accurate. <a href="https://docs.wordfence.com/en/Misconfigured_how_get_IPs_notice " target="_blank">Get More Information</a>', array());
374
+ $haveIssues = true;
375
+ }
376
+ else if (!empty($existing) && $existing != $recommendation) {
377
+ $extraMsg = '';
378
+ if ($recommendation == 'REMOTE_ADDR') {
379
+ $extraMsg = ' For maximum security use PHP\'s built in REMOTE_ADDR.';
380
+ }
381
+ else if ($recommendation == 'HTTP_X_FORWARDED_FOR') {
382
+ $extraMsg = ' This site appears to be behind a front-end proxy, so using the X-Forwarded-For HTTP header will resolve to the correct IPs.';
383
+ }
384
+ else if ($recommendation == 'HTTP_X_REAL_IP') {
385
+ $extraMsg = ' This site appears to be behind a front-end proxy, so using the X-Real-IP HTTP header will resolve to the correct IPs.';
386
+ }
387
+ else if ($recommendation == 'HTTP_CF_CONNECTING_IP') {
388
+ $extraMsg = ' This site appears to be behind Cloudflare, so using the Cloudflare "CF-Connecting-IP" HTTP header will resolve to the correct IPs.';
389
+ }
390
+
391
+ $this->addIssue('checkHowGetIPs', 2, 'checkHowGetIPs', 'checkHowGetIPs' . $recommendation . WORDFENCE_VERSION, "'How does Wordfence get IPs' is misconfigured", 'A test request to this website was detected on a different value for this setting. IP blocking and live traffic information may not be accurate. <a href="https://docs.wordfence.com/en/Misconfigured_how_get_IPs_notice " target="_blank">Get More Information</a>' . $extraMsg, array('recommendation' => $recommendation));
392
+ $haveIssues = true;
393
+ }
394
+
395
+ wordfence::statusEnd($this->statusIDX['checkHowGetIPs'], $haveIssues);
396
+ }
397
+ }
398
399
private function scan_checkReadableConfig() {
400
$haveIssues = false;
lib/wfUtils.php CHANGED
@@ -630,6 +630,10 @@ class wfUtils {
630
}
631
}
632
public static function getIP(){
633
//For debugging.
634
//return '54.232.205.132';
635
//return self::makeRandomIP();
@@ -638,6 +642,7 @@ class wfUtils {
638
$ip = self::getIPAndServerVarible();
639
if (is_array($ip)) {
640
list($IP, $variable) = $ip;
641
return $IP;
642
}
643
return false;
@@ -658,7 +663,15 @@ class wfUtils {
658
return self::getCleanIPAndServerVar($ipsToCheck);
659
}
660
} else {
661
- $ipsToCheck = array($connectionIP);
662
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
663
$ipsToCheck[] = array($_SERVER['HTTP_X_FORWARDED_FOR'], 'HTTP_X_FORWARDED_FOR');
664
}
@@ -1402,6 +1415,94 @@ class wfUtils {
1402
}
1403
return $output;
1404
}
1405
}
1406
1407
// GeoIP lib uses these as well
630
}
631
}
632
public static function getIP(){
633
+ static $theIP = null;
634
+ if (isset($theIP)) {
635
+ return $theIP;
636
+ }
637
//For debugging.
638
//return '54.232.205.132';
639
//return self::makeRandomIP();
642
$ip = self::getIPAndServerVarible();
643
if (is_array($ip)) {
644
list($IP, $variable) = $ip;
645
+ $theIP = $IP;
646
return $IP;
647
}
648
return false;
663
return self::getCleanIPAndServerVar($ipsToCheck);
664
}
665
} else {
666
+ $ipsToCheck = array();
667
+
668
+ $recommendedField = wfConfig::get('detectProxyRecommendation', ''); //Prioritize the result from our proxy check if done
669
+ if (!empty($recommendedField) && $recommendedField != 'UNKNOWN') {
670
+ if (isset($_SERVER[$recommendedField])) {
671
+ $ipsToCheck[] = array($_SERVER[$recommendedField], $recommendedField);
672
+ }
673
+ }
674
+ $ipsToCheck[] = $connectionIP;
675
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
676
$ipsToCheck[] = array($_SERVER['HTTP_X_FORWARDED_FOR'], 'HTTP_X_FORWARDED_FOR');
677
}
1415
}
1416
return $output;
1417
}
1418
+
1419
+ public static function requestDetectProxyCallback($timeout = 0.01, $blocking = false) {
1420
+ $nonce = bin2hex(wfWAFUtils::random_bytes(32));
1421
+ $callback = self::getSiteBaseURL() . '?_wfsf=detectProxy';
1422
+
1423
+ wfConfig::set('detectProxyNonce', $nonce, wfConfig::DONT_AUTOLOAD);
1424
+ wfConfig::set('detectProxyRecommendation', '', wfConfig::DONT_AUTOLOAD);
1425
+
1426
+ $payload = array(
1427
+ 'nonce' => $nonce,
1428
+ 'callback' => $callback,
1429
+ );
1430
+
1431
+ $siteurl = '';
1432
+ if (function_exists('get_bloginfo')) {
1433
+ if (is_multisite()) {
1434
+ $siteurl = network_home_url();
1435
+ $siteurl = rtrim($siteurl, '/'); //Because previously we used get_bloginfo and it returns http://example.com without a '/' char.
1436
+ } else {
1437
+ $siteurl = home_url();
1438
+ }
1439
+ }
1440
+
1441
+ wp_remote_post(WFWAF_API_URL_SEC . "?" . http_build_query(array(
1442
+ 'action' => 'detect_proxy',
1443
+ 'k' => wfConfig::get('apiKey'),
1444
+ 's' => $siteurl,
1445
+ 't' => microtime(true),
1446
+ ), null, '&'),
1447
+ array(
1448
+ 'body' => json_encode($payload),
1449
+ 'headers' => array(
1450
+ 'Content-Type' => 'application/json',
1451
+ ),
1452
+ 'timeout' => $timeout,
1453
+ 'blocking' => $blocking,
1454
+ ));
1455
+
1456
+ //Asynchronous so we don't care about a response at this point.
1457
+ }
1458
+
1459
+ /**
1460
+ * @return bool Returns false if the payload is invalid, true if it processed the callback (even if the IP wasn't found).
1461
+ */
1462
+ public static function processDetectProxyCallback() {
1463
+ $nonce = wfConfig::get('detectProxyNonce', '');
1464
+ $testNonce = (isset($_POST['nonce']) ? $_POST['nonce'] : '');
1465
+ if (empty($nonce) || empty($testNonce)) {
1466
+ return false;
1467
+ }
1468
+
1469
+ if (!hash_equals($nonce, $testNonce)) {
1470
+ return false;
1471
+ }
1472
+
1473
+ $ips = (isset($_POST['ips']) ? $_POST['ips'] : array());
1474
+ if (empty($ips)) {
1475
+ return false;
1476
+ }
1477
+
1478
+ $expandedIPs = array();
1479
+ foreach ($ips as $ip) {
1480
+ $expandedIPs[] = self::inet_pton($ip);
1481
+ }
1482
+
1483
+ $checks = array('HTTP_CF_CONNECTING_IP', 'HTTP_X_REAL_IP', 'REMOTE_ADDR', 'HTTP_X_FORWARDED_FOR');
1484
+ foreach ($checks as $key) {
1485
+ if (!isset($_SERVER[$key])) {
1486
+ continue;
1487
+ }
1488
+
1489
+ $testIP = self::getCleanIPAndServerVar(array(array($_SERVER[$key], $key)));
1490
+ if ($testIP === false) {
1491
+ continue;
1492
+ }
1493
+
1494
+ $testIP = self::inet_pton($testIP[0]);
1495
+ if (in_array($testIP, $expandedIPs)) {
1496
+ wfConfig::set('detectProxyRecommendation', $key, wfConfig::DONT_AUTOLOAD);
1497
+ wfConfig::set('detectProxyNonce', '', wfConfig::DONT_AUTOLOAD);
1498
+ return true;
1499
+ }
1500
+ }
1501
+
1502
+ wfConfig::set('detectProxyRecommendation', 'UNKNOWN', wfConfig::DONT_AUTOLOAD);
1503
+ wfConfig::set('detectProxyNonce', '', wfConfig::DONT_AUTOLOAD);
1504
+ return true;
1505
+ }
1506
}
1507
1508
// GeoIP lib uses these as well
lib/wordfenceClass.php CHANGED
@@ -564,6 +564,9 @@ SQL
564
if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
565
wfWAFIPBlocksController::synchronizeConfigSettings();
566
}
567
568
//Must be the final line
569
}
@@ -1135,6 +1138,17 @@ SQL
1135
exit();
1136
}
1137
}
1138
1139
// Sync the WAF data with the database.
1140
if (!WFWAF_SUBDIRECTORY_INSTALL && $waf = wfWAF::getInstance()) {
@@ -2533,6 +2547,22 @@ SQL
2533
wfConfig::set('falconDeprecationChoice', '1');
2534
return array('ok' => 1);
2535
}
2536
public static function ajax_removeFromCache_callback(){
2537
$id = $_POST['id'];
2538
$link = get_permalink($id);
@@ -2731,7 +2761,7 @@ SQL
2731
exit;
2732
}
2733
2734
- wfErrorLogHandler::outputErrorLog($_GET['logfile']); //exits
2735
}
2736
public static function ajax_addCacheExclusion_callback(){
2737
$ex = wfConfig::get('cacheExclusions', false);
@@ -3194,8 +3224,13 @@ HTACCESS;
3194
if ($IP == wfUtils::getIP()) {
3195
return array('err' => 1, 'errorMsg' => "You can't block your own IP address.");
3196
}
3197
- if ($log->isWhitelisted($IP)) {
3198
- return array('err' => 1, 'errorMsg' => "The IP address " . wp_kses($IP, array()) . " is whitelisted and can't be blocked or it is in a range of internal IP addresses that Wordfence does not block. You can remove this IP from the whitelist on the Wordfence options page.");
3199
}
3200
if (wfConfig::get('neverBlockBG') != 'treatAsOtherCrawlers') { //Either neverBlockVerified or neverBlockUA is selected which means the user doesn't want to block google
3201
if (wfCrawl::isVerifiedGoogleCrawler($IP)) {
@@ -4310,7 +4345,7 @@ HTML;
4310
'activityLogUpdate', 'ticker', 'loadIssues', 'updateIssueStatus', 'deleteIssue', 'updateAllIssues',
4311
'reverseLookup', 'unlockOutIP', 'loadBlockRanges', 'unblockRange', 'blockIPUARange', 'whois', 'unblockIP',
4312
'blockIP', 'permBlockIP', 'loadStaticPanel', 'saveConfig', 'downloadHtaccess', 'downloadLogFile', 'checkFalconHtaccess',
4313
- 'updateConfig', 'saveCacheConfig', 'removeFromCache', 'autoUpdateChoice', 'adminEmailChoice', 'suPHPWAFUpdateChoice', 'falconDeprecationChoice', 'saveCacheOptions', 'clearPageCache',
4314
'getCacheStats', 'clearAllBlocked', 'killScan', 'saveCountryBlocking', 'saveScanSchedule', 'tourClosed',
4315
'welcomeClosed', 'startTourAgain', 'downgradeLicense', 'addTwoFactor', 'twoFacActivate', 'twoFacDel',
4316
'loadTwoFactor', 'loadAvgSitePerf', 'sendTestEmail', 'addCacheExclusion', 'removeCacheExclusion',
@@ -4476,6 +4511,43 @@ HTML;
4476
echo '<div id="wordfenceFalconDeprecationWarning" class="fade error"><p><strong>Support for the Falcon and Basic cache will be removed.</strong> This site currently has the ' . $cacheName . ' cache enabled, and it is scheduled to be removed in an upcoming release. Please investigate other caching options and then <a href="' . $url . '">click here to visit the cache settings page</a> to manually disable the cache. It will be disabled automatically when support is removed.</p><p>
4477
<a class="button button-small wf-dismiss-link" href="#" onclick="wordfenceExt.falconDeprecationChoice(\'no\'); return false;">Dismiss</a></p></div>';
4478
}
4479
public static function autoUpdateNotice(){
4480
echo '<div id="wordfenceAutoUpdateChoice" class="fade error"><p><strong>Do you want Wordfence to stay up-to-date automatically?</strong>&nbsp;&nbsp;&nbsp;<a href="#" onclick="wordfenceExt.autoUpdateChoice(\'yes\'); return false;">Yes, enable auto-update.</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="wordfenceExt.autoUpdateChoice(\'no\'); return false;">No thanks.</a></p></div>';
4481
}
@@ -4508,6 +4580,14 @@ HTML;
4508
add_action('admin_notices', 'wordfence::falconDeprecationWarning');
4509
}
4510
}
4511
if(! $warningAdded){
4512
if(wfConfig::get('tourClosed') == '1' && (! wfConfig::get('autoUpdate')) && (! wfConfig::get('autoUpdateChoice'))){
4513
$warningAdded = true;
564
if (!WFWAF_SUBDIRECTORY_INSTALL && class_exists('wfWAFIPBlocksController')) {
565
wfWAFIPBlocksController::synchronizeConfigSettings();
566
}
567
+
568
+ //Check the How does Wordfence get IPs setting
569
+ wfUtils::requestDetectProxyCallback();
570
571
//Must be the final line
572
}
1138
exit();
1139
}
1140
}
1141
+ else if ($wfFunc == 'detectProxy') {
1142
+ wfUtils::doNotCache();
1143
+ if (wfUtils::processDetectProxyCallback()) {
1144
+ self::getLog()->getCurrentRequest()->action = 'scan:detectproxy'; //Exempt a valid callback from live traffic
1145
+ echo wfConfig::get('detectProxyRecommendation', '-');
1146
+ }
1147
+ else {
1148
+ echo '0';
1149
+ }
1150
+ exit();
1151
+ }
1152
1153
// Sync the WAF data with the database.
1154
if (!WFWAF_SUBDIRECTORY_INSTALL && $waf = wfWAF::getInstance()) {
2547
wfConfig::set('falconDeprecationChoice', '1');
2548
return array('ok' => 1);
2549
}
2550
+ public static function ajax_misconfiguredHowGetIPsChoice_callback() {
2551
+ $choice = $_POST['choice'];
2552
+ if ($choice == 'yes') {
2553
+ wfConfig::set('howGetIPs', wfConfig::get('detectProxyRecommendation', ''));
2554
+
2555
+ if (isset($_POST['issueID'])) {
2556
+ $issueID = intval($_POST['issueID']);
2557
+ $wfIssues = new wfIssues();
2558
+ $wfIssues->updateIssue($issueID, 'delete');
2559
+ }
2560
+ }
2561
+ else {
2562
+ wfConfig::set('misconfiguredHowGetIPsChoice' . WORDFENCE_VERSION, '1');
2563
+ }
2564
+ return array('ok' => 1);
2565
+ }
2566
public static function ajax_removeFromCache_callback(){
2567
$id = $_POST['id'];
2568
$link = get_permalink($id);
2761
exit;
2762
}
2763
2764
+ wfErrorLogHandler::outputErrorLog(stripslashes($_GET['logfile'])); //exits
2765
}
2766
public static function ajax_addCacheExclusion_callback(){
2767
$ex = wfConfig::get('cacheExclusions', false);
3224
if ($IP == wfUtils::getIP()) {
3225
return array('err' => 1, 'errorMsg' => "You can't block your own IP address.");
3226
}
3227
+ $forcedWhitelistEntry = false;
3228
+ if ($log->isWhitelisted($IP, $forcedWhitelistEntry)) {
3229
+ $message = "The IP address " . wp_kses($IP, array()) . " is whitelisted and can't be blocked. You can remove this IP from the whitelist on the Wordfence options page.";
3230
+ if ($forcedWhitelistEntry) {
3231
+ $message = "The IP address " . wp_kses($IP, array()) . " is in a range of internal IP addresses that Wordfence does not block.";
3232
+ }
3233
+ return array('err' => 1, 'errorMsg' => $message);
3234
}
3235
if (wfConfig::get('neverBlockBG') != 'treatAsOtherCrawlers') { //Either neverBlockVerified or neverBlockUA is selected which means the user doesn't want to block google
3236
if (wfCrawl::isVerifiedGoogleCrawler($IP)) {
4345
'activityLogUpdate', 'ticker', 'loadIssues', 'updateIssueStatus', 'deleteIssue', 'updateAllIssues',
4346
'reverseLookup', 'unlockOutIP', 'loadBlockRanges', 'unblockRange', 'blockIPUARange', 'whois', 'unblockIP',
4347
'blockIP', 'permBlockIP', 'loadStaticPanel', 'saveConfig', 'downloadHtaccess', 'downloadLogFile', 'checkFalconHtaccess',
4348
+ 'updateConfig', 'saveCacheConfig', 'removeFromCache', 'autoUpdateChoice', 'adminEmailChoice', 'suPHPWAFUpdateChoice', 'falconDeprecationChoice', 'misconfiguredHowGetIPsChoice', 'saveCacheOptions', 'clearPageCache',
4349
'getCacheStats', 'clearAllBlocked', 'killScan', 'saveCountryBlocking', 'saveScanSchedule', 'tourClosed',
4350
'welcomeClosed', 'startTourAgain', 'downgradeLicense', 'addTwoFactor', 'twoFacActivate', 'twoFacDel',
4351
'loadTwoFactor', 'loadAvgSitePerf', 'sendTestEmail', 'addCacheExclusion', 'removeCacheExclusion',
4511
echo '<div id="wordfenceFalconDeprecationWarning" class="fade error"><p><strong>Support for the Falcon and Basic cache will be removed.</strong> This site currently has the ' . $cacheName . ' cache enabled, and it is scheduled to be removed in an upcoming release. Please investigate other caching options and then <a href="' . $url . '">click here to visit the cache settings page</a> to manually disable the cache. It will be disabled automatically when support is removed.</p><p>
4512
<a class="button button-small wf-dismiss-link" href="#" onclick="wordfenceExt.falconDeprecationChoice(\'no\'); return false;">Dismiss</a></p></div>';
4513
}
4514
+ public static function misconfiguredHowGetIPsNotice() {
4515
+ $url = network_admin_url('admin.php?page=WordfenceSecOpt');
4516
+ $existing = wfConfig::get('howGetIPs', '');
4517
+ $recommendation = wfConfig::get('detectProxyRecommendation', '');
4518
+ if (empty($existing) || empty($recommendation) || $recommendation == 'UNKNOWN' || $existing == $recommendation) {
4519
+ return;
4520
+ }
4521
+ $existingMsg = '';
4522
+ if ($existing == 'REMOTE_ADDR') {
4523
+ $existingMsg = 'This site is currently using PHP\'s built in REMOTE_ADDR.';
4524
+ }
4525
+ else if ($existing == 'HTTP_X_FORWARDED_FOR') {
4526
+ $existingMsg = 'This site is currently using the X-Forwarded-For HTTP header, which should only be used when the site is behind a front-end proxy that outputs this header.';
4527
+ }
4528
+ else if ($existing == 'HTTP_X_REAL_IP') {
4529
+ $existingMsg = 'This site is currently using the X-Real-IP HTTP header, which should only be used when the site is behind a front-end proxy that outputs this header.';
4530
+ }
4531
+ else if ($existing == 'HTTP_CF_CONNECTING_IP') {
4532
+ $existingMsg = 'This site is currently using the Cloudflare "CF-Connecting-IP" HTTP header, which should only be used when the site is behind Cloudflare.';
4533
+ }
4534
+
4535
+ $recommendationMsg = '';
4536
+ if ($recommendation == 'REMOTE_ADDR') {
4537
+ $recommendationMsg = 'For maximum security use PHP\'s built in REMOTE_ADDR.';
4538
+ }
4539
+ else if ($recommendation == 'HTTP_X_FORWARDED_FOR') {
4540
+ $recommendationMsg = 'This site appears to be behind a front-end proxy, so using the X-Forwarded-For HTTP header will resolve to the correct IPs.';
4541
+ }
4542
+ else if ($recommendation == 'HTTP_X_REAL_IP') {
4543
+ $recommendationMsg = 'This site appears to be behind a front-end proxy, so using the X-Real-IP HTTP header will resolve to the correct IPs.';
4544
+ }
4545
+ else if ($recommendation == 'HTTP_CF_CONNECTING_IP') {
4546
+ $recommendationMsg = 'This site appears to be behind Cloudflare, so using the Cloudflare "CF-Connecting-IP" HTTP header will resolve to the correct IPs.';
4547
+ }
4548
+ echo '<div id="wordfenceMisconfiguredHowGetIPsNotice" class="fade error"><p><strong>Your \'How does Wordfence get IPs\' setting is misconfigured.</strong> ' . $existingMsg . ' ' . $recommendationMsg . ' <a href="#" onclick="wordfenceExt.misconfiguredHowGetIPsChoice(\'yes\'); return false;">Click here to use the recommended setting</a> or <a href="' . $url . '">visit the options page</a> to manually update it.</p><p>
4549
+ <a class="button button-small wf-dismiss-link" href="#" onclick="wordfenceExt.misconfiguredHowGetIPsChoice(\'no\'); return false;">Dismiss</a> <a class="wfhelp" target="_blank" href="https://docs.wordfence.com/en/Misconfigured_how_get_IPs_notice"></a></p></div>';
4550
+ }
4551
public static function autoUpdateNotice(){
4552
echo '<div id="wordfenceAutoUpdateChoice" class="fade error"><p><strong>Do you want Wordfence to stay up-to-date automatically?</strong>&nbsp;&nbsp;&nbsp;<a href="#" onclick="wordfenceExt.autoUpdateChoice(\'yes\'); return false;">Yes, enable auto-update.</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="wordfenceExt.autoUpdateChoice(\'no\'); return false;">No thanks.</a></p></div>';
4553
}
4580
add_action('admin_notices', 'wordfence::falconDeprecationWarning');
4581
}
4582
}
4583
+ if (!wfConfig::get('misconfiguredHowGetIPsChoice' . WORDFENCE_VERSION) && !(defined('WORDFENCE_DISABLE_MISCONFIGURED_HOWGETIPS') && WORDFENCE_DISABLE_MISCONFIGURED_HOWGETIPS)) {
4584
+ $warningAdded = true;
4585
+ if(wfUtils::isAdminPageMU()){
4586
+ add_action('network_admin_notices', 'wordfence::misconfiguredHowGetIPsNotice');
4587
+ } else {
4588
+ add_action('admin_notices', 'wordfence::misconfiguredHowGetIPsNotice');
4589
+ }
4590
+ }
4591
if(! $warningAdded){
4592
if(wfConfig::get('tourClosed') == '1' && (! wfConfig::get('autoUpdate')) && (! wfConfig::get('autoUpdateChoice'))){
4593
$warningAdded = true;
lib/wordfenceHash.php CHANGED
@@ -622,7 +622,7 @@ class wordfenceHash {
622
}
623
624
//Will be malware scanned, return true
625
- if (strpos($file, 'lib/wordfenceScanner.php') === false && ($fileExt == 'js')) {
626
return true;
627
}
628
622
}
623
624
//Will be malware scanned, return true
625
+ if ($fileExt == 'js') {
626
return true;
627
}
628
lib/wordfenceScanner.php CHANGED
@@ -300,8 +300,8 @@ class wordfenceScanner {
300
break;
301
}
302
}
303
- else if(strpos($file, 'lib/wordfenceScanner.php') === false) {
304
- $regexMatched = false;
305
foreach ($this->patterns['rules'] as $rule) {
306
$type = (isset($rule[4]) && !empty($rule[4])) ? $rule[4] : 'server';
307
$logOnly = (isset($rule[5]) && !empty($rule[5])) ? $rule[5] : false;
@@ -335,7 +335,7 @@ class wordfenceScanner {
335
}
336
}
337
if ($regexMatched) { break; }
338
- }
339
if ($treatAsBinary && wfConfig::get('scansEnabled_highSense')) {
340
$badStringFound = false;
341
if (strpos($data, $this->patterns['badstrings'][0]) !== false) {
300
break;
301
}
302
}
303
+ else {
304
+ $regexMatched = false;
305
foreach ($this->patterns['rules'] as $rule) {
306
$type = (isset($rule[4]) && !empty($rule[4])) ? $rule[4] : 'server';
307
$logOnly = (isset($rule[5]) && !empty($rule[5])) ? $rule[5] : false;
335
}
336
}
337
if ($regexMatched) { break; }
338
+ }
339
if ($treatAsBinary && wfConfig::get('scansEnabled_highSense')) {
340
$badStringFound = false;
341
if (strpos($data, $this->patterns['badstrings'][0]) !== false) {
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
3
Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking
4
Requires at least: 3.9
5
Tested up to: 4.7.0
6
- Stable tag: 6.2.6
7
8
Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
9
@@ -190,6 +190,19 @@ Secure your website with Wordfence.
190
191
== Changelog ==
192
193
= 6.2.6 =
194
* Improvement: Improved formatting of attack data when it contains binary characters.
195
* Improvement: Updated internal GeoIP database.
3
Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking
4
Requires at least: 3.9
5
Tested up to: 4.7.0
6
+ Stable tag: 6.2.7
7
8
Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
9
190
191
== Changelog ==
192
193
+ = 6.2.7 =
194
+ * Improvement: WordPress 4.7 improvements for the Web Application Firewall.
195
+ * Improvement: Updated signatures for hash-based malware detection.
196
+ * Improvement: Automatically attempt to detect when a site is behind a proxy and has IP information in a different field.
197
+ * Improvement: Added additional contextual help links.
198
+ * Improvement: Significant performance improvement for determining the connecting IP.
199
+ * Improvement: Better messaging for two-factor recovery codes.
200
+ * Fix: Adjusted message when trying to block an IP in the whitelist.
201
+ * Fix: Error log download links now work on Windows servers.
202
+ * Fix: Avoid running out of memory when viewing very large activity logs.
203
+ * Fix: Fixed warning that could be logged when following an unlock email link.
204
+ * Fix: Tour popups on options page now scroll into view correctly.
205
+
206
= 6.2.6 =
207
* Improvement: Improved formatting of attack data when it contains binary characters.
208
* Improvement: Updated internal GeoIP database.
waf/bootstrap.php CHANGED
@@ -29,6 +29,10 @@ class wfWAFWordPressRequest extends wfWAFRequest {
29
}
30
31
public function getIP() {
32
$howGet = wfWAF::getInstance()->getStorageEngine()->getConfig('howGetIPs');
33
if (is_string($howGet) && is_array($_SERVER) && array_key_exists($howGet, $_SERVER)) {
34
$ips[] = array($_SERVER[$howGet], $howGet);
@@ -37,8 +41,10 @@ class wfWAFWordPressRequest extends wfWAFRequest {
37
$cleanedIP = $this->_getCleanIPAndServerVar($ips);
38
if (is_array($cleanedIP)) {
39
list($ip, $variable) = $cleanedIP;
40
return $ip;
41
}
42
return $cleanedIP;
43
}
44
29
}
30
31
public function getIP() {
32
+ static $theIP = null;
33
+ if (isset($theIP)) {
34
+ return $theIP;
35
+ }
36
$howGet = wfWAF::getInstance()->getStorageEngine()->getConfig('howGetIPs');
37
if (is_string($howGet) && is_array($_SERVER) && array_key_exists($howGet, $_SERVER)) {
38
$ips[] = array($_SERVER[$howGet], $howGet);
41
$cleanedIP = $this->_getCleanIPAndServerVar($ips);
42
if (is_array($cleanedIP)) {
43
list($ip, $variable) = $cleanedIP;
44
+ $theIP = $ip;
45
return $ip;
46
}
47
+ $theIP = $cleanedIP;
48
return $cleanedIP;
49
}
50
wordfence.php CHANGED
@@ -4,14 +4,14 @@ Plugin Name: Wordfence Security
4
Plugin URI: http://www.wordfence.com/
5
Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
6
Author: Wordfence
7
- Version: 6.2.6
8
Author URI: http://www.wordfence.com/
9
Network: true
10
*/
11
if(defined('WP_INSTALLING') && WP_INSTALLING){
12
return;
13
}
14
- define('WORDFENCE_VERSION', '6.2.6');
15
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
16
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
17
4
Plugin URI: http://www.wordfence.com/
5
Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
6
Author: Wordfence
7
+ Version: 6.2.7
8
Author URI: http://www.wordfence.com/
9
Network: true
10
*/
11
if(defined('WP_INSTALLING') && WP_INSTALLING){
12
return;
13
}
14
+ define('WORDFENCE_VERSION', '6.2.7');
15
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
16
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
17