Wordfence Security – Firewall & Malware Scan - Version 6.2.6

Version Description

  • Improvement: Improved formatting of attack data when it contains binary characters.
  • Improvement: Updated internal GeoIP database.
  • Improvement: Improved the ordering of rules in the malware scan so more specific rules are checked first.
  • Fix: Country blocking redirects are no longer allowed to be cached.
  • Fix: Fixed an issue with 2FA on multisite where the site could report URLs with different schemes depending on the state of plugin loading.
Download this release

Release Info

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

Code changes from version 6.2.5 to 6.2.6

css/main.css CHANGED
@@ -1237,4 +1237,8 @@ tr.wf-table-filters input {
1237
1238
.wordfenceWrap.wordfence-community {
1239
min-height: 760px;
1240
}
1237
1238
.wordfenceWrap.wordfence-community {
1239
min-height: 760px;
1240
+ }
1241
+
1242
+ .wf-hex-sequence {
1243
+ color: #587ECB;
1244
}
lib/GeoIP.dat CHANGED
Binary file
lib/GeoIPv6.dat CHANGED
Binary file
lib/menu_options.php CHANGED
@@ -422,7 +422,7 @@ $w = new wfConfig();
422
</tr>
423
<?php if ( wfConfig::get( 'isPaid' ) ) { ?>
424
<tr>
425
- <th>Scan public facing site for vulnerabilities?<a
426
href="http://docs.wordfence.com/en/Wordfence_options#Scan_public_facing_site"
427
target="_blank" class="wfhelp"></a></th>
428
<td><input type="checkbox" id="scansEnabled_public" class="wfConfigElem"
@@ -430,7 +430,7 @@ $w = new wfConfig();
430
</tr>
431
<?php } else { ?>
432
<tr>
433
- <th style="color: #F00;">Scan public facing site for vulnerabilities?<a
434
href="http://docs.wordfence.com/en/Wordfence_options#Scan_public_facing_site"
435
target="_blank" class="wfhelp"></a>(<a
436
href="https://www.wordfence.com/gnl1optPdOnly1/wordfence-signup/" target="_blank">Paid members only</a>)
@@ -440,7 +440,7 @@ $w = new wfConfig();
440
</tr>
441
<?php } ?>
442
<tr>
443
- <th>Scan for the HeartBleed vulnerability?<a
444
href="http://docs.wordfence.com/en/Wordfence_options#Scan_for_the_HeartBleed_vulnerability"
445
target="_blank" class="wfhelp"></a></th>
446
<td><input type="checkbox" id="scansEnabled_heartbleed" class="wfConfigElem"
422
</tr>
423
<?php if ( wfConfig::get( 'isPaid' ) ) { ?>
424
<tr>
425
+ <th>Scan public facing site for vulnerabilities<a
426
href="http://docs.wordfence.com/en/Wordfence_options#Scan_public_facing_site"
427
target="_blank" class="wfhelp"></a></th>
428
<td><input type="checkbox" id="scansEnabled_public" class="wfConfigElem"
430
</tr>
431
<?php } else { ?>
432
<tr>
433
+ <th style="color: #F00;">Scan public facing site for vulnerabilities<a
434
href="http://docs.wordfence.com/en/Wordfence_options#Scan_public_facing_site"
435
target="_blank" class="wfhelp"></a>(<a
436
href="https://www.wordfence.com/gnl1optPdOnly1/wordfence-signup/" target="_blank">Paid members only</a>)
440
</tr>
441
<?php } ?>
442
<tr>
443
+ <th>Scan for the HeartBleed vulnerability<a
444
href="http://docs.wordfence.com/en/Wordfence_options#Scan_for_the_HeartBleed_vulnerability"
445
target="_blank" class="wfhelp"></a></th>
446
<td><input type="checkbox" id="scansEnabled_heartbleed" class="wfConfigElem"
lib/wfLog.php CHANGED
@@ -1177,6 +1177,7 @@ class wfLog {
1177
exit();
1178
}
1179
private function redirect($URL){
1180
wp_redirect($URL, 302);
1181
exit();
1182
}
@@ -1850,7 +1851,7 @@ class wfLiveTrafficQuery {
1850
$limit = absint($this->getLimit());
1851
$offset = absint($this->getOffset());
1852
1853
- $wheres = array("h.action != 'logged:waf'");
1854
if ($startDate) {
1855
$wheres[] = $wpdb->prepare('h.ctime > %f', $startDate);
1856
}
1177
exit();
1178
}
1179
private function redirect($URL){
1180
+ wfUtils::doNotCache();
1181
wp_redirect($URL, 302);
1182
exit();
1183
}
1851
$limit = absint($this->getLimit());
1852
$offset = absint($this->getOffset());
1853
1854
+ $wheres = array("h.action != 'logged:waf'", "h.action != 'scan:detectproxy'");
1855
if ($startDate) {
1856
$wheres[] = $wpdb->prepare('h.ctime > %f', $startDate);
1857
}
lib/wfUtils.php CHANGED
@@ -658,9 +658,7 @@ class wfUtils {
658
return self::getCleanIPAndServerVar($ipsToCheck);
659
}
660
} else {
661
- $ipsToCheck = array(
662
- $connectionIP,
663
- );
664
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
665
$ipsToCheck[] = array($_SERVER['HTTP_X_FORWARDED_FOR'], 'HTTP_X_FORWARDED_FOR');
666
}
@@ -1094,7 +1092,8 @@ class wfUtils {
1094
}
1095
}
1096
public static function doNotCache(){
1097
- header("Cache-Control: no-cache, must-revalidate");
1098
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); //In the past
1099
if(! defined('DONOTCACHEPAGE')){ define('DONOTCACHEPAGE', true); }
1100
if(! defined('DONOTCACHEDB')){ define('DONOTCACHEDB', true); }
@@ -1335,6 +1334,74 @@ class wfUtils {
1335
$keys[$index] = $newKey;
1336
return array_combine($keys, array_values($array));
1337
}
1338
}
1339
1340
// GeoIP lib uses these as well
658
return self::getCleanIPAndServerVar($ipsToCheck);
659
}
660
} else {
661
+ $ipsToCheck = array($connectionIP);
662
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
663
$ipsToCheck[] = array($_SERVER['HTTP_X_FORWARDED_FOR'], 'HTTP_X_FORWARDED_FOR');
664
}
1092
}
1093
}
1094
public static function doNotCache(){
1095
+ header("Pragma: no-cache");
1096
+ header("Cache-Control: no-cache, must-revalidate, private");
1097
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); //In the past
1098
if(! defined('DONOTCACHEPAGE')){ define('DONOTCACHEPAGE', true); }
1099
if(! defined('DONOTCACHEDB')){ define('DONOTCACHEDB', true); }
1334
$keys[$index] = $newKey;
1335
return array_combine($keys, array_values($array));
1336
}
1337
+
1338
+ /**
1339
+ * Takes a string that may have characters that will be interpreted as invalid UTF-8 byte sequences and translates them into a string of the equivalent hex sequence.
1340
+ *
1341
+ * @param $string
1342
+ * @param bool $inline
1343
+ * @return string
1344
+ */
1345
+ public static function potentialBinaryStringToHTML($string, $inline = false) {
1346
+ $output = '';
1347
+
1348
+ if (!defined('ENT_SUBSTITUTE')) {
1349
+ define('ENT_SUBSTITUTE', 0);
1350
+ }
1351
+
1352
+ $span = '<span class="wf-hex-sequence">';
1353
+ if ($inline) {
1354
+ $span = '<span style="color:#587ECB">';
1355
+ }
1356
+
1357
+ for ($i = 0; $i < strlen($string); $i++) {
1358
+ $c = $string[$i];
1359
+ $b = ord($c);
1360
+ if ($b < 0x20) {
1361
+ $output .= $span . '\x' . str_pad(dechex($b), 2, '0', STR_PAD_LEFT) . '</span>';
1362
+ }
1363
+ else if ($b < 0x80) {
1364
+ $output .= htmlspecialchars($c, ENT_QUOTES, 'UTF-8');
1365
+ }
1366
+ else { //Assume multi-byte UTF-8
1367
+ $bytes = 0;
1368
+ $test = $b;
1369
+
1370
+ while (($test & 0x80) > 0) {
1371
+ $bytes++;
1372
+ $test = (($test << 1) & 0xff);
1373
+ }
1374
+
1375
+ $brokenUTF8 = ($i + $bytes > strlen($string) || $bytes == 1);
1376
+ if (!$brokenUTF8) { //Make sure we have all the bytes
1377
+ for ($n = 1; $n < $bytes; $n++) {
1378
+ $c2 = $string[$i + $n];
1379
+ $b2 = ord($c2);
1380
+ if (($b2 & 0xc0) != 0x80) {
1381
+ $brokenUTF8 = true;
1382
+ $bytes = $n;
1383
+ break;
1384
+ }
1385
+ }
1386
+ }
1387
+
1388
+ if ($brokenUTF8) {
1389
+ $bytes = min($bytes, strlen($string) - $i);
1390
+ for ($n = 0; $n < $bytes; $n++) {
1391
+ $c2 = $string[$i + $n];
1392
+ $b2 = ord($c2);
1393
+ $output .= $span . '\x' . str_pad(dechex($b2), 2, '0', STR_PAD_LEFT) . '</span>';
1394
+ }
1395
+ $i += ($bytes - 1);
1396
+ }
1397
+ else {
1398
+ $output .= htmlspecialchars(substr($string, $i, $bytes), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
1399
+ $i += ($bytes - 1);
1400
+ }
1401
+ }
1402
+ }
1403
+ return $output;
1404
+ }
1405
}
1406
1407
// GeoIP lib uses these as well
lib/wordfenceClass.php CHANGED
@@ -582,13 +582,25 @@ SQL
582
}
583
}
584
}
585
- public static function initProtection(){
586
- self::getLog()->initLogRequest();
587
- if(preg_match('/\/wp\-admin\/admin\-ajax\.php/', $_SERVER['REQUEST_URI'])){
588
- if(
589
- (isset($_GET['action']) && $_GET['action'] == 'revslider_show_image' && isset($_GET['img']) && preg_match('/\.php#x2F;i', $_GET['img'])) ||
590
- (isset($_POST['action']) && $_POST['action'] == 'revslider_show_image' && isset($_POST['img']) && preg_match('/\.php#x2F;i', $_POST['img']))
591
- ){
592
self::getLog()->do503(86400, "URL not allowed. Slider Revolution Hack attempt detected. #2");
593
exit(); //function above exits anyway
594
}
@@ -603,8 +615,8 @@ SQL
603
//Either there is no version in options or the version in options is greater and we need to run the upgrade
604
self::runInstall();
605
}
606
-
607
- self::initProtection();
608
609
//Fix wp_mail bug when $_SERVER['SERVER_NAME'] is undefined
610
add_filter('wp_mail_from', 'wordfence::fixWPMailFromAddress');
@@ -1027,6 +1039,8 @@ SQL
1027
public static function veryFirstAction() {
1028
/** @var wpdb $wpdb ; */
1029
global $wpdb;
1030
1031
$wfFunc = isset($_GET['_wfsf']) ? @$_GET['_wfsf'] : false;
1032
if($wfFunc == 'unlockEmail'){
582
}
583
}
584
}
585
+ public static function initProtection(){ //Basic protection during WAF learning period
586
+ if (preg_match('#/wp\-admin/admin\-ajax\.php$#i', $_SERVER['SCRIPT_FILENAME'])) {
587
+ $gAction = isset($_GET['action']) ? $_GET['action'] : '';
588
+ $pAction = isset($_POST['action']) ? $_POST['action'] : '';
589
+ if (
590
+ (($gAction == 'revslider_show_image' || $gAction == 'nopriv_revslider_show_image') && isset($_GET['img']) && preg_match('/\.php#x2F;i', $_GET['img'])) ||
591
+ (($pAction == 'revslider_show_image' || $pAction == 'nopriv_revslider_show_image') && isset($_POST['img']) && preg_match('/\.php#x2F;i', $_POST['img']))
592
+ ) {
593
+ self::getLog()->do503(86400, "URL not allowed. Slider Revolution Hack attempt detected. #2");
594
+ exit(); //function above exits anyway
595
+ }
596
+
597
+ if (
598
+ (
599
+ (($gAction == 'revslider_ajax_action' || $gAction == 'nopriv_revslider_ajax_action') && isset($_GET['client_action']) && $_GET['client_action'] == 'update_plugin') ||
600
+ (($pAction == 'revslider_ajax_action' || $pAction == 'nopriv_revslider_ajax_action') && isset($_POST['client_action']) && $_POST['client_action'] == 'update_plugin')
601
+ ) &&
602
+ !wfUtils::isAdmin()
603
+ ) {
604
self::getLog()->do503(86400, "URL not allowed. Slider Revolution Hack attempt detected. #2");
605
exit(); //function above exits anyway
606
}
615
//Either there is no version in options or the version in options is greater and we need to run the upgrade
616
self::runInstall();
617
}
618
+
619
+ self::getLog()->initLogRequest();
620
621
//Fix wp_mail bug when $_SERVER['SERVER_NAME'] is undefined
622
add_filter('wp_mail_from', 'wordfence::fixWPMailFromAddress');
1039
public static function veryFirstAction() {
1040
/** @var wpdb $wpdb ; */
1041
global $wpdb;
1042
+
1043
+ self::initProtection();
1044
1045
$wfFunc = isset($_GET['_wfsf']) ? @$_GET['_wfsf'] : false;
1046
if($wfFunc == 'unlockEmail'){
lib/wordfenceScanner.php CHANGED
@@ -322,7 +322,7 @@ class wordfenceScanner {
322
'ignoreP' => $this->path . $file,
323
'ignoreC' => $fileSum,
324
'shortMsg' => "File appears to be malicious: " . esc_html($file),
325
- 'longMsg' => "This file appears to be installed by a hacker to perform malicious activity. If you know about this file you can choose to ignore it to exclude it from future scans. The text we found in this file that matches a known malicious file is: <strong style=\"color: #F00;\">\"" . esc_html((strlen($matchString) > 200 ? substr($matchString, 0, 200) . '...' : $matchString)) . "\"</strong>. The infection type is: <strong>" . esc_html($rule[3]) . '</strong>.' . $extraMsg,
326
'data' => array_merge(array(
327
'file' => $file,
328
), $dataForFile),
322
'ignoreP' => $this->path . $file,
323
'ignoreC' => $fileSum,
324
'shortMsg' => "File appears to be malicious: " . esc_html($file),
325
+ 'longMsg' => "This file appears to be installed by a hacker to perform malicious activity. If you know about this file you can choose to ignore it to exclude it from future scans. The text we found in this file that matches a known malicious file is: <strong style=\"color: #F00;\">\"" . wfUtils::potentialBinaryStringToHTML((strlen($matchString) > 200 ? substr($matchString, 0, 200) . '...' : $matchString)) . "\"</strong>. The infection type is: <strong>" . esc_html($rule[3]) . '</strong>.' . $extraMsg,
326
'data' => array_merge(array(
327
'file' => $file,
328
), $dataForFile),
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
Contributors: mmaunder
3
Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking
4
Requires at least: 3.9
5
- Tested up to: 4.6.1
6
- Stable tag: 6.2.5
7
8
Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
9
@@ -190,6 +190,13 @@ Secure your website with Wordfence.
190
191
== Changelog ==
192
193
= 6.2.5 =
194
* Fix: Fixed an issue that could occur on older WordPress versions when processing login attempts
195
2
Contributors: mmaunder
3
Tags: security, secure, security plugin, wordpress security, login security, firewall, malware, antivirus, web application firewall, block hackers, country blocking
4
Requires at least: 3.9
5
+ Tested up to: 4.7.0
6
+ Stable tag: 6.2.6
7
8
Secure your website with the most comprehensive WordPress security plugin. Firewall, malware scan, blocking, live traffic, login security & more.
9
190
191
== Changelog ==
192
193
+ = 6.2.6 =
194
+ * Improvement: Improved formatting of attack data when it contains binary characters.
195
+ * Improvement: Updated internal GeoIP database.
196
+ * Improvement: Improved the ordering of rules in the malware scan so more specific rules are checked first.
197
+ * Fix: Country blocking redirects are no longer allowed to be cached.
198
+ * Fix: Fixed an issue with 2FA on multisite where the site could report URLs with different schemes depending on the state of plugin loading.
199
+
200
= 6.2.5 =
201
* Fix: Fixed an issue that could occur on older WordPress versions when processing login attempts
202
vendor/wordfence/wf-waf/src/lib/utils.php CHANGED
@@ -606,6 +606,10 @@ class wfWAFUtils {
606
$is_apache = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false);
607
$is_IIS = !$is_apache && (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'ExpressionDevServer') !== false);
608
609
if (!$is_IIS && PHP_SAPI != 'cgi-fcgi') {
610
self::statusHeader($status); // This causes problems on IIS and some FastCGI setups
611
}
606
$is_apache = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false);
607
$is_IIS = !$is_apache && (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'ExpressionDevServer') !== false);
608
609
+ header("Pragma: no-cache");
610
+ header("Cache-Control: no-cache, must-revalidate, private");
611
+ header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); //In the past
612
+
613
if (!$is_IIS && PHP_SAPI != 'cgi-fcgi') {
614
self::statusHeader($status); // This causes problems on IIS and some FastCGI setups
615
}
views/reports/activity-report-email-inline.php CHANGED
@@ -279,7 +279,7 @@ h6 a:visited { color: purple !important; }
279
<td style="font-size: 100%; vertical-align: baseline; font-weight: normal; text-align: left; border-collapse: collapse; margin: 0; padding: 6px 4px; border: 1px solid #cccccc;white-space: nowrap;<?php echo $bg_colors[$stripe] ?>" align="left" valign="baseline"><?php echo $this->attackTime($attack_row->attackLogTime) ?></td>
280
<td style="font-size: 100%; vertical-align: baseline; font-weight: normal; text-align: left; border-collapse: collapse; margin: 0; padding: 6px 4px; border: 1px solid #cccccc;<?php echo $bg_colors[$stripe] ?>" align="left" valign="baseline">
281
<div style="font-weight: bold; font-size: 12px;"><?php echo $this->displayIP($attack_row->IP) ?></div>
282
- <pre class="display-file" style="font-size: 12px; vertical-align: baseline; width: 420px; margin: 0; padding: 0; border: 0; white-space: normal;"><?php echo esc_html($attack_row->longDescription) ?></pre>
283
</td>
284
</tr>
285
<?php endforeach ?>
279
<td style="font-size: 100%; vertical-align: baseline; font-weight: normal; text-align: left; border-collapse: collapse; margin: 0; padding: 6px 4px; border: 1px solid #cccccc;white-space: nowrap;<?php echo $bg_colors[$stripe] ?>" align="left" valign="baseline"><?php echo $this->attackTime($attack_row->attackLogTime) ?></td>
280
<td style="font-size: 100%; vertical-align: baseline; font-weight: normal; text-align: left; border-collapse: collapse; margin: 0; padding: 6px 4px; border: 1px solid #cccccc;<?php echo $bg_colors[$stripe] ?>" align="left" valign="baseline">
281
<div style="font-weight: bold; font-size: 12px;"><?php echo $this->displayIP($attack_row->IP) ?></div>
282
+ <pre class="display-file" style="font-size: 12px; vertical-align: baseline; width: 420px; margin: 0; padding: 0; border: 0; white-space: normal;"><?php echo wfUtils::potentialBinaryStringToHTML($attack_row->longDescription, true) ?></pre>
283
</td>
284
</tr>
285
<?php endforeach ?>
wordfence.php CHANGED
@@ -4,14 +4,14 @@ Plugin Name: Wordfence Security
4
Plugin URI: http://www.wordfence.com/
5
Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
6
Author: Wordfence
7
- Version: 6.2.5
8
Author URI: http://www.wordfence.com/
9
Network: true
10
*/
11
if(defined('WP_INSTALLING') && WP_INSTALLING){
12
return;
13
}
14
- define('WORDFENCE_VERSION', '6.2.5');
15
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
16
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
17
4
Plugin URI: http://www.wordfence.com/
5
Description: Wordfence Security - Anti-virus, Firewall and Malware Scan
6
Author: Wordfence
7
+ Version: 6.2.6
8
Author URI: http://www.wordfence.com/
9
Network: true
10
*/
11
if(defined('WP_INSTALLING') && WP_INSTALLING){
12
return;
13
}
14
+ define('WORDFENCE_VERSION', '6.2.6');
15
define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
16
basename(dirname(__FILE__)) . '/' . basename(__FILE__));
17