Wordfence Security – Firewall & Malware Scan - Version 6.1.3

Version Description

  • Improvement: Added dismiss button to the Wordfence WAF setup admin notice.
  • Fix: Removed .htaccess and .user.ini from publicly accessible config and backup file scan.
  • Fix: Removed the disallow file mods for admins created outside of WordPress.
  • Fix: Fixed bug with 'Hide WordPress version' causing issues with reCAPTCHA.
  • Improvement: Added instructions for NGINX users to restrict access to .user.ini during Firewall configuration.
  • Fix: Fixed bug with multiple API calls to 'get_known_files'.
Download this release

Release Info

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

Code changes from version 6.1.2 to 6.1.3

Files changed (7) hide show
  1. css/main.css +15 -0
  2. js/tourTip.js +12 -0
  3. lib/menu_waf.php +17 -0
  4. lib/wfScanEngine.php +17 -8
  5. lib/wordfenceClass.php +50 -12
  6. readme.txt +9 -1
  7. wordfence.php +2 -2
css/main.css CHANGED
@@ -576,6 +576,21 @@ table.block-ranges-table tr td {
576
  border: 1px solid #ffd975;
577
  border-width: 1px 1px 1px 10px;
578
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
579
  .wf-success {
580
  margin: 12px 0;
581
  padding: 8px;
576
  border: 1px solid #ffd975;
577
  border-width: 1px 1px 1px 10px;
578
  }
579
+ .wf-success-text,
580
+ .wf-notice-text {
581
+ display: inline-block;
582
+ vertical-align: middle;
583
+ line-height: 1.3;
584
+ font-size: 16px;
585
+ font-weight: bold;
586
+ font-style: italic;
587
+ }
588
+ .wf-notice-text {
589
+ color: #6d798c;
590
+ }
591
+ .wf-success-text {
592
+ color: #11967A;
593
+ }
594
  .wf-success {
595
  margin: 12px 0;
596
  padding: 8px;
js/tourTip.js CHANGED
@@ -172,5 +172,17 @@ if(WordfenceAdminVars.tourClosed != '1' && WordfenceAdminVars.welcomeClosed != '
172
 
173
  });
174
  }
 
 
 
 
 
 
 
 
 
 
 
 
175
  });
176
 
172
 
173
  });
174
  }
175
+
176
+ (function($) {
177
+ $('.wf-dismiss-link').on('click', function() {
178
+ $('#wf-extended-protection-notice').css({
179
+ opacity: .75
180
+ });
181
+ $.get(this.href, function() {
182
+ $('#wf-extended-protection-notice').fadeOut(1000);
183
+ });
184
+ return false;
185
+ });
186
+ })(jQuery);
187
  });
188
 
lib/menu_waf.php CHANGED
@@ -1,6 +1,7 @@
1
  <?php
2
  $waf = wfWAF::getInstance();
3
  $config = $waf->getStorageEngine();
 
4
  /** @var array $wafData */
5
  ?>
6
  <div class="wrap" id="paidWrap">
@@ -61,6 +62,22 @@ $config = $waf->getStorageEngine();
61
  <form action="javascript:void(0)" id="waf-config-form">
62
 
63
  <table class="wfConfigForm">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  <tr>
65
  <td><h2>Firewall Status:<a href="http://docs.wordfence.com/en/WAF#Firewall_Status"
66
  target="_blank" class="wfhelp"></a></h2></td>
1
  <?php
2
  $waf = wfWAF::getInstance();
3
  $config = $waf->getStorageEngine();
4
+ $wafConfigURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configureAutoPrepend');
5
  /** @var array $wafData */
6
  ?>
7
  <div class="wrap" id="paidWrap">
62
  <form action="javascript:void(0)" id="waf-config-form">
63
 
64
  <table class="wfConfigForm">
65
+ <tr>
66
+ <td>
67
+ <h2>Protection Level:<a href="http://docs.wordfence.com/en/WAF#Protection_Level"
68
+ target="_blank" class="wfhelp"></a></h2>
69
+ </td>
70
+ <td colspan="2">
71
+ <?php if (!WFWAF_AUTO_PREPEND): ?>
72
+ <span class="wf-notice-text">Basic WordPress Protection</span>
73
+ &nbsp;&nbsp;&nbsp;
74
+ <a style="vertical-align: middle" class="button button-primary"
75
+ href="<?php echo $wafConfigURL ?>">Optimize the Wordfence Firewall</a>
76
+ <?php else: ?>
77
+ <span class="wf-success-text">Extended Protection</span>
78
+ <?php endif ?>
79
+ </td>
80
+ </tr>
81
  <tr>
82
  <td><h2>Firewall Status:<a href="http://docs.wordfence.com/en/WAF#Firewall_Status"
