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 | 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 +27 -2
- js/tourTip.js +8 -0
- lib/menu_options.php +11 -1
- lib/menu_scan.php +34 -0
- lib/menu_waf.php +6 -2
- lib/viewFullActivityLog.php +9 -4
- lib/wfConfig.php +1 -0
- lib/wfLog.php +9 -1
- lib/wfScanEngine.php +56 -1
- lib/wfUtils.php +102 -1
- lib/wordfenceClass.php +84 -4
- lib/wordfenceHash.php +1 -1
- lib/wordfenceScanner.php +3 -3
- readme.txt +14 -1
- waf/bootstrap.php +6 -0
- wordfence.php +2 -2
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
|
|
|
|
|
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> <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> <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 |
-
$
|
17 |
$timeOffset = 3600 * get_option('gmt_offset');
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
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'] . '] ' . 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(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
3198 |
-
|
|
|
|
|
|
|
|
|
|
|
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> <a href="#" onclick="wordfenceExt.autoUpdateChoice(\'yes\'); return false;">Yes, enable auto-update.</a> | <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> <a href="#" onclick="wordfenceExt.autoUpdateChoice(\'yes\'); return false;">Yes, enable auto-update.</a> | <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 (
|
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
|
304 |
-
|
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.
|
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.
|
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.
|
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 |
|