Wordfence Security – Firewall & Malware Scan - Version 5.2.5

Version Description

  • Security release. Update immediately. Thanks to Julio Potier.
  • Code hardening including improved sanitization and an additional nonce for unlock email form. Special thanks to Ryan Satterfield for the hard work.
  • Stability of auto-update improved for LiteSpeed customers. We auto-detect if you don't have E=noabort:1 in your .htaccess and give you instructions.
  • Auto-update also disabled now for LiteSpeed customers who don't have E=noabort:1 and you will get an email alert with an explanation.
  • Fixed a bug that may cause you to have advanced blocking patterns disabled with falcon engine enabled that should not be disabled.
  • Removed a benign warning in wfCache.php.
  • Added clarity to the banned URL option on the options page. All URL's must be relative.
  • Added a primary key to the wp_wfStatus table which is required for certain incremental backup plugins and utilities.
  • Fixed advanced country blocking which was not correctly displaying advanced options.
  • Migrated to using wp_kses() for sanitization.
  • Prevent IP spoofing in default Wordfence IP configuration.
  • Change explanations of how Wordfence gets IP's to make it clear which to use to prevent spoofing.
  • Make it clear that the option to have IP's immediately blocked when they access a URL requires relative URL's starting with a forward slash.
  • Whitelist Sucuri's scanning IP addresses which were getting blocked because they triggered Wordfence blocking during a scan.
  • Improved Wordfence's code that acquires the visitor IP to block certain spoofing attacks, be more platform agnostic and deal with visits from private IP's more elegantly.
Download this release

Release Info

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

Code changes from version 5.2.4 to 5.2.5