83
  target="_blank" class="wfhelp"></a></h2></td>
lib/wfScanEngine.php CHANGED
@@ -71,7 +71,7 @@ class wfScanEngine {
71
  }
72
 
73
  public function __sleep(){ //Same order here as above for properties that are included in serialization
74
- return array('hasher', 'jobList', 'i', 'wp_version', 'apiKey', 'startTime', 'maxExecTime', 'publicScanEnabled', 'fileContentsResults', 'scanner', 'scanQueue', 'hoover', 'scanData', 'statusIDX', 'userPasswdQueue', 'passwdHasIssues', 'dbScanner');
75
  }
76
  public function __construct(){
77
  $this->startTime = time();
@@ -247,8 +247,8 @@ class wfScanEngine {
247
  $status = wordfence::statusStart("Check for publicly accessible configuration files, backup files and logs");
248
 
249
  $backupFileTests = array(
250
- wfCommonBackupFileTest::createFromRootPath('.user.ini'),
251
- wfCommonBackupFileTest::createFromRootPath('.htaccess'),
252
  wfCommonBackupFileTest::createFromRootPath('wp-config.php.bak'),
253
  wfCommonBackupFileTest::createFromRootPath('wp-config.php.swo'),
254
  wfCommonBackupFileTest::createFromRootPath('wp-config.php.save'),
@@ -273,10 +273,10 @@ class wfScanEngine {
273
  ),
274
  )),
275
  );
276
- $userIniFilename = ini_get('user_ini.filename');
277
- if ($userIniFilename && $userIniFilename !== '.user.ini') {
278
- $backupFileTests[] = wfCommonBackupFileTest::createFromRootPath($userIniFilename);
279
- }
280
 
281
 
282
  /** @var wfCommonBackupFileTest $test */
