Wordfence Security – Firewall & Malware Scan - Version 6.1.6

Version Description

  • Fix: Fixed bug with 2FA not properly handling email address login.
  • Fix: Show logins/logouts when Live Traffic is disabled.
  • Fix: Fixed bug with PCRE versions < 7.0 (repeated subpattern is too long).
  • Fix: Now able to delete whitelisted URL/params containing ampersands and non-UTF8 characters.
  • Improvement: Reduced 2FA activation code to expire after 30 days.
  • Improvement: Live Traffic now only shows verified Googlebot under Google Crawler filter for new visits.
  • Improvement: Adjusted permissions on Firewall log/config files to be 0640.
  • Fix: Fixed false positive from Maldet in the wfConfig table during the scan.
Download this release

Release Info

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

Code changes from version 6.1.5 to 6.1.6

css/main.css CHANGED
@@ -1032,3 +1032,13 @@ tr.wf-table-filters {
1032
  tr.wf-table-filters input {
1033
  max-width: 140px;
1034
  }
 
 
 
 
 
 
 
 
 
 
1032
  tr.wf-table-filters input {
1033
  max-width: 140px;
1034
  }
1035
+
1036
+ #wordfenceLiveActivityDisabled {
1037
+ background: #fff;
1038
+ border-left: 4px solid #ffb900;
1039
+ -webkit-box-shadow: 0 1px 1px 0 rgba(0, 0, 0, .1);
1040
+ box-shadow: 0 1px 1px 0 rgba(0, 0, 0, .1);
1041
+ margin-bottom: 12px;
1042
+ padding: 1px 13px;
1043
+ max-width: 900px;
1044
+ }
lib/menu_activity.php CHANGED
@@ -31,14 +31,11 @@
31
  </table>
32
  </div>
33
  <div class="wordfenceWrap">
34
-
35
  <?php if (!wfConfig::liveTrafficEnabled()): ?>
36
- <div style="color: #F00;">
37
- Live Traffic is disabled.
38
- <?php if (wfConfig::get('cacheType') == 'falcon') { ?>This is done to improve performance because you have Wordfence Falcon Engine enabled.<?php } ?>
39
- </div>
40
- <?php else: ?>
41
- <div id="wf-live-traffic" class="wfTabsContainer">
42
 
43
  <div id="wf-live-traffic-legend">
44
  <ul>
@@ -393,7 +390,6 @@
393
  No events to report yet.
394
  </div>
395
  </div>
396
- <?php endif ?>
397
  </div>
398
  </div>
399
 
31
  </table>
32
  </div>
33
  <div class="wordfenceWrap">
 
34
  <?php if (!wfConfig::liveTrafficEnabled()): ?>
35
+ <div id="wordfenceLiveActivityDisabled"><p><strong>Live activity is disabled.</strong> <?php if (wfConfig::get('cacheType') == 'falcon') { ?>This is done to improve performance because you have Wordfence Falcon Engine enabled.<?php } ?> Login and firewall activity will still appear below.</p></div>
36
+ <?php endif ?>
37
+
38
+ <div id="wf-live-traffic" class="wfTabsContainer">
 
 
39
 
40
  <div id="wf-live-traffic-legend">
41
  <ul>
390
  No events to report yet.
391
  </div>
392
  </div>
 
393
  </div>
394
  </div>
395
 
lib/menu_options.php CHANGED
@@ -672,7 +672,7 @@ $w = new wfConfig();
672
  require( 'wfAction.php' ); ?></td>
673
  </tr>
674
  <tr>
675
- <th>If 404's for known vulnerable URL's exceed:<a
676
  href="http://docs.wordfence.com/en/Wordfence_options#If_404.27s_for_known_vulnerable_URL.27s_exceed"
677
  target="_blank" class="wfhelp"></a></th>
678
  <td><?php $rateName = 'maxScanHits';
672
  require( 'wfAction.php' ); ?></td>
673
  </tr>
674
  <tr>
675
+ <th>If 404s for known vulnerable URLs exceed:<a
676
  href="http://docs.wordfence.com/en/Wordfence_options#If_404.27s_for_known_vulnerable_URL.27s_exceed"
677
  target="_blank" class="wfhelp"></a></th>
678
  <td><?php $rateName = 'maxScanHits';
