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 | 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 +3 -3
- lib/diffResult.php +3 -3
- lib/menu_countryBlocking.php +4 -4
- lib/menu_options.php +14 -7
- lib/menu_rangeBlocking.php +1 -1
- lib/menu_whois.php +2 -2
- lib/viewFullActivityLog.php +1 -1
- lib/wfCache.php +3 -3
- lib/wfConfig.php +11 -1
- lib/wfLog.php +7 -1
- lib/wfSchema.php +1 -0
- lib/wfUnlockMsg.php +1 -0
- lib/wfUtils.php +63 -75
- lib/wfViewResult.php +1 -1
- lib/wordfenceClass.php +43 -37
- readme.txt +18 -1
- wordfence.php +2 -2
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
|
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
|
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
|
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>" .
|
25 |
} else if($cType == 'plugin'){
|
26 |
-
echo "Plugin File</td></tr><tr><td>Plugin Name:</td><td>" .
|
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
|
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
|
49 |
then redirect that user to
|
50 |
-
<input type="text" id="wfBypassRedirDest" value="<?php echo
|
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
|
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"> </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'); ?> /> Regular scans ensure your site stays secure.</td></tr>
|
49 |
<tr><td colspan="2"> </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'); ?> /> Automatically updates Wordfence to the newest version within 24 hours of a new release
|
|
|
|
|
|
|
|
|
|
|
51 |
<tr><td colspan="2"> </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" /> <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="">
|
68 |
-
<option value="REMOTE_ADDR"<?php $w->sel('howGetIPs', 'REMOTE_ADDR'); ?>>Use PHP's built in REMOTE_ADDR
|
69 |
-
<option value="
|
70 |
-
<option value="
|
71 |
-
<option value="HTTP_CF_CONNECTING_IP"<?php $w->sel('howGetIPs', 'HTTP_CF_CONNECTING_IP'); ?>>
|
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
|
|
|
|
|
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"> </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'); ?> /> Regular scans ensure your site stays secure.</td></tr>
|
49 |
<tr><td colspan="2"> </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'); ?> /> 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"> </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" /> <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
|
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" > (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();"> <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" > (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
|
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
|
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'] . '] ' .
|
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'] . '] ' . 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'] ?
|
158 |
-
$append .= "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('/\/[^\/]*$/', '', $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('/\/[^\/]*$/', '', $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
|
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 |
-
$
|
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" /> <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" /> <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 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
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 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
break;
|
165 |
}
|
166 |
}
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
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 |
-
|
178 |
}
|
179 |
-
wfConfig::set('IPGetFail', '');
|
180 |
}
|
181 |
-
|
|
|
|
|
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+)$/', $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+$/', '', $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+$/', '', $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+$/', '', $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+)$/', $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
|
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
|
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 \"" .
|
693 |
exit();
|
694 |
} else if($wfFunc == 'unlockAccess'){
|
695 |
if(! preg_match('/^\d+\.\d+\.\d+\.\d+$/', 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' =>
|
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: " .
|
1041 |
}
|
1042 |
if(isset($codeResult['ok']) && $codeResult['ok']){
|
1043 |
$code = $codeResult['code'];
|
1044 |
} else if(isset($codeResult['errorMsg']) && $codeResult['errorMsg']){
|
1045 |
-
return array('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: " .
|
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: " .
|
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: " .
|
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: " .
|
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: " .
|
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: " .
|
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: " .
|
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: " .
|
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 " .
|
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 " .
|
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$/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: " .
|
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 " .
|
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 " .
|
2039 |
continue;
|
2040 |
}
|
2041 |
|
2042 |
if(preg_match('/\.\./', $file)){
|
2043 |
-
$errors[] = "An invalid file " .
|
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 " .
|
2051 |
} else {
|
2052 |
-
$errMsg = "We could not write to " .
|
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 " .
|
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 " .
|
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' =>
|
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
|
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> ' .
|
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+$/', 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$/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.
|
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.
|
8 |
Author URI: http://www.wordfence.com/
|
9 |
*/
|
10 |
if(defined('WP_INSTALLING') && WP_INSTALLING){
|
11 |
return;
|
12 |
}
|
13 |
-
define('WORDFENCE_VERSION', '5.2.
|
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 |
}
|