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$/i', $_GET['img'])) ||
590
- (isset($_POST['action']) && $_POST['action'] == 'revslider_show_image' && isset($_POST['img']) && preg_match('/\.php$/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$/i', $_GET['img'])) ||
591
+ (($pAction == 'revslider_show_image' || $pAction == 'nopriv_revslider_show_image') && isset($_POST['img']) && preg_match('/\.php$/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