lib/menu_waf.php CHANGED
@@ -348,15 +348,15 @@ $wafConfigURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configu
348
  </td>
349
  <td>
350
  <input name="replaceWhitelistedPath" type="hidden" value="${whitelistedURLParam.path}">
351
- <span class="whitelist-display">${WFAD.base64_decode(whitelistedURLParam.path)}</span>
352
  <input name="whitelistedPath" class="whitelist-edit whitelist-path" type="text"
353
- value="${WFAD.base64_decode(whitelistedURLParam.path)}">
354
  </td>
355
  <td>
356
  <input name="replaceWhitelistedParam" type="hidden" value="${whitelistedURLParam.paramKey}">
357
- <span class="whitelist-display">${WFAD.base64_decode(whitelistedURLParam.paramKey)}</span>
358
  <input name="whitelistedParam" class="whitelist-edit whitelist-param-key"
359
- type="text" value="${WFAD.base64_decode(whitelistedURLParam.paramKey)}">
360
  </td>
361
  <td>
362
  {{if (whitelistedURLParam.data.timestamp)}}
@@ -598,10 +598,13 @@ $wafConfigURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configu
598
  if (this.checked) {
599
  var tr = $(this).closest('tr');
600
  if (tr.is(':visible')) {
601
- var path = tr.find('input[name=whitelistedPath]').val();
602
- var paramKey = tr.find('input[name=whitelistedParam]').val();
603
- var enabled = tr.find('input[name=whitelistedEnabled]').attr('checked') ? 1 : 0;
604
- data.push([encodeURIComponent(path), encodeURIComponent(paramKey), enabled]);
 
 
 
605
  }
606
  }
607
  });
@@ -633,16 +636,19 @@ $wafConfigURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configu
633
  $(document).on('click', '.whitelist-url-delete', function() {
634
  if (confirm('Are you sure you\'d like to delete this URL?')) {
635
  var tr = $(this).closest('tr');
636
-
637
- var pathInput = tr.find('input.whitelist-path');
638
- var paramInput = tr.find('input.whitelist-param-key');
639
- WFAD.wafConfigSave('deleteWhitelist', {
640
- deletedWhitelistedPath: pathInput.val(),
641
- deletedWhitelistedParam: paramInput.val()
642
- }, function() {
643
- WFAD.colorbox('400px', 'Firewall Configuration', 'The Wordfence Web Application Firewall ' +
644
- 'whitelist was saved successfully.');
645
- }, false);
 
 
 
646
  }
647
  });
648
  $(document).on('click', '.whitelist-url-save', function() {
348
  </td>
349
  <td>
350
  <input name="replaceWhitelistedPath" type="hidden" value="${whitelistedURLParam.path}">
351
+ <span class="whitelist-display">${WFAD.htmlEscape(WFAD.base64_decode(whitelistedURLParam.path))}</span>
352
  <input name="whitelistedPath" class="whitelist-edit whitelist-path" type="text"
353
+ value="${WFAD.htmlEscape(WFAD.base64_decode(whitelistedURLParam.path))}">
354
  </td>
355
  <td>
356
  <input name="replaceWhitelistedParam" type="hidden" value="${whitelistedURLParam.paramKey}">
357
+ <span class="whitelist-display">${WFAD.htmlEscape(WFAD.base64_decode(whitelistedURLParam.paramKey))}</span>
358
  <input name="whitelistedParam" class="whitelist-edit whitelist-param-key"
359
+ type="text" value="${WFAD.htmlEscape(WFAD.base64_decode(whitelistedURLParam.paramKey))}">
360
  </td>
361
  <td>
362
  {{if (whitelistedURLParam.data.timestamp)}}
598
  if (this.checked) {
599
  var tr = $(this).closest('tr');
600
  if (tr.is(':visible')) {
601
+ var index = tr.attr('data-index');
602
+ if (index in WFAD.wafData.whitelistedURLParams) {
603
+ var path = WFAD.wafData.whitelistedURLParams[index].path;
604
+ var paramKey = WFAD.wafData.whitelistedURLParams[index].paramKey;
605
+ var enabled = tr.find('input[name=whitelistedEnabled]').attr('checked') ? 1 : 0;
606
+ data.push([path, paramKey, enabled]);
607
+ }
608
  }
609
  }
610
  });