@@ -1427,7 +1427,16 @@ class wfCommonBackupFileTest {
1427
  */
1428
  public function isPubliclyAccessible() {
1429
  $this->response = wp_remote_get($this->url, $this->requestArgs);
1430
- return wp_remote_retrieve_response_code($this->response) === 200;
 
 
 
 
 
 
 
 
 
1431
  }
1432
 
1433
  /**
71
  }
72
 
73
  public function __sleep(){ //Same order here as above for properties that are included in serialization
74
+ return array('hasher', 'jobList', 'i', 'wp_version', 'apiKey', 'startTime', 'maxExecTime', 'publicScanEnabled', 'fileContentsResults', 'scanner', 'scanQueue', 'hoover', 'scanData', 'statusIDX', 'userPasswdQueue', 'passwdHasIssues', 'dbScanner', 'knownFilesLoader');
75
  }
76
  public function __construct(){
77
  $this->startTime = time();
247
  $status = wordfence::statusStart("Check for publicly accessible configuration files, backup files and logs");
248
 
249
  $backupFileTests = array(
250
+ // wfCommonBackupFileTest::createFromRootPath('.user.ini'),
251
+ // wfCommonBackupFileTest::createFromRootPath('.htaccess'),
252
  wfCommonBackupFileTest::createFromRootPath('wp-config.php.bak'),
253
  wfCommonBackupFileTest::createFromRootPath('wp-config.php.swo'),
254
  wfCommonBackupFileTest::createFromRootPath('wp-config.php.save'),
273
  ),
274
  )),
275
  );
276
+ // $userIniFilename = ini_get('user_ini.filename');
277
+ // if ($userIniFilename && $userIniFilename !== '.user.ini') {
278
+ // $backupFileTests[] = wfCommonBackupFileTest::createFromRootPath($userIniFilename);
279
+ // }
280
 
281
 
282
  /** @var wfCommonBackupFileTest $test */
1427
  */
1428
  public function isPubliclyAccessible() {
1429
  $this->response = wp_remote_get($this->url, $this->requestArgs);
1430
+ if ((int) floor(((int) wp_remote_retrieve_response_code($this->response) / 100)) === 2) {
1431
+ $handle = @fopen($this->path, 'r');
1432
+ if ($handle) {
1433
+ $contents = fread($handle, 700);
1434
+ fclose($handle);
1435
+ $remoteContents = substr(wp_remote_retrieve_body($this->response), 0, 700);
1436
+ return $contents === $remoteContents;
1437
+ }
1438
+ }
1439
+ return false;
1440
  }
1441
 
1442
  /**
lib/wordfenceClass.php CHANGED
@@ -3355,12 +3355,12 @@ HTML;
3355
  self::setCookie();
3356
  }
3357
  // This is more of a hurdle, but might stop an automated process.
3358
- if (current_user_can('administrator')) {
3359
- $adminUsers = new wfAdminUserMonitor();
3360
- if ($adminUsers->isEnabled() && !$adminUsers->isAdminUserLogged(get_current_user_id())) {
3361
- define('DISALLOW_FILE_MODS', true);
3362
- }
3363
- }
3364
 
3365
  $currentUserID = get_current_user_id();
3366
  $role = wordfence::getCurrentUserRole();
@@ -3474,7 +3474,7 @@ HTML;
3474
  }
3475
 
3476
  if (!WFWAF_AUTO_PREPEND || WFWAF_SUBDIRECTORY_INSTALL) {
3477
- if (empty($_GET['wafAction'])) {
3478
  if (is_multisite()) {
3479
  add_action('network_admin_notices', 'wordfence::wafAutoPrependNotice');
3480
  } else {
@@ -3690,6 +3690,12 @@ HTML;
3690
 
3691
  if (!empty($_GET['wafAction'])) {
3692
  switch ($_GET['wafAction']) {
 
 
 
 
 
 
3693
  case 'configureAutoPrepend':
3694
  if (WFWAF_AUTO_PREPEND && !WFWAF_SUBDIRECTORY_INSTALL) {
3695
  break;
@@ -3854,14 +3860,42 @@ list below:</p>";
3854
  you know your web server's configuration, please select it now.</p>";
3855
  }
3856
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3857
  $wafActionContent .= "
3858
  <form action='$adminURL' method='post'>
3859
  <input type='hidden' name='wfnonce' value='$wfnonce'>
3860
- <select name='serverConfiguration'>
3861
  $wafPrependOptions
3862
  </select>
3863
  <button class='button button-primary' type='submit'>Continue</button>
3864
  </form>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3865
  ";
3866
 
3867
  $wafActionContent .= "
@@ -3943,12 +3977,12 @@ $wafPrependOptions
3943
  }
3944
 
3945
  public static function replaceVersion($url) {
3946
- return preg_replace_callback("/([&;\?]ver)=(.+?)(?:&|$)/", "wordfence::replaceVersionCallback", $url);
3947
  }
3948
 
3949
  public static function replaceVersionCallback($matches) {
3950
  global $wp_version;
3951
- return $matches[1] . '=' . ($wp_version === $matches[2] ? wp_hash($matches[2]) : $matches[2]);
3952
  }
3953
 
3954
  public static function genFilter($gen, $type){
@@ -4951,8 +4985,12 @@ LIMIT %d", $lastSendTime, $limit));
4951
 
4952
  public static function wafAutoPrependNotice() {
4953
  $url = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configureAutoPrepend');
4954
- echo '<div class="update-nag">To make your site as secure as possible, take a moment to setup the Wordfence Web
4955
- Application Firewall: &nbsp;<a class="button button-small" href="' . esc_url($url) . '">Click here to configure.</a><br>
 
 
 
 
4956
  <em style="font-size: 85%;">If you cannot complete the setup process,
4957
  <a target="_blank" href="https://docs.wordfence.com/en/Web_Application_Firewall_Setup">click here for help</a>.</em>
4958
  </div>';
3355
  self::setCookie();
3356
  }
3357
  // This is more of a hurdle, but might stop an automated process.
3358
+ // if (current_user_can('administrator')) {
3359
+ // $adminUsers = new wfAdminUserMonitor();
3360
+ // if ($adminUsers->isEnabled() && !$adminUsers->isAdminUserLogged(get_current_user_id())) {
3361
+ // define('DISALLOW_FILE_MODS', true);
3362
+ // }
3363
+ // }
3364
 
3365
  $currentUserID = get_current_user_id();
3366
  $role = wordfence::getCurrentUserRole();
3474
  }
3475
 
3476
  if (!WFWAF_AUTO_PREPEND || WFWAF_SUBDIRECTORY_INSTALL) {
3477
+ if (empty($_GET['wafAction']) && !wfConfig::get('dismissAutoPrependNotice')) {
3478
  if (is_multisite()) {
3479
  add_action('network_admin_notices', 'wordfence::wafAutoPrependNotice');
3480
  } else {
3690
 
3691
  if (!empty($_GET['wafAction'])) {
3692
  switch ($_GET['wafAction']) {
3693
+ case 'dismissAutoPrependNotice':
3694
+ check_admin_referer('wfDismissAutoPrependNotice', 'nonce');
3695
+ wfConfig::set('dismissAutoPrependNotice', 1);
3696
+
3697
+ break;
3698
+
3699
  case 'configureAutoPrepend':
3700
  if (WFWAF_AUTO_PREPEND && !WFWAF_SUBDIRECTORY_INSTALL) {
3701
  break;
3860
  you know your web server's configuration, please select it now.</p>";
3861
  }
3862
 
3863
+ $userIni = ini_get('user_ini.filename');
3864
+ $nginxIniWarning = '';
3865
+ if ($userIni) {
3866
+ $nginxIniWarning = "<div class='wf-notice wf-nginx-waf-config'>
3867
+ Part of the Firewall configuration procedure for NGINX depends on creating a <code>" . esc_html($userIni) . "</code> file
3868
+ in the root of your WordPress installation. This file can contain sensitive information and public access to it should
3869
+ be restricted. We have
3870
+ <a href='https://docs.wordfence.com/en/Web_Application_Firewall_FAQ#NGINX'>instructions on our documentation site</a> on what
3871
+ directives to put in your nginx.conf to fix this.
3872
+ ";
3873
+ }
3874
+
3875
+
3876
  $wafActionContent .= "
3877
  <form action='$adminURL' method='post'>
3878
  <input type='hidden' name='wfnonce' value='$wfnonce'>
3879
+ <select name='serverConfiguration' id='wf-waf-server-config'>
3880
  $wafPrependOptions
3881
  </select>
3882
  <button class='button button-primary' type='submit'>Continue</button>
3883
  </form>
3884
+ $nginxIniWarning
3885
+ </div>
3886
+ <script>
3887
+ (function($) {
3888
+ var nginxNotice = $('.wf-nginx-waf-config').hide();
3889
+ $('#wf-waf-server-config').on('change', function() {
3890
+ var el = $(this);
3891
+ if (el.val() == 'nginx') {
3892
+ nginxNotice.fadeIn();
3893
+ } else {
3894
+ nginxNotice.fadeOut();
3895
+ }
3896
+ }).triggerHandler('change');
3897
+ })(jQuery);
3898
+ </script>
3899
  ";
3900
 
3901
  $wafActionContent .= "
3977
  }
3978
 
3979
  public static function replaceVersion($url) {
3980
+ return preg_replace_callback("/([&;\?]ver)=(.+?)(&|$)/", "wordfence::replaceVersionCallback", $url);
3981
  }
3982
 
3983
  public static function replaceVersionCallback($matches) {
3984
  global $wp_version;
3985
+ return $matches[1] . '=' . ($wp_version === $matches[2] ? wp_hash($matches[2]) : $matches[2]) . $matches[3];
3986
  }
3987
 
3988
  public static function genFilter($gen, $type){
4985
 
4986
  public static function wafAutoPrependNotice() {
4987
  $url = network_admin_url('admin.php?page=WordfenceWAF&wafAction=configureAutoPrepend');
4988
+ $dismissURL = network_admin_url('admin.php?page=WordfenceWAF&wafAction=dismissAutoPrependNotice&nonce=' .
4989
+ rawurlencode(wp_create_nonce('wfDismissAutoPrependNotice')));
4990
+ echo '<div class="update-nag" id="wf-extended-protection-notice">To make your site as secure as possible, take a moment to optimize the Wordfence Web
4991
+ Application Firewall: &nbsp;<a class="button button-small" href="' . esc_url($url) . '">Click here to configure.</a>
4992
+ <a class="button button-small wf-dismiss-link" href="' . esc_url($dismissURL) . '">Dismiss</a>
4993
+ <br>
4994
  <em style="font-size: 85%;">If you cannot complete the setup process,
4995
  <a target="_blank" href="https://docs.wordfence.com/en/Web_Application_Firewall_Setup">click here for help</a>.</em>
4996
  </div>';
readme.txt CHANGED
@@ -3,7 +3,7 @@ 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
6
- Stable tag: 6.1.2
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,14 @@ Designed for every skill level, [The WordPress Security Learning Center](https:/
195
 
196
  == Changelog ==
197
 
 
 
 
 
 
 
 
 
198
  = 6.1.2 =
199
  * Fix: Fixed fatal error when using a whitelisted IPv6 range and connecting with an IPv6 address.
200
 
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
6
+ Stable tag: 6.1.3
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.3 =
199
+ * Improvement: Added dismiss button to the Wordfence WAF setup admin notice.
200
+ * Fix: Removed .htaccess and .user.ini from publicly accessible config and backup file scan.
201
+ * Fix: Removed the disallow file mods for admins created outside of WordPress.
202
+ * Fix: Fixed bug with 'Hide WordPress version' causing issues with reCAPTCHA.
203
+ * Improvement: Added instructions for NGINX users to restrict access to .user.ini during Firewall configuration.
204
+ * Fix: Fixed bug with multiple API calls to 'get_known_files'.
205
+
206
  = 6.1.2 =
207
  * Fix: Fixed fatal error when using a whitelisted IPv6 range and connecting with an IPv6 address.
208
 
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.2
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.2');
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.3
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.3');
15
  define('WORDFENCE_BASENAME', function_exists('plugin_basename') ? plugin_basename(__FILE__) :
16
  basename(dirname(__FILE__)) . '/' . basename(__FILE__));
17