lib/IPTraf.php CHANGED
@@ -4,7 +4,7 @@
4
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5
<link rel='stylesheet' id='wordfence-main-style-css' href='<?php echo wfUtils::getBaseURL(); ?>/css/iptraf.css?ver=<?php echo WORDFENCE_VERSION; ?>' type='text/css' media='all' />
6
<body>
7
- <h1>Wordfence: All recent hits for IP address <?php echo htmlspecialchars($IP, ENT_QUOTES, 'UTF-8'); if($reverseLookup){ echo '[' . htmlspecialchars($reverseLookup, ENT_QUOTES, 'UTF-8') . ']'; } ?></h1>
8
<table border="0" cellpadding="2" cellspacing="0" style="width: 900px;">
9
<?php foreach($results as $key => $v){ ?>
10
<tr><th>Time:</th><td><?php echo $v['timeAgo'] ?> ago -- <?php echo date(DATE_RFC822, $v['ctime']); ?> -- <?php echo $v['ctime']; ?> in Unixtime</td></tr>
@@ -12,11 +12,11 @@
12
<?php if(wfUtils::hasXSS($v['URL'])){ ?>
13
<tr><th>URL:</th><td><span style="color: #F00;">Possible XSS code filtered out for your security</span></td></tr>
14
<?php } else { ?>
15
- <tr><th>URL:</th><td><a href="<?php echo $v['URL']; ?>" target="_blank"><?php echo $v['URL']; ?></a></td></tr>
16
<?php } ?>
17
<tr><th>Type:</th><td><?php if($v['type'] == 'hit'){ echo 'Normal request'; } else if($v['type'] == '404'){ echo '<span style="color: #F00;">Page not found</span>'; } ?></td></tr>
18
<?php if($v['referer']){ ?><tr><th>Referrer:</th><td><a href="<?php echo $v['referer']; ?>" target="_blank"><?php echo $v['referer']; ?></a></td></tr><?php } ?>
19
- <tr><th>Full Browser ID:</th><td><?php echo esc_html($v['UA']); ?></td></tr>
20
<?php if($v['user']){ ?>
21
<tr><th>User:</th><td><a href="<?php echo $v['user']['editLink']; ?>" target="_blank"><?php echo $v['user']['avatar'] . ' ' . $v['user']['display_name']; ?></a></td></tr>
22
<?php } ?>
4
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5
<link rel='stylesheet' id='wordfence-main-style-css' href='<?php echo wfUtils::getBaseURL(); ?>/css/iptraf.css?ver=<?php echo WORDFENCE_VERSION; ?>' type='text/css' media='all' />
6
<body>
7
+ <h1>Wordfence: All recent hits for IP address <?php echo wp_kses($IP, array()); if($reverseLookup){ echo '[' . wp_kses($reverseLookup, array()) . ']'; } ?></h1>
8
<table border="0" cellpadding="2" cellspacing="0" style="width: 900px;">
9
<?php foreach($results as $key => $v){ ?>
10
<tr><th>Time:</th><td><?php echo $v['timeAgo'] ?> ago -- <?php echo date(DATE_RFC822, $v['ctime']); ?> -- <?php echo $v['ctime']; ?> in Unixtime</td></tr>
12
<?php if(wfUtils::hasXSS($v['URL'])){ ?>
13
<tr><th>URL:</th><td><span style="color: #F00;">Possible XSS code filtered out for your security</span></td></tr>
14
<?php } else { ?>
15
+ <tr><th>URL:</th><td><a href="<?php echo wp_kses($v['URL'], array()); ?>" target="_blank"><?php echo $v['URL']; ?></a></td></tr>
16
<?php } ?>
17
<tr><th>Type:</th><td><?php if($v['type'] == 'hit'){ echo 'Normal request'; } else if($v['type'] == '404'){ echo '<span style="color: #F00;">Page not found</span>'; } ?></td></tr>
18
<?php if($v['referer']){ ?><tr><th>Referrer:</th><td><a href="<?php echo $v['referer']; ?>" target="_blank"><?php echo $v['referer']; ?></a></td></tr><?php } ?>
19
+ <tr><th>Full Browser ID:</th><td><?php echo wp_kses($v['UA'], array()); ?></td></tr>
20
<?php if($v['user']){ ?>
21
<tr><th>User:</th><td><a href="<?php echo $v['user']['editLink']; ?>" target="_blank"><?php echo $v['user']['avatar'] . ' ' . $v['user']['display_name']; ?></a></td></tr>
22
<?php } ?>
lib/diffResult.php CHANGED
@@ -15,15 +15,15 @@
15
ignore this file the next time Wordfence scans your system.
16
</p>
17
<table border="0" style="margin: 0 0 20px 0;" class="summary">
18
- <tr><td>Filename:</td><td><?php echo htmlentities($_GET['file']); ?></td></tr>
19
<tr><td>File type:</td><td><?php
20
$cType = $_GET['cType'];
21
if($cType == 'core'){
22
echo "WordPress Core File</td></tr>";
23
} else if($cType == 'theme'){
24
- echo "Theme File</td></tr><tr><td>Theme Name:</td><td>" . htmlentities($_GET['cName']) . "</td></tr><tr><td>Theme Version:</td><td>" . htmlentities($_GET['cVersion']) . "</td></tr>";
25
} else if($cType == 'plugin'){
26
- echo "Plugin File</td></tr><tr><td>Plugin Name:</td><td>" . htmlentities($_GET['cName']) . "</td></tr><tr><td>Plugin Version:</td><td>" . htmlentities($_GET['cVersion']) . "</td></tr>";
27
} else {
28
echo "Unknown Type</td></tr>";
29
}
15
ignore this file the next time Wordfence scans your system.
16
</p>
17
<table border="0" style="margin: 0 0 20px 0;" class="summary">
18
+ <tr><td>Filename:</td><td><?php echo wp_kses($_GET['file'], array()); ?></td></tr>
19
<tr><td>File type:</td><td><?php
20
$cType = $_GET['cType'];
21
if($cType == 'core'){
22
echo "WordPress Core File</td></tr>";
23
} else if($cType == 'theme'){
24
+ echo "Theme File</td></tr><tr><td>Theme Name:</td><td>" . wp_kses($_GET['cName'], array()) . "</td></tr><tr><td>Theme Version:</td><td>" . wp_kses($_GET['cVersion'], array()) . "</td></tr>";
25
} else if($cType == 'plugin'){
26
+ echo "Plugin File</td></tr><tr><td>Plugin Name:</td><td>" . wp_kses($_GET['cName'], array()) . "</td></tr><tr><td>Plugin Version:</td><td>" . wp_kses($_GET['cVersion'], array()) . "</td></tr>";
27
} else {
28
echo "Unknown Type</td></tr>";
29
}
lib/menu_countryBlocking.php CHANGED
@@ -38,20 +38,20 @@ WFAD.countryMap = <?php echo json_encode($wfBulkCountries); ?>;
38
<option value="redir"<?php if(wfConfig::get('cbl_action') == 'redir'){ echo ' selected'; } ?>>Redirect to the URL below</option>
39
</select>
40
</td></tr>
41
- <tr><th>URL to redirect blocked users to:</th><td><input type="text" id="wfRedirURL" value="<?php if(wfConfig::get('cbl_redirURL')){ echo htmlspecialchars(wfConfig::get('cbl_redirURL')); } ?>" /></td></tr>
42
<tr><th>Block countries even if they are logged in:</th><td><input type="checkbox" id="wfLoggedInBlocked" value="1" <?php if(wfConfig::get('cbl_loggedInBlocked')){ echo 'checked'; } ?> /></td></tr>
43
<tr><th>Block access to the login form:</th><td><input type="checkbox" id="wfLoginFormBlocked" value="1" <?php if(wfConfig::get('cbl_loginFormBlocked')){ echo 'checked'; } ?> /></td></tr>
44
<tr><th>Block access to the rest of the site (outside the login form):</th><td><input type="checkbox" id="wfRestOfSiteBlocked" value="1" <?php if(wfConfig::get('cbl_restOfSiteBlocked')){ echo 'checked'; } ?> /></td></tr>
45
<tr><td colspan="2"><h2>Advanced Country Blocking Options</h2></td></tr>
46
<tr><th colspan="2">
47
If user hits the URL
48
- <input type="text" id="wfBypassRedirURL" value="<?php echo htmlspecialchars(wfConfig::get('cbl_cblBypassURL', "")); ?>" size="20" />
49
then redirect that user to
50
- <input type="text" id="wfBypassRedirDest" value="<?php echo htmlspecialchars(wfConfig::get('cbl_cblBypassURLRedir', "")); ?>" size="20" /> and set a cookie that will bypass all country blocking.
51
</th></tr>
52
<tr><th colspan="2">
53
If user who is allowed to access the site views the URL
54
- <input type="text" id="wfBypassViewURL" value="<?php echo htmlspecialchars(wfConfig::get('cbl_cblBypassURL', "")); ?>" size="20" />
55
then set a cookie that will bypass country blocking in future in case that user hits the site from a blocked country.
56
</th></tr>
57
38
<option value="redir"<?php if(wfConfig::get('cbl_action') == 'redir'){ echo ' selected'; } ?>>Redirect to the URL below</option>
39
</select>
40
</td></tr>
41
+ <tr><th>URL to redirect blocked users to:</th><td><input type="text" id="wfRedirURL" value="<?php if(wfConfig::get('cbl_redirURL')){ echo wp_kses(wfConfig::get('cbl_redirURL'), array()); } ?>" /></td></tr>
42
<tr><th>Block countries even if they are logged in:</th><td><input type="checkbox" id="wfLoggedInBlocked" value="1" <?php if(wfConfig::get('cbl_loggedInBlocked')){ echo 'checked'; } ?> /></td></tr>
43
<tr><th>Block access to the login form:</th><td><input type="checkbox" id="wfLoginFormBlocked" value="1" <?php if(wfConfig::get('cbl_loginFormBlocked')){ echo 'checked'; } ?> /></td></tr>
44
<tr><th>Block access to the rest of the site (outside the login form):</th><td><input type="checkbox" id="wfRestOfSiteBlocked" value="1" <?php if(wfConfig::get('cbl_restOfSiteBlocked')){ echo 'checked'; } ?> /></td></tr>
45
<tr><td colspan="2"><h2>Advanced Country Blocking Options</h2></td></tr>
46
<tr><th colspan="2">
47
If user hits the URL
48
+ <input type="text" id="wfBypassRedirURL" value="<?php echo wp_kses(wfConfig::get('cbl_bypassRedirURL', ""), array()); ?>" size="20" />
49
then redirect that user to
50
+ <input type="text" id="wfBypassRedirDest" value="<?php echo wp_kses(wfConfig::get('cbl_bypassRedirDest', ""), array()); ?>" size="20" /> and set a cookie that will bypass all country blocking.
51
</th></tr>
52
<tr><th colspan="2">
53
If user who is allowed to access the site views the URL
54
+ <input type="text" id="wfBypassViewURL" value="<?php echo wp_kses(wfConfig::get('cbl_bypassViewURL', ""), array()); ?>" size="20" />
55
then set a cookie that will bypass country blocking in future in case that user hits the site from a blocked country.
56
</th></tr>
57
lib/menu_options.php CHANGED
@@ -47,7 +47,12 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
47
<tr><td colspan="2">&nbsp;</td></tr>
48
<tr><th class="wfConfigEnable">Enable automatic scheduled scans</th><td><input type="checkbox" id="scheduledScansEnabled" class="wfConfigElem" name="scheduledScansEnabled" value="1" <?php $w->cb('scheduledScansEnabled'); ?> />&nbsp;Regular scans ensure your site stays secure.</td></tr>
49
<tr><td colspan="2">&nbsp;</td></tr>
50
- <tr><th class="wfConfigEnable">Update Wordfence automatically when a new version is released?</th><td><input type="checkbox" id="autoUpdate" class="wfConfigElem" name="autoUpdate" value="1" <?php $w->cb('autoUpdate'); ?> />&nbsp;Automatically updates Wordfence to the newest version within 24 hours of a new release.</td></tr>
51
<tr><td colspan="2">&nbsp;</td></tr>
52
53
<tr><th>Where to email alerts:</th><td><input type="text" id="alertEmails" name="alertEmails" value="<?php $w->f('alertEmails'); ?>" size="50" />&nbsp;<span class="wfTipText">Separate multiple emails with commas</span></td></tr>
@@ -64,11 +69,11 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
64
</td></tr>
65
<tr><th>How does Wordfence get IPs:</th><td>
66
<select id="howGetIPs" name="howGetIPs">
67
- <option value="">Set this option if you're seeing visitors from fake IP addresses or who appear to be from your internal network but aren't.</option>
68
- <option value="REMOTE_ADDR"<?php $w->sel('howGetIPs', 'REMOTE_ADDR'); ?>>Use PHP's built in REMOTE_ADDR. Use this if you're not using Nginx or any separate front-end proxy or firewall. Try this first.</option>
69
- <option value="HTTP_X_REAL_IP"<?php $w->sel('howGetIPs', 'HTTP_X_REAL_IP'); ?>>Use the X-Real-IP HTTP header which my Nginx, firewall or front-end proxy is setting. Try this next.</option>
70
- <option value="HTTP_X_FORWARDED_FOR"<?php $w->sel('howGetIPs', 'HTTP_X_FORWARDED_FOR'); ?>>Use the X-Forwarded-For HTTP header which my Nginx, firewall or front-end proxy is setting.</option>
71
- <option value="HTTP_CF_CONNECTING_IP"<?php $w->sel('howGetIPs', 'HTTP_CF_CONNECTING_IP'); ?>>I'm using Cloudflare so use the "CF-Connecting-IP" HTTP header to get a visitor IP</option>
72
</select>
73
</td></tr>
74
</table>
@@ -261,7 +266,9 @@ var WFSLevels = <?php echo json_encode(wfConfig::$securityLevels); ?>;
261
<tr><th colspan="2" style="color: #999;">Whitelisted IP's must be separated by commas. You can specify ranges using the following format: 123.23.34.[1-50]<br />Wordfence automatically whitelists <a href="http://en.wikipedia.org/wiki/Private_network" target="_blank">private networks</a> because these are not routable on the public Internet.<br /><br /></th></tr>
262
263
<tr><th>Immediately block IP's that access these URLs:</th><td><input type="text" name="bannedURLs" id="bannedURLs" value="<?php echo $w->getHTML('bannedURLs'); ?>" size="40" /></td></tr>
264
- <tr><th colspan="2" style="color: #999;">Separate multiple URL's with commas. If you see an attacker repeatedly probing your site for a known vulnerability you can use this to immediately block them.<br /><br /></th></tr>
265
266
<tr><th>Hide WordPress version</th><td><input type="checkbox" id="other_hideWPVersion" class="wfConfigElem" name="other_hideWPVersion" value="1" <?php $w->cb('other_hideWPVersion'); ?> /></td></tr>
267
<tr><th>Hold anonymous comments using member emails for moderation</th><td><input type="checkbox" id="other_noAnonMemberComments" class="wfConfigElem" name="other_noAnonMemberComments" value="1" <?php $w->cb('other_noAnonMemberComments'); ?> /></td></tr>
47
<tr><td colspan="2">&nbsp;</td></tr>
48
<tr><th class="wfConfigEnable">Enable automatic scheduled scans</th><td><input type="checkbox" id="scheduledScansEnabled" class="wfConfigElem" name="scheduledScansEnabled" value="1" <?php $w->cb('scheduledScansEnabled'); ?> />&nbsp;Regular scans ensure your site stays secure.</td></tr>
49
<tr><td colspan="2">&nbsp;</td></tr>
50
+ <tr><th class="wfConfigEnable">Update Wordfence automatically when a new version is released?</th><td><input type="checkbox" id="autoUpdate" class="wfConfigElem" name="autoUpdate" value="1" <?php $w->cb('autoUpdate'); ?> />&nbsp;Automatically updates Wordfence to the newest version within 24 hours of a new release.<br />
51
+ <?php if(getenv('noabort') != '1' && stristr($_SERVER['SERVER_SOFTWARE'], 'litespeed') !== false){ ?>
52
+ <span style="color: #F00;">Warning: </span>You are running LiteSpeed web server and you don't have the "noabort" variable set in your .htaccess.<br />
53
+ <a href="https://support.wordfence.com/solution/articles/1000129050-running-wordfence-under-litespeed-web-server-and-preventing-process-killing-or" target="_blank">Please read this article in our FAQ to make an important change that will ensure your site stability during an update.<br />
54
+ <?php } ?>
55
+ </td></tr>
56
<tr><td colspan="2">&nbsp;</td></tr>
57
58
<tr><th>Where to email alerts:</th><td><input type="text" id="alertEmails" name="alertEmails" value="<?php $w->f('alertEmails'); ?>" size="50" />&nbsp;<span class="wfTipText">Separate multiple emails with commas</span></td></tr>
69
</td></tr>
70
<tr><th>How does Wordfence get IPs:</th><td>
71
<select id="howGetIPs" name="howGetIPs">
72
+ <option value="">Let Wordfence use the most secure method to get visitor IP addresses. Prevents spoofing and works with most sites.</option>
73
+ <option value="REMOTE_ADDR"<?php $w->sel('howGetIPs', 'REMOTE_ADDR'); ?>>Use PHP's built in REMOTE_ADDR and don't use anything else. Very secure if this is compatible with your site.</option>
74
+ <option value="HTTP_X_FORWARDED_FOR"<?php $w->sel('howGetIPs', 'HTTP_X_FORWARDED_FOR'); ?>>Use the X-Forwarded-For HTTP header. Only use if you have a front-end proxy or spoofing may result.</option>
75
+ <option value="HTTP_X_REAL_IP"<?php $w->sel('howGetIPs', 'HTTP_X_REAL_IP'); ?>>Use the X-Real-IP HTTP header. Only use if you have a front-end proxy or spoofing may result.</option>
76
+ <option value="HTTP_CF_CONNECTING_IP"<?php $w->sel('howGetIPs', 'HTTP_CF_CONNECTING_IP'); ?>>Use the Cloudflare "CF-Connecting-IP" HTTP header to get a visitor IP. Only use if you're using Cloudflare.</option>
77
</select>
78
</td></tr>
79
</table>
266
<tr><th colspan="2" style="color: #999;">Whitelisted IP's must be separated by commas. You can specify ranges using the following format: 123.23.34.[1-50]<br />Wordfence automatically whitelists <a href="http://en.wikipedia.org/wiki/Private_network" target="_blank">private networks</a> because these are not routable on the public Internet.<br /><br /></th></tr>
267
268
<tr><th>Immediately block IP's that access these URLs:</th><td><input type="text" name="bannedURLs" id="bannedURLs" value="<?php echo $w->getHTML('bannedURLs'); ?>" size="40" /></td></tr>
269
+ <tr><th colspan="2" style="color: #999;">Separate multiple URL's with commas. If you see an attacker repeatedly probing your site for a known vulnerability you can use this to immediately block them.<br />
270
+ All URL's must start with a '/' without quotes and must be relative. e.g. /badURLone/, /bannedPage.html, /dont-access/this/URL/
271
+ <br /><br /></th></tr>
272
273
<tr><th>Hide WordPress version</th><td><input type="checkbox" id="other_hideWPVersion" class="wfConfigElem" name="other_hideWPVersion" value="1" <?php $w->cb('other_hideWPVersion'); ?> /></td></tr>
274
<tr><th>Hold anonymous comments using member emails for moderation</th><td><input type="checkbox" id="other_noAnonMemberComments" class="wfConfigElem" name="other_noAnonMemberComments" value="1" <?php $w->cb('other_noAnonMemberComments'); ?> /></td></tr>
lib/menu_rangeBlocking.php CHANGED
@@ -16,7 +16,7 @@
16
</ul>
17
</div>
18
<table class="wfConfigForm">
19
- <tr><th>Block anyone that has an IP address in this range:</th><td><input id="ipRange" type="text" size="30" maxlength="255" value="<?php if( isset( $_GET['wfBlockRange'] ) && $_GET['wfBlockRange']){ echo htmlentities($_GET['wfBlockRange']); } ?>" onkeyup="WFAD.calcRangeTotal();">&nbsp;<span id="wfShowRangeTotal"></span></td></tr>
20
<tr><td></td><td style="padding-bottom: 15px;"><strong>Examples:</strong> 192.168.200.200 - 192.168.200.220</td></tr>
21
<tr><th>...you can also enter a User-Agent (browser) that matches:</th><td><input id="uaRange" type="text" size="30" maxlength="255" >&nbsp;(Case insensitive)</td></tr>
22
<tr><td></td><td style="padding-bottom: 15px;"><strong>Examples:</strong> *badRobot*, AnotherBadRobot*, *someKindOfSuffix</td></tr>
16
</ul>
17
</div>
18
<table class="wfConfigForm">
19
+ <tr><th>Block anyone that has an IP address in this range:</th><td><input id="ipRange" type="text" size="30" maxlength="255" value="<?php if( isset( $_GET['wfBlockRange'] ) && $_GET['wfBlockRange']){ echo wp_kses($_GET['wfBlockRange'], array()); } ?>" onkeyup="WFAD.calcRangeTotal();">&nbsp;<span id="wfShowRangeTotal"></span></td></tr>
20
<tr><td></td><td style="padding-bottom: 15px;"><strong>Examples:</strong> 192.168.200.200 - 192.168.200.220</td></tr>
21
<tr><th>...you can also enter a User-Agent (browser) that matches:</th><td><input id="uaRange" type="text" size="30" maxlength="255" >&nbsp;(Case insensitive)</td></tr>
22
<tr><td></td><td style="padding-bottom: 15px;"><strong>Examples:</strong> *badRobot*, AnotherBadRobot*, *someKindOfSuffix</td></tr>
lib/menu_whois.php CHANGED
@@ -28,7 +28,7 @@ if(! function_exists('fsockopen')){
28
<?php if( isset( $_GET['wfnetworkblock'] ) && $_GET['wfnetworkblock']){ ?>
29
<h2>How to block a network</h2>
30
<p style="width: 600px;">
31
- You've chosen to block the network that <span style="color: #F00;"><?php echo htmlentities($_GET['whoisval']); ?></span> is part of.
32
We've marked the networks we found that this IP address belongs to in red below.
33
Make sure you read all the WHOIS information so that you see all networks this IP belongs to. We recommend blocking the network with the lowest number of addresses.
34
You may find this is listed at the end as part of the 'rWHOIS' query which contacts
@@ -51,7 +51,7 @@ if(! function_exists('fsockopen')){
51
</div>
52
</script>
53
<script type="text/javascript">
54
- var whoisval = "<?php if( isset( $_GET['whoisval'] ) ) { echo htmlentities($_GET['whoisval']); } ?>";
55
if(whoisval){
56
jQuery(function(){
57
jQuery('#wfwhois').val(whoisval);
28
<?php if( isset( $_GET['wfnetworkblock'] ) && $_GET['wfnetworkblock']){ ?>
29
<h2>How to block a network</h2>
30
<p style="width: 600px;">
31
+ You've chosen to block the network that <span style="color: #F00;"><?php echo wp_kses($_GET['whoisval'], array()); ?></span> is part of.
32
We've marked the networks we found that this IP address belongs to in red below.
33
Make sure you read all the WHOIS information so that you see all networks this IP belongs to. We recommend blocking the network with the lowest number of addresses.
34
You may find this is listed at the end as part of the 'rWHOIS' query which contacts
51
</div>
52
</script>
53
<script type="text/javascript">
54
+ var whoisval = "<?php if( isset( $_GET['whoisval'] ) ) { echo wp_kses($_GET['whoisval'], array()); } ?>";
55
if(whoisval){
56
jQuery(function(){
57
jQuery('#wfwhois').val(whoisval);
lib/viewFullActivityLog.php CHANGED
@@ -17,7 +17,7 @@ $q = $db->querySelect("select ctime, level, type, msg from $table order by ctime
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;' . htmlspecialchars($r['msg']) . "</div>\n";
21
}
22
}
23
?>
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;' . wp_kses($r['msg'], array()) . "</div>\n";
21
}
22
}
23
?>
lib/wfCache.php CHANGED
@@ -154,8 +154,8 @@ class wfCache {
154
$append .= "Time created on server: " . date('Y-m-d H:i:s T') . ". ";
155
$append .= "Is HTTPS page: " . (self::isHTTPSPage() ? 'HTTPS' : 'no') . ". ";
156
$append .= "Page size: " . strlen($buffer) . " bytes. ";
157
- $append .= "Host: " . ($_SERVER['HTTP_HOST'] ? htmlentities($_SERVER['HTTP_HOST']) : htmlentities($_SERVER['SERVER_NAME'])) . ". ";
158
- $append .= "Request URI: " . htmlentities($_SERVER['REQUEST_URI']) . " ";
159
$appendGzip = $append . " Encoding: GZEncode -->\n";
160
$append .= " Encoding: Uncompressed -->\n";
161
}
@@ -193,7 +193,7 @@ class wfCache {
193
public static function makeDirIfNeeded($file){
194
$file = preg_replace('/\/[^\/]*#x2F;', '', $file);
195
if(! is_dir($file)){
196
- mkdir($file, 0755, true);
197
}
198
}
199
public static function logout(){
154
$append .= "Time created on server: " . date('Y-m-d H:i:s T') . ". ";
155
$append .= "Is HTTPS page: " . (self::isHTTPSPage() ? 'HTTPS' : 'no') . ". ";
156
$append .= "Page size: " . strlen($buffer) . " bytes. ";
157
+ $append .= "Host: " . ($_SERVER['HTTP_HOST'] ? wp_kses($_SERVER['HTTP_HOST'], array()) : wp_kses($_SERVER['SERVER_NAME'], array())) . ". ";
158
+ $append .= "Request URI: " . wp_kses($_SERVER['REQUEST_URI'], array()) . " ";
159
$appendGzip = $append . " Encoding: GZEncode -->\n";
160
$append .= " Encoding: Uncompressed -->\n";
161
}
193
public static function makeDirIfNeeded($file){
194
$file = preg_replace('/\/[^\/]*#x2F;', '', $file);
195
if(! is_dir($file)){
196
+ @mkdir($file, 0755, true);
197
}
198
}
199
public static function logout(){
lib/wfConfig.php CHANGED
@@ -464,7 +464,7 @@ class wfConfig {
464
self::$cache = array();
465
}
466
public static function getHTML($key){
467
- return htmlspecialchars(self::get($key));
468
}
469
public static function inc($key){
470
$val = self::get($key, false);
@@ -751,6 +751,16 @@ class wfConfig {
751
}
752
public static function autoUpdate(){
753
try {
754
require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
755
require_once(ABSPATH . 'wp-admin/includes/misc.php');
756
/* We were creating show_message here so that WP did not write to STDOUT. This had the strange effect of throwing an error about redeclaring show_message function, but only when a crawler hit the site and triggered the cron job. Not a human. So we're now just require'ing misc.php which does generate output, but that's OK because it is a loopback cron request.
464
self::$cache = array();
465
}
466
public static function getHTML($key){
467
+ return wp_kses(self::get($key), array());
468
}
469
public static function inc($key){
470
$val = self::get($key, false);
751
}
752
public static function autoUpdate(){
753
try {
754
+ if(getenv('noabort') != '1' && stristr($_SERVER['SERVER_SOFTWARE'], 'litespeed') !== false){
755
+ wordfence::alert("Wordfence Upgrade not run. Please modify your .htaccess", "To preserve the integrity of your website we are not running Wordfence auto-update.\n" .
756
+ "You are running the LiteSpeed web server which has been known to cause a problem with Wordfence auto-update.\n" .
757
+ "Please go to your website now and make a minor change to your .htaccess to fix this.\n" .
758
+ "You can find out how to make this change at:\n" .
759
+ "https://support.wordfence.com/solution/articles/1000129050-running-wordfence-under-litespeed-web-server-and-preventing-process-killing-or\n" .
760
+ "\nAlternatively you can disable auto-update on your website to stop receiving this message and upgrade Wordfence manually.\n"
761
+ );
762
+ return;
763
+ }
764
require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
765
require_once(ABSPATH . 'wp-admin/includes/misc.php');
766
/* We were creating show_message here so that WP did not write to STDOUT. This had the strange effect of throwing an error about redeclaring show_message function, but only when a crawler hit the site and triggered the cron job. Not a human. So we're now just require'ing misc.php which does generate output, but that's OK because it is a loopback cron request.
lib/wfLog.php CHANGED
@@ -164,6 +164,11 @@ class wfLog {
164
if(wfUtils::isPrivateAddress($IP)){
165
return true;
166
}
167
$list = wfConfig::get('whitelisted');
168
if(! $list){ return false; }
169
$list = explode(',', $list);
@@ -235,7 +240,7 @@ class wfLog {
235
}
236
$blockDat = explode('|', $elem['blockString']);
237
$elem['ipPattern'] = "";
238
- $haveIPBLock = false;
239
$haveBrowserBlock = false;
240
if($blockDat[0]){
241
$haveIPBlock = true;
@@ -862,6 +867,7 @@ class wfLog {
862
foreach($results as &$rec){
863
//$rec['timeAgo'] = wfUtils::makeTimeAgo(time() - $rec['ctime']);
864
$rec['date'] = date('M d H:i:s', $rec['ctime'] + $timeOffset);
865
}
866
return $results;
867
}
164
if(wfUtils::isPrivateAddress($IP)){
165
return true;
166
}
167
+ //These belong to sucuri's scanning servers which will get blocked by Wordfence as a false positive if you try a scan. So we whitelisted them.
168
+ $externalWhite = array('97.74.127.171','69.164.203.172','173.230.128.135','66.228.34.49','66.228.40.185','50.116.36.92','50.116.36.93','50.116.3.171','198.58.96.212','50.116.63.221','192.155.92.112','192.81.128.31','198.58.106.244','192.155.95.139','23.239.9.227','198.58.112.103','192.155.94.43','162.216.16.33','173.255.233.124','173.255.233.124','192.155.90.179','50.116.41.217','192.81.129.227','198.58.111.80');
169
+ if(in_array($IP, $externalWhite)){
170
+ return true;
171
+ }
172
$list = wfConfig::get('whitelisted');
173
if(! $list){ return false; }
174
$list = explode(',', $list);
240
}
241
$blockDat = explode('|', $elem['blockString']);
242
$elem['ipPattern'] = "";
243
+ $haveIPBlock = false;
244
$haveBrowserBlock = false;
245
if($blockDat[0]){
246
$haveIPBlock = true;
867
foreach($results as &$rec){
868
//$rec['timeAgo'] = wfUtils::makeTimeAgo(time() - $rec['ctime']);
869
$rec['date'] = date('M d H:i:s', $rec['ctime'] + $timeOffset);
870
+ $rec['msg'] = wp_kses_data( (string) $rec['msg']);
871
}
872
return $results;
873
}
lib/wfSchema.php CHANGED
@@ -122,6 +122,7 @@ class wfSchema {
122
KEY k2(endTime)
123
) default charset=utf8",
124
"wfStatus" => "(
125
ctime DOUBLE(17,6) UNSIGNED NOT NULL,
126
level tinyint UNSIGNED NOT NULL,
127
type char(5) NOT NULL,
122
KEY k2(endTime)
123
) default charset=utf8",
124
"wfStatus" => "(
125
+ id bigint UNSIGNED NOT NULL auto_increment PRIMARY KEY,
126
ctime DOUBLE(17,6) UNSIGNED NOT NULL,
127
level tinyint UNSIGNED NOT NULL,
128
type char(5) NOT NULL,
lib/wfUnlockMsg.php CHANGED
@@ -1,6 +1,7 @@
1
If you are a site administrator and have been accidentally locked out, please enter your email in the box below and click "Send". If the email address you enter belongs to a known site administrator or someone set to receive Wordfence alerts, we will send you an email to help you regain access. <a href="http://www.wordfence.com/docs/frequently-asked-questions/#3" target="_blank">Please read our FAQ if this does not work.</a>
2
<br /><br />
3
<form method="POST" action="<?php echo wfUtils::getSiteBaseURL(); ?>?_wfsf=unlockEmail">
4
<input type="text" size="50" name="email" value="" maxlength="255" />&nbsp;<input type="submit" name="s" value="Send me an unlock email" />
5
</form>
6
<br /><br />
1
If you are a site administrator and have been accidentally locked out, please enter your email in the box below and click "Send". If the email address you enter belongs to a known site administrator or someone set to receive Wordfence alerts, we will send you an email to help you regain access. <a href="http://www.wordfence.com/docs/frequently-asked-questions/#3" target="_blank">Please read our FAQ if this does not work.</a>
2
<br /><br />
3
<form method="POST" action="<?php echo wfUtils::getSiteBaseURL(); ?>?_wfsf=unlockEmail">
4
+ <input type="hidden" name="nonce" value="<?php echo wp_create_nonce('wf-form'); ?>" />
5
<input type="text" size="50" name="email" value="" maxlength="255" />&nbsp;<input type="submit" name="s" value="Send me an unlock email" />
6
</form>
7
<br /><br />
lib/wfUtils.php CHANGED
@@ -106,21 +106,11 @@ class wfUtils {
106
//return ABSPATH . 'wp-content/plugins/';
107
}
108
public static function defaultGetIP(){
109
- $IP = 0;
110
- if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
111
- $IP = $_SERVER['HTTP_X_FORWARDED_FOR'];
112
- if(is_array($IP) && isset($IP[0])){ $IP = $IP[0]; } //It seems that some hosts may modify _SERVER vars into arrays.
113
- }
114
- if((! preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $IP)) && isset($_SERVER['HTTP_X_REAL_IP'])){
115
- $IP = $_SERVER['HTTP_X_REAL_IP'];
116
- if(is_array($IP) && isset($IP[0])){ $IP = $IP[0]; } //It seems that some hosts may modify _SERVER vars into arrays.
117
- }
118
- if((! preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $IP)) && isset($_SERVER['REMOTE_ADDR'])){
119
- $IP = $_SERVER['REMOTE_ADDR'];
120
- if(is_array($IP) && isset($IP[0])){ $IP = $IP[0]; } //It seems that some hosts may modify _SERVER vars into arrays.
121
- }
122
return $IP;
123
}
124
public static function isPrivateAddress($addr){
125
$num = self::inet_aton($addr);
126
foreach(self::$privateAddrs as $a){
@@ -130,80 +120,78 @@ class wfUtils {
130
}
131
return false;
132
}
133
- public static function makeRandomIP(){
134
- return rand(11,230) . '.' . rand(0,255) . '.' . rand(0,255) . '.' . rand(0,255);
135
- }
136
- public static function getIP(){
137
- //You can use the following examples to force Wordfence to think a visitor has a certain IP if you're testing. Remember to re-comment this out or you will break Wordfence badly.
138
- //return '1.2.33.57';
139
- //return '4.22.23.114';
140
- //return self::makeRandomIP();
141
-
142
- $howGet = wfConfig::get('howGetIPs', false);
143
- if($howGet){
144
- $IP = $_SERVER[$howGet];
145
- if( $howGet == "HTTP_CF_CONNECTING_IP" && (! self::isValidIP($IP)) ){
146
- $IP = $_SERVER['REMOTE_ADDR'];
147
- }
148
- } else {
149
- $IP = wfUtils::defaultGetIP();
150
- }
151
- if(preg_match('/,/', $IP)){
152
- $parts = explode(',', $IP); //Some users have "unknown,100.100.100.100" for example so we take the first thing that looks like an IP.
153
- foreach($parts as $part){
154
- if(preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $part) && (! self::isPrivateAddress($part)) ){
155
- $IP = trim($part);
156
- break;
157
}
158
}
159
- } else if(preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)\s+(\d+)\.(\d+)\.(\d+)\.(\d+)/', $IP)){
160
- $parts = explode(' ', $IP); //Some users have "unknown 100.100.100.100" for example so we take the first thing that looks like an IP.
161
- foreach($parts as $part){
162
- if(preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $part) && (! self::isPrivateAddress($part)) ){
163
- $IP = trim($part);
164
break;
165
}
166
}
167
-
168
- }
169
- if(preg_match('/:\d+#x2F;', $IP)){
170
- $IP = preg_replace('/:\d+#x2F;', '', $IP);
171
- }
172
- if(self::isValidIP($IP)){
173
- if(wfConfig::get('IPGetFail', false)){
174
- if(self::isPrivateAddress($IP) ){
175
- wordfence::status(1, 'error', "Wordfence is receiving IP addresses, but we received an internal IP of $IP so your config may still be incorrect.");
176
} else {
177
- wordfence::status(1, 'error', "Wordfence is now receiving IP addresses correctly. We received $IP from a visitor.");
178
}
179
- wfConfig::set('IPGetFail', '');
180
}
181
- return $IP;
182
} else {
183
- $xFor = "";
184
- if(isset($_SERVER['HTTP_X_FORWARDED_FOR']) ){
185
- $xFor = $_SERVER['HTTP_X_FORWARDED_FOR'];
186
- }
187
- $msg = "Wordfence can't get the IP of clients and therefore can't operate. We received IP: $IP. X-Forwarded-For was: " . $xFor . " REMOTE_ADDR was: " . $_SERVER['REMOTE_ADDR'];
188
- $possible = array();
189
- foreach($_SERVER as $key => $val){
190
- if(is_string($val) && preg_match('/^\d+\.\d+\.\d+\.\d+/', $val) && strlen($val) < 255){
191
- if($val != '127.0.0.1'){
192
- $possible[$key] = $val;
193
- }
194
- }
195
- }
196
- if(sizeof($possible) > 0){
197
- $msg .= " Headers that may contain the client IP: ";
198
- foreach($possible as $key => $val){
199
- $msg .= "$key => $val ";
200
- }
201
- }
202
- wordfence::status(1, 'error', $msg);
203
- wfConfig::set('IPGetFail', 1);
204
return false;
205
}
206
}
207
public static function isValidIP($IP){
208
if(preg_match('/^(\d+)\.(\d+)\.(\d+)\.(\d+)#x2F;', $IP, $m)){
209
if(
106
//return ABSPATH . 'wp-content/plugins/';
107
}
108
public static function defaultGetIP(){
109
return $IP;
110
}
111
+ public static function makeRandomIP(){
112
+ return rand(11,230) . '.' . rand(0,255) . '.' . rand(0,255) . '.' . rand(0,255);
113
+ }
114
public static function isPrivateAddress($addr){
115
$num = self::inet_aton($addr);
116
foreach(self::$privateAddrs as $a){
120
}
121
return false;
122
}
123
+ private static function getCleanIP($arr){ //Expects an array of items. The items are either IP's or IP's separated by comma, space or tab. Or an array of IP's.
124
+ // We then examine all IP's looking for a public IP and storing private IP's in an array. If we find no public IPs we return the first private addr we found.
125
+ $privates = array(); //Store private addrs until end as last resort.
126
+ for($i = 0; $i < count($arr); $i++){
127
+ $item = $arr[$i];
128
+ if(is_array($item)){
129
+ foreach($item as $j){
130
+ $j = preg_replace('/:\d+#x2F;', '', $j); //Strip off port
131
+ if(self::isValidIP($j)){
132
+ if(self::isPrivateAddress($j)){
133
+ $privates[] = $j;
134
+ } else {
135
+ return $j;
136
+ }
137
+ }
138
}
139
+ continue; //This was an array so we can skip to the next item
140
}
141
+ $skipToNext = false;
142
+ foreach(array(',', ' ', "\t") as $char){
143
+ if(strpos($item, $char) !== false){
144
+ $sp = explode($char, $item);
145
+ foreach($sp as $j){
146
+ $j = preg_replace('/:\d+#x2F;', '', $j); //Strip off port
147
+ if(self::isValidIP($j)){
148
+ if(self::isPrivateAddress($j)){
149
+ $privates[] = $j;
150
+ } else {
151
+ return $j;
152
+ }
153
+ }
154
+ }
155
+ $skipToNext = true;
156
break;
157
}
158
}
159
+ if($skipToNext){ continue; } //Skip to next item because this one had a comma, space or tab so was delimited and we didn't find anything.
160
+
161
+ $item = preg_replace('/:\d+#x2F;', '', $item); //Strip off port
162
+ if(self::isValidIP($item)){
163
+ if(self::isPrivateAddress($item)){
164
+ $privates[] = $item;
165
} else {
166
+ return $item;
167
}
168
}
169
+ }
170
+ if(sizeof($privates) > 0){
171
+ return $privates[0]; //Return the first private we found so that we respect the order the IP's were passed to this function.
172
} else {
173
return false;
174
}
175
}
176
+ public static function getIP(){
177
+ //For debugging.
178
+ //return '105.2.33.57';
179
+ //return self::makeRandomIP();
180
+ $howGet = wfConfig::get('howGetIPs', false);
181
+ if($howGet){
182
+ if($howGet == 'REMOTE_ADDR'){
183
+ $IP = self::getCleanIP(array($_SERVER['REMOTE_ADDR']));
184
+ } else {
185
+ $IP = self::getCleanIP(array($_SERVER[$howGet], $_SERVER['REMOTE_ADDR']));
186
+ }
187
+ } else {
188
+ $IPs = array($_SERVER['REMOTE_ADDR']);
189
+ if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){ $IPs[] = $_SERVER['HTTP_X_FORWARDED_FOR']; }
190
+ if(isset($_SERVER['HTTP_X_REAL_IP'])){ $IPs[] = $_SERVER['HTTP_X_REAL_IP']; }
191
+ $IP = self::getCleanIP($IPs);
192
+ }
193
+ return $IP; //Returns a valid IP or false.
194
+ }
195
public static function isValidIP($IP){
196
if(preg_match('/^(\d+)\.(\d+)\.(\d+)\.(\d+)#x2F;', $IP, $m)){
197
if(
lib/wfViewResult.php CHANGED
@@ -6,7 +6,7 @@
6
<body>
7
<h1>Wordfence: File Viewer</h1>
8
<table border="0" style="margin: 0 0 20px 0;" class="summary">
9
- <tr><td>Filename:</td><td><?php echo htmlspecialchars($localFile, ENT_QUOTES, 'UTF-8'); ?></td></tr>
10
<tr><td>File Size:</td><td><?php echo $fileSize; ?></td></tr>
11
<tr><td>File last modified:</td><td><?php echo $fileMTime; ?></td></tr>
12
</table>
6
<body>
7
<h1>Wordfence: File Viewer</h1>
8
<table border="0" style="margin: 0 0 20px 0;" class="summary">
9
+ <tr><td>Filename:</td><td><?php echo wp_kses($localFile, array()); ?></td></tr>
10
<tr><td>File Size:</td><td><?php echo $fileSize; ?></td></tr>
11
<tr><td>File last modified:</td><td><?php echo $fileMTime; ?></td></tr>
12
</table>
lib/wordfenceClass.php CHANGED
@@ -298,6 +298,8 @@ class wordfence {
298
$db->queryWriteIgnoreError("alter table $prefix"."wfLockedOut modify column blockedTime bigint signed NOT NULL");
299
$db->queryWriteIgnoreError("drop table if exists $prefix"."wfFileQueue");
300
$db->queryWriteIgnoreError("drop table if exists $prefix"."wfFileChanges");
301
302
$optScanEnabled = $db->querySingle("select val from $prefix"."wfConfig where name='scansEnabled_options'");
303
if($optScanEnabled != '0' && $optScanEnabled != '1'){
@@ -533,7 +535,7 @@ class wordfence {
533
}
534
535
if(! is_array($returnArr)){
536
- error_log("Function $func did not return an array and did not generate an error.");
537
$returnArr = array();
538
}
539
if(isset($returnArr['nonce'])){
@@ -615,7 +617,7 @@ class wordfence {
615
$user = get_user_by('email', $_POST['user_login']);
616
if($user){
617
if(wfConfig::get('alertOn_lostPasswdForm')){
618
- wordfence::alert("Password recovery attempted", "Someone tried to recover the password for user with email address: $email", $IP);
619
}
620
}
621
if(wfConfig::get('loginSecurityEnabled')){
@@ -647,6 +649,9 @@ class wordfence {
647
public static function veryFirstAction(){
648
$wfFunc = @$_GET['_wfsf'];
649
if($wfFunc == 'unlockEmail'){
650
$numTries = get_transient('wordfenceUnlockTries');
651
if($numTries > 10){
652
echo "<html><body><h1>Please wait 3 minutes and try again</h1><p>You have used this form too much. Please wait 3 minutes and try again.</p></body></html>";
@@ -689,7 +694,7 @@ class wordfence {
689
));
690
wp_mail($email, "Unlock email requested", $content, "Content-Type: text/html");
691
}
692
- echo "<html><body><h1>Your request was received</h1><p>We received a request to email \"" . htmlspecialchars($email, ENT_QUOTES, 'UTF-8') . "\" instructions to unlock their access. If that is the email address of a site administrator or someone on the Wordfence alert list, then they have been emailed instructions on how to regain access to this sytem. The instructions we sent will expire 30 minutes from now.</body></html>";
693
exit();
694
} else if($wfFunc == 'unlockAccess'){
695
if(! preg_match('/^\d+\.\d+\.\d+\.\d+#x2F;', get_transient('wfunlock_' . $_GET['key']))){
@@ -1009,7 +1014,7 @@ class wordfence {
1009
throw new Exception("We could not fetch a core WordPress file from the Wordfence API.");
1010
}
1011
} catch (Exception $e){
1012
- return array('errorMsg' => htmlentities($e->getMessage()));
1013
}
1014
}
1015
public static function ajax_loadAvgSitePerf_callback(){
@@ -1024,8 +1029,8 @@ class wordfence {
1024
if(! wfConfig::get('isPaid')){
1025
return array('errorMsg' => 'Cellphone Sign-in is only available to paid members. <a href="https://www.wordfence.com/wordfence-signup/" target="_blank">Click here to upgrade now.</a>');
1026
}
1027
- $username = $_POST['username'];
1028
- $phone = $_POST['phone'];
1029
$user = get_user_by('login', $username);
1030
if(! $user){
1031
return array('errorMsg' => "The username you specified does not exist.");
@@ -1037,12 +1042,12 @@ class wordfence {
1037
try {
1038
$codeResult = $api->call('twoFactor_verification', array(), array('phone' => $phone));
1039
} catch(Exception $e){
1040
- return array('errorMsg' => "Could not contact Wordfence servers to generate a verification code: " . htmlentities($e->getMessage()) );
1041
}
1042
if(isset($codeResult['ok']) && $codeResult['ok']){
1043
$code = $codeResult['code'];
1044
} else if(isset($codeResult['errorMsg']) && $codeResult['errorMsg']){
1045
- return array('errorMsg' => htmlentities($codeResult['errorMsg']));
1046
} else {
1047
return array('errorMsg' => "We could not generate a verification code.");
1048
}
@@ -1055,8 +1060,8 @@ class wordfence {
1055
);
1056
}
1057
public static function ajax_twoFacActivate_callback(){
1058
- $userID = $_POST['userID'];
1059
- $code = $_POST['code'];
1060
$twoFactorUsers = wfConfig::get_ser('twoFactorUsers', array());
1061
if(! is_array($twoFactorUsers)){
1062
$twoFactorUsers = array();
@@ -1071,7 +1076,7 @@ class wordfence {
1071
$user = $twoFactorUsers[$i];
1072
break;
1073
} else {
1074
- return array('errorMsg' => "That is not the correct code. Please look for an SMS containing an activation code on the phone with number: " . htmlentities($twoFactorUsers[$i][1]) );
1075
}
1076
}
1077
}
@@ -1281,7 +1286,7 @@ class wordfence {
1281
if($r['type'] == 'error'){
1282
$content .= "\n";
1283
}
1284
- $content .= date(DATE_RFC822, $r['ctime'] + $timeOffset) . '::' . sprintf('%.4f', $r['ctime']) . ':' . $r['level'] . ':' . $r['type'] . '::' . $r['msg'] . "\n";
1285
}
1286
$content .= "\n\n";
1287
@@ -1312,7 +1317,7 @@ class wordfence {
1312
throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free API key.");
1313
}
1314
} catch(Exception $e){
1315
- return array('errorMsg' => "Could not fetch free API key from Wordfence: " . htmlentities($e->getMessage()));
1316
}
1317
return array('ok' => 1);
1318
}
@@ -1622,7 +1627,7 @@ class wordfence {
1622
}
1623
}
1624
if(sizeof($badEmails) > 0){
1625
- return array('errorMsg' => "The following emails are invalid: " . htmlentities(implode(', ', $badEmails)) );
1626
}
1627
$opts['alertEmails'] = implode(',', $emails);
1628
} else {
@@ -1643,7 +1648,7 @@ class wordfence {
1643
}
1644
}
1645
if(sizeof($badWhiteIPs) > 0){
1646
- return array('errorMsg' => "Please make sure you separate your IP addresses with commas. The following whitelisted IP addresses are invalid: " . htmlentities(implode(', ', $badWhiteIPs)) );
1647
}
1648
$opts['whitelisted'] = implode(',', $whiteIPs);
1649
} else {
@@ -1680,7 +1685,7 @@ class wordfence {
1680
}
1681
1682
if(sizeof($invalidUsers) > 0){
1683
- return array('errorMsg' => "The following users you selected to ignore in live traffic reports are not valid on this system: " . htmlentities(implode(', ', $invalidUsers)) );
1684
}
1685
if(sizeof($validUsers) > 0){
1686
$opts['liveTraf_ignoreUsers'] = implode(',', $validUsers);
@@ -1700,7 +1705,7 @@ class wordfence {
1700
}
1701
}
1702
if(sizeof($invalidIPs) > 0){
1703
- return array('errorMsg' => "The following IPs you selected to ignore in live traffic reports are not valid: " . htmlentities(implode(', ', $invalidIPs)) );
1704
}
1705
if(sizeof($validIPs) > 0){
1706
$opts['liveTraf_ignoreIPs'] = implode(',', $validIPs);
@@ -1757,7 +1762,7 @@ class wordfence {
1757
throw new Exception("We could not understand the Wordfence server's response because it did not contain an 'ok' and 'apiKey' element.");
1758
}
1759
} catch(Exception $e){
1760
- return array('errorMsg' => "Your options have been saved, but we encountered a problem. You left your API key blank, so we tried to get you a free API key from the Wordfence servers. However we encountered a problem fetching the free key: " . htmlentities($e->getMessage()) );
1761
}
1762
} else if($opts['apiKey'] != wfConfig::get('apiKey')){
1763
$api = new wfAPI($opts['apiKey'], wfUtils::getWPVersion());
@@ -1774,7 +1779,7 @@ class wordfence {
1774
throw new Exception("We could not understand the Wordfence API server reply when updating your API key.");
1775
}
1776
} catch (Exception $e){
1777
- return array('errorMsg' => "Your options have been saved. However we noticed you changed your API key and we tried to verify it with the Wordfence servers and received an error: " . htmlentities($e->getMessage()) );
1778
}
1779
} else {
1780
$api = new wfAPI($opts['apiKey'], wfUtils::getWPVersion());
@@ -1853,7 +1858,7 @@ class wordfence {
1853
}
1854
$clientIP = wfUtils::inet_aton(wfUtils::getIP());
1855
if($ip1 <= $clientIP && $ip2 >= $clientIP){
1856
- return array('err' => 1, 'errorMsg' => "You are trying to block yourself. Your IP address is " . htmlentities(wfUtils::getIP()) . " which falls into the range " . htmlentities($ipRange) . ". This blocking action has been cancelled so that you don't block yourself from your website.");
1857
}
1858
$ipRange = $ip1 . '-' . $ip2;
1859
}
@@ -1881,7 +1886,7 @@ class wordfence {
1881
return array('err' => 1, 'errorMsg' => "You can't block your own IP address.");
1882
}
1883
if(self::getLog()->isWhitelisted($IP)){
1884
- return array('err' => 1, 'errorMsg' => "The IP address " . htmlentities($IP) . " 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.");
1885
}
1886
if(wfConfig::get('neverBlockBG') != 'treatAsOtherCrawlers'){ //Either neverBlockVerified or neverBlockUA is selected which means the user doesn't want to block google
1887
if(wfCrawl::verifyCrawlerPTR('/\.googlebot\.com#x2F;i', $IP)){
@@ -1956,7 +1961,7 @@ class wordfence {
1956
$issues = new wfIssues();
1957
$jsonData = array(
1958
'serverTime' => $serverTime,
1959
- 'msg' => $wfdb->querySingle("select msg from $p"."wfStatus where level < 3 order by ctime desc limit 1")
1960
);
1961
$events = array();
1962
$alsoGet = $_POST['alsoGet'];
@@ -2001,13 +2006,14 @@ class wordfence {
2001
return array('ok' => 1, 'email' => $email);
2002
}
2003
public static function ajax_bulkOperation_callback(){
2004
- $op = $_POST['op'];
2005
if($op == 'del' || $op == 'repair'){
2006
$ids = $_POST['ids'];
2007
$filesWorkedOn = 0;
2008
$errors = array();
2009
$issues = new wfIssues();
2010
foreach($ids as $id){
2011
$issue = $issues->getIssueByID($id);
2012
if(! $issue){
2013
$errors[] = "Could not delete one of the files because we could not find the issue. Perhaps it's been resolved?";
@@ -2017,7 +2023,7 @@ class wordfence {
2017
$localFile = ABSPATH . '/' . preg_replace('/^[\.\/]+/', '', $file);
2018
$localFile = realpath($localFile);
2019
if(strpos($localFile, ABSPATH) !== 0){
2020
- $errors[] = "An invalid file was requested: " . htmlentities($file);
2021
continue;
2022
}
2023
if($op == 'del'){
@@ -2026,7 +2032,7 @@ class wordfence {
2026
$filesWorkedOn++;
2027
} else {
2028
$err = error_get_last();
2029
- $errors[] = "Could not delete file " . htmlentities($file) . ". Error was: " . htmlentities($err['message']);
2030
}
2031
} else if($op == 'repair'){
2032
$dat = $issue['data'];
@@ -2035,21 +2041,21 @@ class wordfence {
2035
$errors[] = $result['cerrorMsg'];
2036
continue;
2037
} else if(! $result['fileContent']){
2038
- $errors[] = "We could not get the original file of " . htmlentities($file) . " to do a repair.";
2039
continue;
2040
}
2041
2042
if(preg_match('/\.\./', $file)){
2043
- $errors[] = "An invalid file " . htmlentities($file) . " was specified for repair.";
2044
continue;
2045
}
2046
$fh = fopen($localFile, 'w');
2047
if(! $fh){
2048
$err = error_get_last();
2049
if(preg_match('/Permission denied/i', $err['message'])){
2050
- $errMsg = "You don't have permission to repair " . htmlentities($file) . ". You need to either fix the file manually using FTP or change the file permissions and ownership so that your web server has write access to repair the file.";
2051
} else {
2052
- $errMsg = "We could not write to " . htmlentities($file) . ". The error was: " . $err['message'];
2053
}
2054
$errors[] = $errMsg;
2055
continue;
@@ -2059,7 +2065,7 @@ class wordfence {
2059
flock($fh, LOCK_UN);
2060
fclose($fh);
2061
if($bytes < 1){
2062
- $errors[] = "We could not write to " . htmlentities($file) . ". ($bytes bytes written) You may not have permission to modify files on your WordPress server.";
2063
continue;
2064
}
2065
$filesWorkedOn++;
@@ -2090,7 +2096,7 @@ class wordfence {
2090
}
2091
}
2092
public static function ajax_deleteFile_callback(){
2093
- $issueID = $_POST['issueID'];
2094
$wfIssues = new wfIssues();
2095
$issue = $wfIssues->getIssueByID($issueID);
2096
if(! $issue){
@@ -2114,11 +2120,11 @@ class wordfence {
2114
);
2115
} else {
2116
$err = error_get_last();
2117
- return array('errorMsg' => "Could not delete file " . htmlentities($file) . ". The error was: " . htmlentities($err['message']));
2118
}
2119
}
2120
public static function ajax_restoreFile_callback(){
2121
- $issueID = $_POST['issueID'];
2122
$wfIssues = new wfIssues();
2123
$issue = $wfIssues->getIssueByID($issueID);
2124
if(! $issue){
@@ -2164,7 +2170,7 @@ class wordfence {
2164
self::status(4, 'info', "Ajax request received to start scan.");
2165
$err = wfScanEngine::startScan();
2166
if($err){
2167
- return array('errorMsg' => htmlentities($err));
2168
} else {
2169
return array("ok" => 1);
2170
}
@@ -2343,7 +2349,7 @@ EOL;
2343
return ($a['ctime'] < $b['ctime']) ? -1 : 1;
2344
}
2345
public static function wfFunc_view(){
2346
- $localFile = ABSPATH . '/' . preg_replace('/^(?:\.\.|[\/]+)/', '', $_GET['file']);
2347
if(strpos($localFile, '..') !== false){
2348
echo "Invalid file requested. (Relative paths not allowed)";
2349
exit();
@@ -2386,7 +2392,7 @@ EOL;
2386
2387
$result = self::getWPFileContent($_GET['file'], $_GET['cType'], $_GET['cName'], $_GET['cVersion']);
2388
if( isset( $result['errorMsg'] ) && $result['errorMsg']){
2389
- echo htmlentities($result['errorMsg']);
2390
exit(0);
2391
} else if(! $result['fileContent']){
2392
echo "We could not get the contents of the original file to do a comparison.";
@@ -2483,7 +2489,7 @@ EOL;
2483
$activationError = substr($activationError, 0, 400) . '...[output truncated]';
2484
}
2485
if($activationError){
2486
- echo '<div id="wordfenceConfigWarning" class="updated fade"><p><strong>Wordfence generated an error on activation. The output we received during activation was:</strong> ' . htmlspecialchars($activationError) . '</p></div>';
2487
}
2488
delete_option('wf_plugin_act_error');
2489
}
298
$db->queryWriteIgnoreError("alter table $prefix"."wfLockedOut modify column blockedTime bigint signed NOT NULL");
299
$db->queryWriteIgnoreError("drop table if exists $prefix"."wfFileQueue");
300
$db->queryWriteIgnoreError("drop table if exists $prefix"."wfFileChanges");
301
+ //Adding primary key to this table because some backup apps use primary key during backup.
302
+ $db->queryWriteIgnoreError("alter table wp_wfStatus add id bigint UNSIGNED NOT NULL auto_increment PRIMARY KEY");
303
304
$optScanEnabled = $db->querySingle("select val from $prefix"."wfConfig where name='scansEnabled_options'");
305
if($optScanEnabled != '0' && $optScanEnabled != '1'){
535
}
536
537
if(! is_array($returnArr)){
538
+ error_log("Function " . wp_kses($func, array()) . " did not return an array and did not generate an error.");
539
$returnArr = array();
540
}
541
if(isset($returnArr['nonce'])){
617
$user = get_user_by('email', $_POST['user_login']);
618
if($user){
619
if(wfConfig::get('alertOn_lostPasswdForm')){
620
+ wordfence::alert("Password recovery attempted", "Someone tried to recover the password for user with email address: " . wp_kses($email, array()), $IP);
621
}
622
}
623
if(wfConfig::get('loginSecurityEnabled')){
649
public static function veryFirstAction(){
650
$wfFunc = @$_GET['_wfsf'];
651
if($wfFunc == 'unlockEmail'){
652
+ if(! wp_verify_nonce(@$_POST['nonce'], 'wf-form')){
653
+ die("Sorry but your browser sent an invalid security token when trying to use this form.");
654
+ }
655
$numTries = get_transient('wordfenceUnlockTries');
656
if($numTries > 10){
657
echo "<html><body><h1>Please wait 3 minutes and try again</h1><p>You have used this form too much. Please wait 3 minutes and try again.</p></body></html>";
694
));
695
wp_mail($email, "Unlock email requested", $content, "Content-Type: text/html");
696
}
697
+ echo "<html><body><h1>Your request was received</h1><p>We received a request to email \"" . wp_kses($email, array()) . "\" instructions to unlock their access. If that is the email address of a site administrator or someone on the Wordfence alert list, then they have been emailed instructions on how to regain access to this sytem. The instructions we sent will expire 30 minutes from now.</body></html>";
698
exit();
699
} else if($wfFunc == 'unlockAccess'){
700
if(! preg_match('/^\d+\.\d+\.\d+\.\d+#x2F;', get_transient('wfunlock_' . $_GET['key']))){
1014
throw new Exception("We could not fetch a core WordPress file from the Wordfence API.");
1015
}
1016
} catch (Exception $e){
1017
+ return array('errorMsg' => wp_kses($e->getMessage(), array()));
1018
}
1019
}
1020
public static function ajax_loadAvgSitePerf_callback(){
1029
if(! wfConfig::get('isPaid')){
1030
return array('errorMsg' => 'Cellphone Sign-in is only available to paid members. <a href="https://www.wordfence.com/wordfence-signup/" target="_blank">Click here to upgrade now.</a>');
1031
}
1032
+ $username = sanitize_text_field($_POST['username']);
1033
+ $phone = sanitize_text_field($_POST['phone']);
1034
$user = get_user_by('login', $username);
1035
if(! $user){
1036
return array('errorMsg' => "The username you specified does not exist.");
1042
try {
1043
$codeResult = $api->call('twoFactor_verification', array(), array('phone' => $phone));
1044
} catch(Exception $e){
1045
+ return array('errorMsg' => "Could not contact Wordfence servers to generate a verification code: " . wp_kses($e->getMessage(), array()) );
1046
}
1047
if(isset($codeResult['ok']) && $codeResult['ok']){
1048
$code = $codeResult['code'];
1049
} else if(isset($codeResult['errorMsg']) && $codeResult['errorMsg']){
1050
+ return array('errorMsg' => wp_kses($codeResult['errorMsg'], array()));
1051
} else {
1052
return array('errorMsg' => "We could not generate a verification code.");
1053
}
1060
);
1061
}
1062
public static function ajax_twoFacActivate_callback(){
1063
+ $userID = sanitize_text_field($_POST['userID']);
1064
+ $code = sanitize_text_field($_POST['code']);
1065
$twoFactorUsers = wfConfig::get_ser('twoFactorUsers', array());
1066
if(! is_array($twoFactorUsers)){
1067
$twoFactorUsers = array();
1076
$user = $twoFactorUsers[$i];
1077
break;
1078
} else {
1079
+ return array('errorMsg' => "That is not the correct code. Please look for an SMS containing an activation code on the phone with number: " . wp_kses($twoFactorUsers[$i][1], array()) );
1080
}
1081
}
1082
}
1286
if($r['type'] == 'error'){
1287
$content .= "\n";
1288
}
1289
+ $content .= date(DATE_RFC822, $r['ctime'] + $timeOffset) . '::' . sprintf('%.4f', $r['ctime']) . ':' . $r['level'] . ':' . $r['type'] . '::' . wp_kses_data( (string) $r['msg']) . "\n";
1290
}
1291
$content .= "\n\n";
1292
1317
throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free API key.");
1318
}
1319
} catch(Exception $e){
1320
+ return array('errorMsg' => "Could not fetch free API key from Wordfence: " . wp_kses($e->getMessage(), array()));
1321
}
1322
return array('ok' => 1);
1323
}
1627
}
1628
}
1629
if(sizeof($badEmails) > 0){
1630
+ return array('errorMsg' => "The following emails are invalid: " . wp_kses(implode(', ', $badEmails), array()) );
1631
}
1632
$opts['alertEmails'] = implode(',', $emails);
1633
} else {
1648
}
1649
}
1650
if(sizeof($badWhiteIPs) > 0){
1651
+ return array('errorMsg' => "Please make sure you separate your IP addresses with commas. The following whitelisted IP addresses are invalid: " . wp_kses(implode(', ', $badWhiteIPs), array()) );
1652
}
1653
$opts['whitelisted'] = implode(',', $whiteIPs);
1654
} else {
1685
}
1686
1687
if(sizeof($invalidUsers) > 0){
1688
+ return array('errorMsg' => "The following users you selected to ignore in live traffic reports are not valid on this system: " . wp_kses(implode(', ', $invalidUsers), array()) );
1689
}
1690
if(sizeof($validUsers) > 0){
1691
$opts['liveTraf_ignoreUsers'] = implode(',', $validUsers);
1705
}
1706
}
1707
if(sizeof($invalidIPs) > 0){
1708
+ return array('errorMsg' => "The following IPs you selected to ignore in live traffic reports are not valid: " . wp_kses(implode(', ', $invalidIPs), array()) );
1709
}
1710
if(sizeof($validIPs) > 0){
1711
$opts['liveTraf_ignoreIPs'] = implode(',', $validIPs);
1762
throw new Exception("We could not understand the Wordfence server's response because it did not contain an 'ok' and 'apiKey' element.");
1763
}
1764
} catch(Exception $e){
1765
+ return array('errorMsg' => "Your options have been saved, but we encountered a problem. You left your API key blank, so we tried to get you a free API key from the Wordfence servers. However we encountered a problem fetching the free key: " . wp_kses($e->getMessage(), array()) );
1766
}
1767
} else if($opts['apiKey'] != wfConfig::get('apiKey')){
1768
$api = new wfAPI($opts['apiKey'], wfUtils::getWPVersion());
1779
throw new Exception("We could not understand the Wordfence API server reply when updating your API key.");
1780
}
1781
} catch (Exception $e){
1782
+ return array('errorMsg' => "Your options have been saved. However we noticed you changed your API key and we tried to verify it with the Wordfence servers and received an error: " . wp_kses($e->getMessage(), array()) );
1783
}
1784
} else {
1785
$api = new wfAPI($opts['apiKey'], wfUtils::getWPVersion());
1858
}
1859
$clientIP = wfUtils::inet_aton(wfUtils::getIP());
1860
if($ip1 <= $clientIP && $ip2 >= $clientIP){
1861
+ return array('err' => 1, 'errorMsg' => "You are trying to block yourself. Your IP address is " . wp_kses(wfUtils::getIP(), array()) . " which falls into the range " . wp_kses($ipRange, array()) . ". This blocking action has been cancelled so that you don't block yourself from your website.");
1862
}
1863
$ipRange = $ip1 . '-' . $ip2;
1864
}
1886
return array('err' => 1, 'errorMsg' => "You can't block your own IP address.");
1887
}
1888
if(self::getLog()->isWhitelisted($IP)){
1889
+ 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.");
1890
}
1891
if(wfConfig::get('neverBlockBG') != 'treatAsOtherCrawlers'){ //Either neverBlockVerified or neverBlockUA is selected which means the user doesn't want to block google
1892
if(wfCrawl::verifyCrawlerPTR('/\.googlebot\.com#x2F;i', $IP)){
1961
$issues = new wfIssues();
1962
$jsonData = array(
1963
'serverTime' => $serverTime,
1964
+ 'msg' => wp_kses_data( (string) $wfdb->querySingle("select msg from $p"."wfStatus where level < 3 order by ctime desc limit 1"))
1965
);
1966
$events = array();
1967
$alsoGet = $_POST['alsoGet'];
2006
return array('ok' => 1, 'email' => $email);
2007
}
2008
public static function ajax_bulkOperation_callback(){
2009
+ $op = sanitize_text_field($_POST['op']);
2010
if($op == 'del' || $op == 'repair'){
2011
$ids = $_POST['ids'];
2012
$filesWorkedOn = 0;
2013
$errors = array();
2014
$issues = new wfIssues();
2015
foreach($ids as $id){
2016
+ $id = intval($id); //Make sure input is a number.
2017
$issue = $issues->getIssueByID($id);
2018
if(! $issue){
2019
$errors[] = "Could not delete one of the files because we could not find the issue. Perhaps it's been resolved?";
2023
$localFile = ABSPATH . '/' . preg_replace('/^[\.\/]+/', '', $file);
2024
$localFile = realpath($localFile);
2025
if(strpos($localFile, ABSPATH) !== 0){
2026
+ $errors[] = "An invalid file was requested: " . wp_kses($file, arra());
2027
continue;
2028
}
2029
if($op == 'del'){
2032
$filesWorkedOn++;
2033
} else {
2034
$err = error_get_last();
2035
+ $errors[] = "Could not delete file " . wp_kses($file, array()) . ". Error was: " . wp_kses($err['message'], array());
2036
}
2037
} else if($op == 'repair'){
2038
$dat = $issue['data'];
2041
$errors[] = $result['cerrorMsg'];
2042
continue;
2043
} else if(! $result['fileContent']){
2044
+ $errors[] = "We could not get the original file of " . wp_kses($file, array()) . " to do a repair.";
2045
continue;
2046
}
2047
2048
if(preg_match('/\.\./', $file)){
2049
+ $errors[] = "An invalid file " . wp_kses($file, array()) . " was specified for repair.";
2050
continue;
2051
}
2052
$fh = fopen($localFile, 'w');
2053
if(! $fh){
2054
$err = error_get_last();
2055
if(preg_match('/Permission denied/i', $err['message'])){
2056
+ $errMsg = "You don't have permission to repair " . wp_kses($file, array()) . ". You need to either fix the file manually using FTP or change the file permissions and ownership so that your web server has write access to repair the file.";
2057
} else {
2058
+ $errMsg = "We could not write to " . wp_kses($file, array()) . ". The error was: " . $err['message'];
2059
}
2060
$errors[] = $errMsg;
2061
continue;
2065
flock($fh, LOCK_UN);
2066
fclose($fh);
2067
if($bytes < 1){
2068
+ $errors[] = "We could not write to " . wp_kses($file, array()) . ". ($bytes bytes written) You may not have permission to modify files on your WordPress server.";
2069
continue;
2070
}
2071
$filesWorkedOn++;
2096
}
2097
}
2098
public static function ajax_deleteFile_callback(){
2099
+ $issueID = intval($_POST['issueID']);
2100
$wfIssues = new wfIssues();
2101
$issue = $wfIssues->getIssueByID($issueID);
2102
if(! $issue){
2120
);
2121
} else {
2122
$err = error_get_last();
2123
+ return array('errorMsg' => "Could not delete file " . wp_kses($file, array()) . ". The error was: " . wp_kses($err['message'], array()));
2124
}
2125
}
2126
public static function ajax_restoreFile_callback(){
2127
+ $issueID = intval($_POST['issueID']);
2128
$wfIssues = new wfIssues();
2129
$issue = $wfIssues->getIssueByID($issueID);
2130
if(! $issue){
2170
self::status(4, 'info', "Ajax request received to start scan.");
2171
$err = wfScanEngine::startScan();
2172
if($err){
2173
+ return array('errorMsg' => wp_kses($err, array()));
2174
} else {
2175
return array("ok" => 1);
2176
}
2349
return ($a['ctime'] < $b['ctime']) ? -1 : 1;
2350
}
2351
public static function wfFunc_view(){
2352
+ $localFile = ABSPATH . '/' . preg_replace('/^(?:\.\.|[\/]+)/', '', sanitize_text_field($_GET['file']));
2353
if(strpos($localFile, '..') !== false){
2354
echo "Invalid file requested. (Relative paths not allowed)";
2355
exit();
2392
2393
$result = self::getWPFileContent($_GET['file'], $_GET['cType'], $_GET['cName'], $_GET['cVersion']);
2394
if( isset( $result['errorMsg'] ) && $result['errorMsg']){
2395
+ echo wp_kses($result['errorMsg'], array());
2396
exit(0);
2397
} else if(! $result['fileContent']){
2398
echo "We could not get the contents of the original file to do a comparison.";
2489
$activationError = substr($activationError, 0, 400) . '...[output truncated]';
2490
}
2491
if($activationError){
2492
+ echo '<div id="wordfenceConfigWarning" class="updated fade"><p><strong>Wordfence generated an error on activation. The output we received during activation was:</strong> ' . wp_kses($activationError, array()) . '</p></div>';
2493
}
2494
delete_option('wf_plugin_act_error');
2495
}
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
3
Tags: wordpress, security, performance, speed, caching, cache, caching plugin, wordpress cache, wordpress caching, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure, two factor, cellphone sign-in, cellphone signin, cellphone, twofactor, security, secure, htaccess, login, log, users, login alerts, lock, chmod, maintenance, plugin, private, privacy, protection, permissions, 503, base64, injection, code, encode, script, attack, hack, hackers, block, blocked, prevent, prevention, RFI, XSS, CRLF, CSRF, SQL Injection, vulnerability, website security, WordPress security, security log, logging, HTTP log, error log, login security, personal security, infrastructure security, firewall security, front-end security, web server security, proxy security, reverse proxy security, secure website, secure login, two factor security, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm, woocommerce support, woocommerce caching
4
Requires at least: 3.3.1
5
Tested up to: 4.0
6
- Stable tag: 5.2.4
7
8
Wordfence Security is a free enterprise class security and performance plugin that makes your site up to 50 times faster and more secure.
9
@@ -163,6 +163,23 @@ cause a security hole on your site.
163
164
== Changelog ==
165
166
= 5.2.4 =
167
* Security release. Upgrade immediately.
168
* This release fixes an XSS vunlerability on Wordfence "view all traffic from IP" page.
3
Tags: wordpress, security, performance, speed, caching, cache, caching plugin, wordpress cache, wordpress caching, wordpress security, security plugin, secure, anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence, securty, secrity, secure, two factor, cellphone sign-in, cellphone signin, cellphone, twofactor, security, secure, htaccess, login, log, users, login alerts, lock, chmod, maintenance, plugin, private, privacy, protection, permissions, 503, base64, injection, code, encode, script, attack, hack, hackers, block, blocked, prevent, prevention, RFI, XSS, CRLF, CSRF, SQL Injection, vulnerability, website security, WordPress security, security log, logging, HTTP log, error log, login security, personal security, infrastructure security, firewall security, front-end security, web server security, proxy security, reverse proxy security, secure website, secure login, two factor security, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm, woocommerce support, woocommerce caching
4
Requires at least: 3.3.1
5
Tested up to: 4.0
6
+ Stable tag: 5.2.5
7
8
Wordfence Security is a free enterprise class security and performance plugin that makes your site up to 50 times faster and more secure.
9
163
164
== Changelog ==
165
166
+ = 5.2.5 =
167
+ * Security release. Update immediately. Thanks to Julio Potier.
168
+ * Code hardening including improved sanitization and an additional nonce for unlock email form. Special thanks to Ryan Satterfield for the hard work.
169
+ * Stability of auto-update improved for LiteSpeed customers. We auto-detect if you don't have E=noabort:1 in your .htaccess and give you instructions.
170
+ * Auto-update also disabled now for LiteSpeed customers who don't have E=noabort:1 and you will get an email alert with an explanation.
171
+ * Fixed a bug that may cause you to have advanced blocking patterns disabled with falcon engine enabled that should not be disabled.
172
+ * Removed a benign warning in wfCache.php.
173
+ * Added clarity to the banned URL option on the options page. All URL's must be relative.
174
+ * Added a primary key to the wp_wfStatus table which is required for certain incremental backup plugins and utilities.
175
+ * Fixed advanced country blocking which was not correctly displaying advanced options.
176
+ * Migrated to using wp_kses() for sanitization.
177
+ * Prevent IP spoofing in default Wordfence IP configuration.
178
+ * Change explanations of how Wordfence gets IP's to make it clear which to use to prevent spoofing.
179
+ * Make it clear that the option to have IP's immediately blocked when they access a URL requires relative URL's starting with a forward slash.
180
+ * Whitelist Sucuri's scanning IP addresses which were getting blocked because they triggered Wordfence blocking during a scan.
181
+ * Improved Wordfence's code that acquires the visitor IP to block certain spoofing attacks, be more platform agnostic and deal with visits from private IP's more elegantly.
182
+
183
= 5.2.4 =
184
* Security release. Upgrade immediately.
185
* This release fixes an XSS vunlerability on Wordfence "view all traffic from IP" page.
wordfence.php CHANGED
@@ -4,13 +4,13 @@ Plugin Name: Wordfence Security
4
Plugin URI: http://www.wordfence.com/
5
Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
6
Author: Wordfence
7
- Version: 5.2.4
8
Author URI: http://www.wordfence.com/
9
*/
10
if(defined('WP_INSTALLING') && WP_INSTALLING){
11
return;
12
}
13
- define('WORDFENCE_VERSION', '5.2.4');
14
if(get_option('wordfenceActivated') != 1){
15
add_action('activated_plugin','wordfence_save_activation_error'); function wordfence_save_activation_error(){ update_option('wf_plugin_act_error', ob_get_contents()); }
16
}
4
Plugin URI: http://www.wordfence.com/
5
Description: Wordfence Security - Anti-virus, Firewall and High Speed Cache
6
Author: Wordfence
7
+ Version: 5.2.5
8
Author URI: http://www.wordfence.com/
9
*/
10
if(defined('WP_INSTALLING') && WP_INSTALLING){
11
return;
12
}
13
+ define('WORDFENCE_VERSION', '5.2.5');
14
if(get_option('wordfenceActivated') != 1){
15
add_action('activated_plugin','wordfence_save_activation_error'); function wordfence_save_activation_error(){ update_option('wf_plugin_act_error', ob_get_contents()); }
16
}