636
  $(document).on('click', '.whitelist-url-delete', function() {
637
  if (confirm('Are you sure you\'d like to delete this URL?')) {
638
  var tr = $(this).closest('tr');
639
+ var index = tr.attr('data-index');
640
+
641
+ if (index in WFAD.wafData.whitelistedURLParams) {
642
+ var path = WFAD.wafData.whitelistedURLParams[index].path;
643
+ var param = WFAD.wafData.whitelistedURLParams[index].paramKey;
644
+ WFAD.wafConfigSave('deleteWhitelist', {
645
+ deletedWhitelistedPath: path,
646
+ deletedWhitelistedParam: param
647
+ }, function() {
648
+ WFAD.colorbox('400px', 'Firewall Configuration', 'The Wordfence Web Application Firewall ' +
649
+ 'whitelist was saved successfully.');
650
+ }, false);
651
+ }
652
  }
653
  });
654
  $(document).on('click', '.whitelist-url-save', function() {
lib/wfLog.php CHANGED
@@ -542,7 +542,13 @@ class wfLog {
542
  * @return bool|int
543
  */
544
  public function logHit(){
545
- if (!wfConfig::liveTrafficEnabled() || !$this->logHitOK()) {
 
 
 
 
 
 
546
  return false;
547
  }
548
  if ($this->currentRequest !== null) {
@@ -1036,6 +1042,8 @@ class wfLog {
1036
  if (!$this->currentRequest->actionDescription) {
1037
  $this->currentRequest->actionDescription = "blocked: " . $reason;
1038
  }
 
 
1039
 
1040
  wfConfig::inc('total503s');
1041
  wfUtils::doNotCache();
@@ -1061,7 +1069,7 @@ class wfLog {
1061
  } else if($nb == 'neverBlockUA' || $nb == 'neverBlockVerified'){
1062
  if(wfCrawl::isGoogleCrawler()){ //Check the UA using regex
1063
  if($nb == 'neverBlockVerified'){
1064
- if(wfCrawl::isVerifiedGoogleCrawler($this->googlePattern, wfUtils::getIP())){ //UA check passed, now verify using PTR if configured to
1065
  self::$gbSafeCache[$cacheKey] = false; //This is a verified Google crawler, so no we can't block it
1066
  } else {
1067
  self::$gbSafeCache[$cacheKey] = true; //This is a crawler claiming to be Google but it did not verify
@@ -1661,11 +1669,29 @@ class wfLiveTrafficQuery {
1661
  $sql = $this->buildQuery();
1662
  $results = $wpdb->get_results($sql, ARRAY_A);
1663
  $this->getWFLog()->processGetHitsResults('', $results);
1664
-
1665
- foreach ($results as &$row) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1666
  $row['actionData'] = (array) json_decode($row['actionData'], true);
1667
  }
1668
- return $results;
1669
  }
1670
 
1671
  /**
542
  * @return bool|int
543
  */
544
  public function logHit(){
545
+ $liveTrafficEnabled = wfConfig::liveTrafficEnabled();
546
+ $action = $this->currentRequest->action;
547
+ $logHitOK = $this->logHitOK();
548
+ if (!$logHitOK) {
549
+ return false;
550
+ }
551
+ if (!$liveTrafficEnabled && !$action) {
552
  return false;
553
  }
554
  if ($this->currentRequest !== null) {
1042
  if (!$this->currentRequest->actionDescription) {
1043
  $this->currentRequest->actionDescription = "blocked: " . $reason;
1044
  }
1045
+
1046
+ $this->logHit();
1047
 
1048
  wfConfig::inc('total503s');
1049
  wfUtils::doNotCache();
1069
  } else if($nb == 'neverBlockUA' || $nb == 'neverBlockVerified'){
1070
  if(wfCrawl::isGoogleCrawler()){ //Check the UA using regex
1071
  if($nb == 'neverBlockVerified'){
1072
+ if(wfCrawl::isVerifiedGoogleCrawler(wfUtils::getIP())){ //UA check passed, now verify using PTR if configured to
1073
  self::$gbSafeCache[$cacheKey] = false; //This is a verified Google crawler, so no we can't block it
1074
  } else {
1075
  self::$gbSafeCache[$cacheKey] = true; //This is a crawler claiming to be Google but it did not verify
1669
  $sql = $this->buildQuery();
1670
  $results = $wpdb->get_results($sql, ARRAY_A);
1671
  $this->getWFLog()->processGetHitsResults('', $results);
1672
+
1673
+ $verifyCrawlers = false;
1674
+ if ($this->filters !== null && count($this->filters->getFilters()) > 0) {
1675
+ $filters = $this->filters->getFilters();
1676
+ foreach ($filters as $f) {
1677
+ if (strtolower($f->getParam()) == "isgoogle") {
1678
+ $verifyCrawlers = true;
1679
+ break;
1680
+ }
1681
+ }
1682
+ }
1683
+
1684
+ foreach ($results as $key => &$row) {
1685
+ if ($row['isGoogle'] && $verifyCrawlers) {
1686
+ if (!wfCrawl::isVerifiedGoogleCrawler($row['IP'], $row['UA'])) {
1687
+ unset($results[$key]); //foreach copies $results and iterates on the copy, so it is safe to mutate $results within the loop
1688
+ continue;
1689
+ }
1690
+ }
1691
+
1692
  $row['actionData'] = (array) json_decode($row['actionData'], true);
1693
  }
1694
+ return array_values($results);
1695
  }
1696
 
1697
  /**
lib/wordfenceClass.php CHANGED
@@ -1163,7 +1163,10 @@ SQL
1163
  foreach($twoFactorUsers as &$t){
1164
  if($t[0] == $userDat->ID && $t[3] == 'activated'){
1165
  if($_POST['wordfence_authFactor'] == $t[2] && $t[4] > time()){
1166
- //Do nothing and allow user to sign in. Their passwd has already been modified to be the passwd without the code.
 
 
 
1167
  } else if($_POST['wordfence_authFactor'] == $t[2]){
1168
  $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
1169
  try {
@@ -1350,6 +1353,9 @@ SQL
1350
  }
1351
  if(! $username){ return; }
1352
  $userDat = get_user_by('login', $username);
 
 
 
1353
  $_POST['wordfence_userDat'] = $userDat;
1354
  if(preg_match(self::$passwordCodePattern, $passwd, $matches)){
1355
  $_POST['wordfence_authFactor'] = $matches[1];
@@ -1363,6 +1369,9 @@ SQL
1363
  }
1364
  if(! $username){ return; }
1365
  $userDat = get_user_by('login', $username);
 
 
 
1366
  $_POST['wordfence_userDat'] = $userDat;
1367
  if(preg_match(self::$passwordCodePattern, $passwd, $matches)){
1368
  $_POST['wordfence_authFactor'] = $matches[1];
@@ -1485,8 +1494,11 @@ SQL
1485
  if($twoFactorUsers[$i][0] == $userID){
1486
  if($twoFactorUsers[$i][2] == $code){
1487
  $twoFactorUsers[$i][3] = 'activated';
 
 
1488
  $found = true;
1489
  $user = $twoFactorUsers[$i];
 
1490
  break;
1491
  } else {
1492
  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()) );
@@ -1517,7 +1529,7 @@ SQL
1517
  $i--;
1518
  }
1519
  }
1520
- $twoFactorUsers[] = array($ID, $phone, $code, 'notActivated', time() + (86400 * 100)); //expiry of code is 100 days in future
1521
  wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
1522
  }
1523
  public static function ajax_loadTwoFactor_callback(){
@@ -4575,7 +4587,7 @@ to your httpd.conf if using Apache, or find documentation on how to disable dire
4575
  $deletedWhitelistedPath = stripslashes($_POST['deletedWhitelistedPath']);
4576
  $deletedWhitelistedParam = stripslashes($_POST['deletedWhitelistedParam']);
4577
  $savedWhitelistedURLParams = (array) wfWAF::getInstance()->getStorageEngine()->getConfig('whitelistedURLParams');
4578
- $key = base64_encode($deletedWhitelistedPath) . '|' . base64_encode($deletedWhitelistedParam);
4579
  unset($savedWhitelistedURLParams[$key]);
4580
  wfWAF::getInstance()->getStorageEngine()->setConfig('whitelistedURLParams', $savedWhitelistedURLParams);
4581
  }
@@ -4738,7 +4750,7 @@ to your httpd.conf if using Apache, or find documentation on how to disable dire
4738
  }
4739
  foreach ($items as $key) {
4740
  list($path, $paramKey, ) = $key;
4741
- $whitelistKey = base64_encode(rawurldecode($path)) . '|' . base64_encode(rawurldecode($paramKey));
4742
  if (array_key_exists($whitelistKey, $whitelist)) {
4743
  unset($whitelist[$whitelistKey]);
4744
  }
@@ -4787,7 +4799,7 @@ to your httpd.conf if using Apache, or find documentation on how to disable dire
4787
  }
4788
  foreach ($items as $key) {
4789
  list($path, $paramKey, ) = $key;
4790
- $whitelistKey = base64_encode(rawurldecode($path)) . '|' . base64_encode(rawurldecode($paramKey));
4791
  if (array_key_exists($whitelistKey, $whitelist) && is_array($whitelist[$whitelistKey])) {
4792
  foreach ($whitelist[$whitelistKey] as $ruleID => $data) {
4793
  $whitelist[$whitelistKey][$ruleID]['disabled'] = !$enabled;
1163
  foreach($twoFactorUsers as &$t){
1164
  if($t[0] == $userDat->ID && $t[3] == 'activated'){
1165
  if($_POST['wordfence_authFactor'] == $t[2] && $t[4] > time()){
1166
+ // Set this 2FA code to expire in 30 seconds (for other plugins hooking into the auth process)
1167
+ $t[4] = time() + 30;
1168
+ wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
1169
+
1170
  } else if($_POST['wordfence_authFactor'] == $t[2]){
1171
  $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
1172
  try {
1353
  }
1354
  if(! $username){ return; }
1355
  $userDat = get_user_by('login', $username);
1356
+ if (!$userDat) {
1357
+ $userDat = get_user_by('email', $username);
1358
+ }
1359
  $_POST['wordfence_userDat'] = $userDat;
1360
  if(preg_match(self::$passwordCodePattern, $passwd, $matches)){
1361
  $_POST['wordfence_authFactor'] = $matches[1];
1369
  }
1370
  if(! $username){ return; }
1371
  $userDat = get_user_by('login', $username);
1372
+ if (!$userDat) {
1373
+ $userDat = get_user_by('email', $username);
1374
+ }
1375
  $_POST['wordfence_userDat'] = $userDat;
1376
  if(preg_match(self::$passwordCodePattern, $passwd, $matches)){
1377
  $_POST['wordfence_authFactor'] = $matches[1];
1494
  if($twoFactorUsers[$i][0] == $userID){
1495
  if($twoFactorUsers[$i][2] == $code){
1496
  $twoFactorUsers[$i][3] = 'activated';
1497
+ // Set the expiration earlier to invalidate this code
1498
+ $twoFactorUsers[$i][4] = 0;
1499
  $found = true;
1500
  $user = $twoFactorUsers[$i];
1501
+
1502
  break;
1503
  } else {
1504
  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()) );
1529
  $i--;
1530
  }
1531
  }
1532
+ $twoFactorUsers[] = array($ID, $phone, $code, 'notActivated', time() + (86400 * 30)); //expiry of code is 30 days in future
1533
  wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
1534
  }
1535
  public static function ajax_loadTwoFactor_callback(){
4587
  $deletedWhitelistedPath = stripslashes($_POST['deletedWhitelistedPath']);
4588
  $deletedWhitelistedParam = stripslashes($_POST['deletedWhitelistedParam']);
4589
  $savedWhitelistedURLParams = (array) wfWAF::getInstance()->getStorageEngine()->getConfig('whitelistedURLParams');
4590
+ $key = $deletedWhitelistedPath . '|' . $deletedWhitelistedParam;
4591
  unset($savedWhitelistedURLParams[$key]);
4592
  wfWAF::getInstance()->getStorageEngine()->setConfig('whitelistedURLParams', $savedWhitelistedURLParams);
4593
  }
4750
  }
4751
  foreach ($items as $key) {
4752
  list($path, $paramKey, ) = $key;
4753
+ $whitelistKey = $path . '|' . $paramKey;
4754
  if (array_key_exists($whitelistKey, $whitelist)) {
4755
  unset($whitelist[$whitelistKey]);
4756
  }
4799
  }
4800
  foreach ($items as $key) {
4801
  list($path, $paramKey, ) = $key;
4802
+ $whitelistKey = $path . '|' . $paramKey;
4803
  if (array_key_exists($whitelistKey, $whitelist) && is_array($whitelist[$whitelistKey])) {
4804
  foreach ($whitelist[$whitelistKey] as $ruleID => $data) {
4805
  $whitelist[$whitelistKey][$ruleID]['disabled'] = !$enabled;
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: mmaunder
3
  Tags: wordpress, security, web application firewall, waf, 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, two factor authentication, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm, woocommerce support, woocommerce caching, IPv6, IP version 6
4
  Requires at least: 3.9
5
- Tested up to: 4.5.1
6
- Stable tag: 6.1.5
7
 
8
  The Wordfence WordPress security plugin provides free enterprise-class WordPress security, protecting your website from hacks and malware.
9
  == Description ==
@@ -195,6 +195,16 @@ Designed for every skill level, [The WordPress Security Learning Center](https:/
195
 
196
  == Changelog ==
197
 
 
 
 
 
 
 
 
 
 
 
198
  = 6.1.5 =
199
  * Fix: WordPress language files no longer flagged as changed.
200
  * Improvement: Accept wildcards in "Immediately block IP's that access these URLs."
2
  Contributors: mmaunder
3
  Tags: wordpress, security, web application firewall, waf, 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, two factor authentication, maximum login security, heartbleed, heart bleed, heartbleed vulnerability, openssl vulnerability, nginx, litespeed, php5-fpm, woocommerce support, woocommerce caching, IPv6, IP version 6
4
  Requires at least: 3.9
5
+ Tested up to: 4.5.2
6
+ Stable tag: 6.1.6
7
 
8
  The Wordfence WordPress security plugin provides free enterprise-class WordPress security, protecting your website from hacks and malware.
9
  == Description ==
195
 
196
  == Changelog ==
197
 
198
+ = 6.1.6 =
199
+ * Fix: Fixed bug with 2FA not properly handling email address login.
200
+ * Fix: Show logins/logouts when Live Traffic is disabled.
201
+ * Fix: Fixed bug with PCRE versions < 7.0 (repeated subpattern is too long).
202
+ * Fix: Now able to delete whitelisted URL/params containing ampersands and non-UTF8 characters.
203
+ * Improvement: Reduced 2FA activation code to expire after 30 days.
204
+ * Improvement: Live Traffic now only shows verified Googlebot under Google Crawler filter for new visits.
205
+ * Improvement: Adjusted permissions on Firewall log/config files to be 0640.
206
+ * Fix: Fixed false positive from Maldet in the wfConfig table during the scan.
207
+
208
  = 6.1.5 =
209
  * Fix: WordPress language files no longer flagged as changed.
210
  * Improvement: Accept wildcards in "Immediately block IP's that access these URLs."
vendor/wordfence/wf-waf/src/lib/parser/sqli.php CHANGED
@@ -2707,15 +2707,15 @@ class wfWAFSQLiLexer implements wfWAFLexerInterface {
2707
  new wfWAFLexerTokenMatcher(self::BINARY_NUMBER_LITERAL, '/^(?:0b[01]+|[bB]\'[01]+\')/', true),
2708
  new wfWAFLexerTokenMatcher(self::HEX_NUMBER_LITERAL, '/^(?:0x[0-9a-fA-F]+|[xX]\'[0-9a-fA-F]+\')/', true),
2709
  new wfWAFLexerTokenMatcher(self::INTEGER_LITERAL, '/^[0-9]+/', true),
2710
- new wfWAFLexerTokenMatcher(self::VARIABLE, '/^(?:@(?:`([^`\\\\]{0,256}(?:\\\\.[^`\\\\]{0,256}){0,256})`|
2711
- "(?:[^#"\\\\]{0,256}(?:\\\\.[^#"\\\\]{0,256}){0,256})"|
2712
- \'(?:[^\'\\\\]{0,256}(?:\\\\.[^\'\\\\]{0,256}){0,256})\'|
2713
  [a-zA-Z_\\$\\.]+|
2714
  @[a-zA-Z_\\$][a-zA-Z_\\$0-9]{0,256}){0,1})
2715
  /Asx'),
2716
- new wfWAFLexerTokenMatcher(self::QUOTED_IDENTIFIER, '/^`(?:[^`\\\\]{0,256}(?:\\\\.[^`\\\\]{0,256}){0,256})`/As'),
2717
- new wfWAFLexerTokenMatcher(self::DOUBLE_STRING_LITERAL, '/^(?:[nN]|_[0-9a-zA-Z\\$_]{0,256})?"(?:[^#"\\\\]{0,256}(?:\\\\.[^#"\\\\]{0,256}){0,256})"/As'),
2718
- new wfWAFLexerTokenMatcher(self::SINGLE_STRING_LITERAL, '/^(?:[nN]|_[0-9a-zA-Z\\$_]{0,256})?\'(?:[^\'\\\\]{0,256}(?:\\\\.[^\'\\\\]{0,256}){0,256})\'/As'),
2719
  // U+0080 .. U+FFFF
2720
  new wfWAFLexerTokenMatcher(self::UNQUOTED_IDENTIFIER, '/^[0-9a-zA-Z\\$_\\x{0080}-\\x{FFFF}]{1,256}/u'),
2721
  new wfWAFLexerTokenMatcher(self::MYSQL_PORTABLE_COMMENT_START, '/^\\/\\*\\![0-9]{0,5}/s'),
2707
  new wfWAFLexerTokenMatcher(self::BINARY_NUMBER_LITERAL, '/^(?:0b[01]+|[bB]\'[01]+\')/', true),
2708
  new wfWAFLexerTokenMatcher(self::HEX_NUMBER_LITERAL, '/^(?:0x[0-9a-fA-F]+|[xX]\'[0-9a-fA-F]+\')/', true),
2709
  new wfWAFLexerTokenMatcher(self::INTEGER_LITERAL, '/^[0-9]+/', true),
2710
+ new wfWAFLexerTokenMatcher(self::VARIABLE, '/^(?:@(?:`(?:[^`]*(?:``[^`]*)*)`|
2711
+ "([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|
2712
+ \'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'|
2713
  [a-zA-Z_\\$\\.]+|
2714
  @[a-zA-Z_\\$][a-zA-Z_\\$0-9]{0,256}){0,1})
2715
  /Asx'),
2716
+ new wfWAFLexerTokenMatcher(self::QUOTED_IDENTIFIER, '/^`(?:[^`]*(?:``[^`]*)*)`/As'),
2717
+ new wfWAFLexerTokenMatcher(self::DOUBLE_STRING_LITERAL, '/^(?:[nN]|_[0-9a-zA-Z\\$_]{0,256})?"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"/As'),
2718
+ new wfWAFLexerTokenMatcher(self::SINGLE_STRING_LITERAL, '/^(?:[nN]|_[0-9a-zA-Z\\$_]{0,256})?\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As'),
2719
  // U+0080 .. U+FFFF
2720
  new wfWAFLexerTokenMatcher(self::UNQUOTED_IDENTIFIER, '/^[0-9a-zA-Z\\$_\\x{0080}-\\x{FFFF}]{1,256}/u'),
2721
  new wfWAFLexerTokenMatcher(self::MYSQL_PORTABLE_COMMENT_START, '/^\\/\\*\\![0-9]{0,5}/s'),
vendor/wordfence/wf-waf/src/lib/storage/file.php CHANGED
@@ -22,6 +22,7 @@ class wfWAFStorageFile implements wfWAFStorageInterface {
22
  fflush($tmpHandle);
23
  self::lock($tmpHandle, LOCK_UN);
24
  fclose($tmpHandle);
 
25
 
26
  // Attempt to verify file has finished writing (sometimes the disk will lie for better benchmarks)
27
  $tmpContents = file_get_contents($tmpFile);
22
  fflush($tmpHandle);
23
  self::lock($tmpHandle, LOCK_UN);
24
  fclose($tmpHandle);
25
+ chmod($tmpFile, 0640);
26
 
27
  // Attempt to verify file has finished writing (sometimes the disk will lie for better benchmarks)
28
  $tmpContents = file_get_contents($tmpFile);
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 High Speed Cache
6
  Author: Wordfence
7
- Version: 6.1.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.1.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 High Speed Cache
6
  Author: Wordfence
7
+ Version: 6.1.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.1.6');
15
  define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
16
  basename(dirname(__FILE__)) . '/' . basename(__FILE__));
17