iThemes Security (formerly Better WP Security) - Version 5.5.0

Version Description

  • New Feature: Added a new File Permissions section on the settings page to bring back the directory and file permissions listing feature found on the Security > Dashboard page of older plugin versions.
    • Bug Fix: Fixed a situation where adding a very large list of IP's in the Ban Hosts list would generate an invalid .htaccess file on some servers.
    • Enhancement: The Database Backups, Local Brute Force Protection, Network Brute Force Protection, Strong Password Enforcement, and WordPress Tweaks features are now active by default on new installations.
    • Enhancement: The WordPress Tweaks feature now uses the "Disable File Editor" setting by default on new installations.
    • Enhancement: The WordPress Tweaks feature now sets the "Multiple Authentication Attempts per XML-RPC Request" setting to "Block" by default on new installations.
    • Enhancement: Improved the styling of notices.
Download this release

Release Info

Developer chrisjean
Plugin Icon 128x128 iThemes Security (formerly Better WP Security)
Version 5.5.0
Comparing to
See all releases

Code changes from version 5.4.5 to 5.5.0

better-wp-security.php CHANGED
@@ -6,7 +6,7 @@
6
  * Description: Take the guesswork out of WordPress security. iThemes Security offers 30+ ways to lock down WordPress in an easy-to-use WordPress security plugin.
7
  * Author: iThemes
8
  * Author URI: https://ithemes.com
9
- * Version: 5.4.5
10
  * Text Domain: better-wp-security
11
  * Network: True
12
  * License: GPLv2
6
  * Description: Take the guesswork out of WordPress security. iThemes Security offers 30+ ways to lock down WordPress in an easy-to-use WordPress security plugin.
7
  * Author: iThemes
8
  * Author URI: https://ithemes.com
9
+ * Version: 5.5.0
10
  * Text Domain: better-wp-security
11
  * Network: True
12
  * License: GPLv2
core/admin-pages/js/script.js CHANGED
@@ -46,6 +46,7 @@ var itsecSettingsPage = {
46
  $container.on( 'keyup', this.closeGridSettingsModal );
47
  $container.on( 'click', '.itsec-toggle-activation', this.toggleModuleActivation );
48
  $container.on( 'click', '.itsec-module-settings-save', this.saveSettings );
 
49
 
50
  $container.on( 'change', '#itsec-filter', this.logPageChangeFilter );
51
 
@@ -491,6 +492,12 @@ var itsecSettingsPage = {
491
  },
492
 
493
  reloadModule: function( module ) {
 
 
 
 
 
 
494
  var method = 'get_refreshed_module_settings';
495
  var data = {};
496
 
46
  $container.on( 'keyup', this.closeGridSettingsModal );
47
  $container.on( 'click', '.itsec-toggle-activation', this.toggleModuleActivation );
48
  $container.on( 'click', '.itsec-module-settings-save', this.saveSettings );
49
+ $container.on( 'click', '.itsec-reload-module', this.reloadModule );
50
 
51
  $container.on( 'change', '#itsec-filter', this.logPageChangeFilter );
52
 
492
  },
493
 
494
  reloadModule: function( module ) {
495
+ if ( module.preventDefault ) {
496
+ module.preventDefault();
497
+
498
+ module = jQuery(this).parents( '.itsec-module-card' ).attr( 'id' ).replace( 'itsec-module-card-', '' );
499
+ }
500
+
501
  var method = 'get_refreshed_module_settings';
502
  var data = {};
503
 
core/admin-pages/page-settings.php CHANGED
@@ -482,7 +482,7 @@ final class ITSEC_Settings_Page {
482
  <li id="itsec-module-card-<?php echo $id; ?>" class="itsec-module-card <?php echo implode( ' ', $classes ); ?>" data-module-id="<?php echo $id; ?>">
483
  <div class="itsec-module-card-content">
484
  <?php if ( $module->upsell ) : ?>
485
- <a href="<?php echo esc_url( $module->upsell_url ); ?>" target="_blank" class="itsec-pro-upsell">&nbsp;</a>
486
  <?php endif; ?>
487
  <h2><?php echo esc_html( $module->title ); ?></h2>
488
  <?php if ( $module->pro ) : ?>
@@ -490,59 +490,59 @@ final class ITSEC_Settings_Page {
490
  <?php endif; ?>
491
  <p class="module-description"><?php echo $module->description; ?></p>
492
  <?php if ( ! $module->upsell ) : ?>
493
- <div class="module-actions hide-if-no-js">
494
- <?php if ( $module->information_only ) : ?>
495
- <button class="button button-secondary itsec-toggle-settings information-only"><?php echo $this->translations['show_information']; ?></button>
496
- <?php elseif ( $module->enabled || $module->always_active ) : ?>
497
- <button class="button button-secondary itsec-toggle-settings"><?php echo $this->translations['show_settings']; ?></button>
498
- <?php if ( ! $module->always_active ) : ?>
499
- <button class="button button-secondary itsec-toggle-activation"><?php echo $this->translations['deactivate']; ?></button>
 
 
 
 
500
  <?php endif; ?>
501
- <?php else : ?>
502
- <button class="button button-secondary itsec-toggle-settings"><?php echo $this->translations['show_description']; ?></button>
503
- <button class="button button-primary itsec-toggle-activation"><?php echo $this->translations['activate']; ?></button>
504
- <?php endif; ?>
505
- </div>
506
  <?php endif; ?>
507
  </div>
508
  <?php if ( ! $module->upsell ) : ?>
509
- <div class="itsec-module-settings-container">
510
- <div class="itsec-modal-navigation">
511
- <button class="dashicons itsec-close-modal"></button>
512
- <button class="itsec-right dashicons hidden"><span class="screen-reader-text"><?php _e( 'Configure next iThemes Security setting', 'better-wp-security' ); ?></span></button>
513
- <button class="itsec-left dashicons hidden"><span class="screen-reader-text"><?php _e( 'Configure previous iThemes Security setting', 'better-wp-security' ); ?></span></button>
514
- </div>
515
- <div class="itsec-module-settings-content-container">
516
- <div class="itsec-module-settings-content">
517
- <h3 class="itsec-modal-header"><?php echo esc_html( $module->title ); ?></h3>
518
- <div class="itsec-module-messages-container"></div>
519
- <div class="itsec-module-settings-content-main">
520
- <?php $this->get_module_settings( $id, $form, true ); ?>
 
521
  </div>
522
  </div>
523
- </div>
524
- <div class="itsec-list-content-footer hide-if-no-js">
525
- <?php if ( $module->can_save ) : ?>
526
- <button class="button button-primary align-left itsec-module-settings-save"><?php echo $this->translations['save_settings']; ?></button>
527
- <?php endif; ?>
528
- <button class="button button-secondary align-left itsec-module-settings-cancel"><?php _e( 'Cancel', 'better-wp-security' ); ?></button>
529
- </div>
530
- <div class="itsec-modal-content-footer">
531
- <?php if ( $module->enabled || $module->always_active || $module->information_only ) : ?>
532
- <?php if ( ! $module->always_active && ! $module->information_only ) : ?>
533
- <button class="button button-secondary align-right itsec-toggle-activation"><?php echo $this->translations['deactivate']; ?></button>
534
  <?php endif; ?>
535
- <?php else : ?>
536
- <button class="button button-primary align-right itsec-toggle-activation"><?php echo $this->translations['activate']; ?></button>
537
- <?php endif; ?>
538
-
539
- <?php if ( $module->can_save ) : ?>
540
- <button class="button button-primary align-left itsec-module-settings-save"><?php echo $this->translations['save_settings']; ?></button>
541
- <?php else : ?>
542
- <button class="button button-primary align-left itsec-close-modal"><?php echo $this->translations['close_settings']; ?></button>
543
- <?php endif; ?>
 
 
 
 
 
 
 
 
544
  </div>
545
- </div>
546
  <?php endif; ?>
547
  </li>
548
  <?php endforeach; ?>
482
  <li id="itsec-module-card-<?php echo $id; ?>" class="itsec-module-card <?php echo implode( ' ', $classes ); ?>" data-module-id="<?php echo $id; ?>">
483
  <div class="itsec-module-card-content">
484
  <?php if ( $module->upsell ) : ?>
485
+ <a href="<?php echo esc_url( $module->upsell_url ); ?>" target="_blank" class="itsec-pro-upsell">&nbsp;</a>
486
  <?php endif; ?>
487
  <h2><?php echo esc_html( $module->title ); ?></h2>
488
  <?php if ( $module->pro ) : ?>
490
  <?php endif; ?>
491
  <p class="module-description"><?php echo $module->description; ?></p>
492
  <?php if ( ! $module->upsell ) : ?>
493
+ <div class="module-actions hide-if-no-js">
494
+ <?php if ( $module->information_only ) : ?>
495
+ <button class="button button-secondary itsec-toggle-settings information-only"><?php echo $this->translations['show_information']; ?></button>
496
+ <?php elseif ( $module->enabled || $module->always_active ) : ?>
497
+ <button class="button button-secondary itsec-toggle-settings"><?php echo $this->translations['show_settings']; ?></button>
498
+ <?php if ( ! $module->always_active ) : ?>
499
+ <button class="button button-secondary itsec-toggle-activation"><?php echo $this->translations['deactivate']; ?></button>
500
+ <?php endif; ?>
501
+ <?php else : ?>
502
+ <button class="button button-secondary itsec-toggle-settings"><?php echo $this->translations['show_description']; ?></button>
503
+ <button class="button button-primary itsec-toggle-activation"><?php echo $this->translations['activate']; ?></button>
504
  <?php endif; ?>
505
+ </div>
 
 
 
 
506
  <?php endif; ?>
507
  </div>
508
  <?php if ( ! $module->upsell ) : ?>
509
+ <div class="itsec-module-settings-container">
510
+ <div class="itsec-modal-navigation">
511
+ <button class="dashicons itsec-close-modal"></button>
512
+ <button class="itsec-right dashicons hidden"><span class="screen-reader-text"><?php _e( 'Configure next iThemes Security setting', 'better-wp-security' ); ?></span></button>
513
+ <button class="itsec-left dashicons hidden"><span class="screen-reader-text"><?php _e( 'Configure previous iThemes Security setting', 'better-wp-security' ); ?></span></button>
514
+ </div>
515
+ <div class="itsec-module-settings-content-container">
516
+ <div class="itsec-module-settings-content">
517
+ <h3 class="itsec-modal-header"><?php echo esc_html( $module->title ); ?></h3>
518
+ <div class="itsec-module-messages-container"></div>
519
+ <div class="itsec-module-settings-content-main">
520
+ <?php $this->get_module_settings( $id, $form, true ); ?>
521
+ </div>
522
  </div>
523
  </div>
524
+ <div class="itsec-list-content-footer hide-if-no-js">
525
+ <?php if ( $module->can_save ) : ?>
526
+ <button class="button button-primary align-left itsec-module-settings-save"><?php echo $this->translations['save_settings']; ?></button>
 
 
 
 
 
 
 
 
527
  <?php endif; ?>
528
+ <button class="button button-secondary align-left itsec-module-settings-cancel"><?php _e( 'Cancel', 'better-wp-security' ); ?></button>
529
+ </div>
530
+ <div class="itsec-modal-content-footer">
531
+ <?php if ( $module->enabled || $module->always_active || $module->information_only ) : ?>
532
+ <?php if ( ! $module->always_active && ! $module->information_only ) : ?>
533
+ <button class="button button-secondary align-right itsec-toggle-activation"><?php echo $this->translations['deactivate']; ?></button>
534
+ <?php endif; ?>
535
+ <?php else : ?>
536
+ <button class="button button-primary align-right itsec-toggle-activation"><?php echo $this->translations['activate']; ?></button>
537
+ <?php endif; ?>
538
+
539
+ <?php if ( $module->can_save ) : ?>
540
+ <button class="button button-primary align-left itsec-module-settings-save"><?php echo $this->translations['save_settings']; ?></button>
541
+ <?php else : ?>
542
+ <button class="button button-primary align-left itsec-close-modal"><?php echo $this->translations['close_settings']; ?></button>
543
+ <?php endif; ?>
544
+ </div>
545
  </div>
 
546
  <?php endif; ?>
547
  </li>
548
  <?php endforeach; ?>
core/class-itsec-core.php CHANGED
@@ -221,6 +221,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
221
  include( "$path/modules/core/init.php" );
222
  include( "$path/modules/backup/init.php" );
223
  include( "$path/modules/file-change/init.php" );
 
224
  include( "$path/modules/hide-backend/init.php" );
225
  include( "$path/modules/ipcheck/init.php" );
226
  include( "$path/modules/malware/init.php" );
221
  include( "$path/modules/core/init.php" );
222
  include( "$path/modules/backup/init.php" );
223
  include( "$path/modules/file-change/init.php" );
224
+ include( "$path/modules/file-permissions/init.php" );
225
  include( "$path/modules/hide-backend/init.php" );
226
  include( "$path/modules/ipcheck/init.php" );
227
  include( "$path/modules/malware/init.php" );
core/class-itsec-lib.php CHANGED
@@ -142,17 +142,9 @@ final class ITSEC_Lib {
142
  * @return string path to wp-config.php
143
  * */
144
  public static function get_config() {
 
145
 
146
- if ( file_exists( trailingslashit( ABSPATH ) . 'wp-config.php' ) ) {
147
-
148
- return trailingslashit( ABSPATH ) . 'wp-config.php';
149
-
150
- } else {
151
-
152
- return trailingslashit( dirname( ABSPATH ) ) . 'wp-config.php';
153
-
154
- }
155
-
156
  }
157
 
158
  /**
@@ -206,23 +198,23 @@ final class ITSEC_Lib {
206
  if ( is_multisite() && function_exists( 'domain_mapping_warning' ) ) {
207
  return '*';
208
  }
209
-
210
-
211
  $host = parse_url( $url, PHP_URL_HOST );
212
-
213
  if ( false === $host ) {
214
  return '*';
215
  }
216
  if ( 'www.' == substr( $host, 0, 4 ) ) {
217
  return substr( $host, 4 );
218
  }
219
-
220
  $host_parts = explode( '.', $host );
221
-
222
  if ( count( $host_parts ) > 2 ) {
223
  $host_parts = array_slice( $host_parts, -2, 2 );
224
  }
225
-
226
  return implode( '.', $host_parts );
227
  }
228
 
@@ -303,17 +295,9 @@ final class ITSEC_Lib {
303
  * @return string path to .htaccess
304
  */
305
  public static function get_htaccess() {
 
306
 
307
- if ( 'nginx' === ITSEC_Lib::get_server() ) {
308
-
309
- return ITSEC_Modules::get_setting( 'global', 'nginx_file' );
310
-
311
- } else {
312
-
313
- return ITSEC_Lib::get_home_path() . '.htaccess';
314
-
315
- }
316
-
317
  }
318
 
319
  /**
@@ -408,7 +392,7 @@ final class ITSEC_Lib {
408
  */
409
  public static function get_server() {
410
  require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-utility.php' );
411
-
412
  return ITSEC_Lib_Utility::get_web_server();
413
  }
414
 
@@ -472,7 +456,7 @@ final class ITSEC_Lib {
472
  public static function get_whitelisted_ips() {
473
  return apply_filters( 'itsec_white_ips', array() );
474
  }
475
-
476
  /**
477
  * Determines whether a given IP address is whiteliste
478
  *
@@ -516,7 +500,7 @@ final class ITSEC_Lib {
516
  public static function get_blacklisted_ips() {
517
  return apply_filters( 'itsec_filter_blacklisted_ips', array() );
518
  }
519
-
520
  /**
521
  * Determines whether a given IP address is blacklisted
522
  *
@@ -527,25 +511,25 @@ final class ITSEC_Lib {
527
  */
528
  public static function is_ip_blacklisted( $ip = null, $blacklisted_ips = null ) {
529
  $ip = sanitize_text_field( $ip );
530
-
531
  if ( empty( $ip ) ) {
532
  $ip = ITSEC_Lib::get_ip();
533
  }
534
-
535
  if ( ! class_exists( 'ITSEC_Lib_IP_Tools' ) ) {
536
  require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-ip-tools.php' );
537
  }
538
-
539
  if ( is_null( $blacklisted_ips ) ) {
540
  $blacklisted_ips = self::get_blacklisted_ips();
541
  }
542
-
543
  foreach ( $blacklisted_ips as $blacklisted_ip ) {
544
  if ( ITSEC_Lib_IP_Tools::intersect( $ip, ITSEC_Lib_IP_Tools::ip_wild_to_ip_cidr( $blacklisted_ip ) ) ) {
545
  return true;
546
  }
547
  }
548
-
549
  return false;
550
  }
551
 
142
  * @return string path to wp-config.php
143
  * */
144
  public static function get_config() {
145
+ require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-config-file.php' );
146
 
147
+ return ITSEC_Lib_Config_File::get_wp_config_file_path();
 
 
 
 
 
 
 
 
 
148
  }
149
 
150
  /**
198
  if ( is_multisite() && function_exists( 'domain_mapping_warning' ) ) {
199
  return '*';
200
  }
201
+
202
+
203
  $host = parse_url( $url, PHP_URL_HOST );
204
+
205
  if ( false === $host ) {
206
  return '*';
207
  }
208
  if ( 'www.' == substr( $host, 0, 4 ) ) {
209
  return substr( $host, 4 );
210
  }
211
+
212
  $host_parts = explode( '.', $host );
213
+
214
  if ( count( $host_parts ) > 2 ) {
215
  $host_parts = array_slice( $host_parts, -2, 2 );
216
  }
217
+
218
  return implode( '.', $host_parts );
219
  }
220
 
295
  * @return string path to .htaccess
296
  */
297
  public static function get_htaccess() {
298
+ require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-config-file.php' );
299
 
300
+ return ITSEC_Lib_Config_File::get_server_config_file_path();
 
 
 
 
 
 
 
 
 
301
  }
302
 
303
  /**
392
  */
393
  public static function get_server() {
394
  require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-utility.php' );
395
+
396
  return ITSEC_Lib_Utility::get_web_server();
397
  }
398
 
456
  public static function get_whitelisted_ips() {
457
  return apply_filters( 'itsec_white_ips', array() );
458
  }
459
+
460
  /**
461
  * Determines whether a given IP address is whiteliste
462
  *
500
  public static function get_blacklisted_ips() {
501
  return apply_filters( 'itsec_filter_blacklisted_ips', array() );
502
  }
503
+
504
  /**
505
  * Determines whether a given IP address is blacklisted
506
  *
511
  */
512
  public static function is_ip_blacklisted( $ip = null, $blacklisted_ips = null ) {
513
  $ip = sanitize_text_field( $ip );
514
+
515
  if ( empty( $ip ) ) {
516
  $ip = ITSEC_Lib::get_ip();
517
  }
518
+
519
  if ( ! class_exists( 'ITSEC_Lib_IP_Tools' ) ) {
520
  require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-ip-tools.php' );
521
  }
522
+
523
  if ( is_null( $blacklisted_ips ) ) {
524
  $blacklisted_ips = self::get_blacklisted_ips();
525
  }
526
+
527
  foreach ( $blacklisted_ips as $blacklisted_ip ) {
528
  if ( ITSEC_Lib_IP_Tools::intersect( $ip, ITSEC_Lib_IP_Tools::ip_wild_to_ip_cidr( $blacklisted_ip ) ) ) {
529
  return true;
530
  }
531
  }
532
+
533
  return false;
534
  }
535
 
core/css/itsec_notice.css CHANGED
@@ -1,120 +1,86 @@
1
- #itsec_setup_notice,
2
- #itsec_support_notice,
3
- #itsec_upgrade_notice,
4
- .itsec-notice {
5
- margin : 1em 0;
6
- position : relative;
7
- font-size : 14px;
8
- line-height : 1.6;
9
- -webkit-border-radius : 3px;
10
- -moz-border-radius : 3px;
11
- border-radius : 3px;
12
- color : #3e85b5;
13
-
14
- border : 1px solid #9fd0f1;
15
- border-bottom-width : 3px;
16
- background : #e3eef6;
17
- -webkit-box-shadow : none;
18
- -moz-box-shadow : none;
19
- box-shadow : none;
20
  }
21
 
22
- #itsec_support_notice span {
23
- display : block;
24
- margin-bottom : 1.5em;
25
- padding-right : 3em;
26
  }
27
 
28
- #itsec_setup_notice span.it-icon-itsec,
29
- #itsec_support_notice span.it-icon-itsec,
30
- .itsec-notice span.it-icon-itsec {
31
- font-size : 2em;
32
- line-height : .1;
33
- vertical-align : middle;
34
- margin : 0;
35
- margin-right : .5em;
36
- padding : 0;
37
- display : inline;
38
  }
39
 
40
- #itsec_support_notice {
41
- padding-bottom : 2em;
42
- }
43
-
44
- #itsec_setup_notice .itsec-notice-button,
45
- #itsec_support_notice .itsec-notice-button,
46
- .itsec-notice .itsec-notice-button {
47
- background : #9fd0f1;
48
- border : 1px solid #79afd3;
49
- border-bottom-width : 2px;
50
- border-radius : 3px;
51
- display : inline-block;
52
- margin : 10px 0 10px 10px;
53
- padding : 10px 18px;
54
- -webkit-transition : all .1s linear;
55
- -moz-transition : all .1s linear;
56
- transition : all .1s linear;
57
-
58
- color : #0071bc;
59
- font-weight : bold;
60
- text-decoration : none;
61
  }
62
 
63
  .itsec_notice_text {
64
- display : block;
65
- margin : 10px 0 10px 0;
66
  }
67
 
68
- #itsec_support_notice .itsec-notice-button {
69
- margin-left : 0;
70
- margin-right : 10px;
71
- }
72
-
73
- #itsec_setup_notice .itsec-notice-button:hover,
74
- #itsec_support_notice .itsec-notice-button:hover,
75
  .itsec-notice .itsec-notice-button:hover {
76
- background : #eff7fd;
77
- cursor : pointer;
78
  }
79
 
80
- #itsec_setup_notice .itsec-notice-hide,
81
- #itsec_support_notice .itsec-notice-hide,
82
- #itsec_upgrade_notice .itsec-notice-hide,
83
  .itsec-notice .itsec-notice-hide {
84
- border : 1px solid transparent;
85
- border-radius : 3px;
86
- display : inline-block;
87
- float : right;
88
- margin : 8px 0;
89
- padding : 7px 14px;
90
- -webkit-transition : all .1s linear;
91
- -moz-transition : all .1s linear;
92
- transition : all .1s linear;
93
- background : none;
94
- font-weight : bold;
95
- text-decoration : none;
96
- }
97
-
98
- #itsec_support_notice .itsec-notice-hide {
99
- float : none;
100
- position : absolute;
101
- top : 14px;
102
- right : 8px;
103
  }
104
 
105
- #itsec_setup_notice .itsec-notice-hide:hover,
106
- #itsec_support_notice .itsec-notice-hide:hover,
107
- #itsec_upgrade_notice .itsec-notice-hide:hover,
108
  .itsec-notice .itsec-notice-hide:hover {
109
- background : #9fd0f1;
110
- border : 1px solid #79afd3;
111
- border-bottom-width : 2px;
112
- border-radius : 3px;
113
- cursor : pointer;
114
  }
115
 
116
- #itsec_setup_notice a.itsec-notice-button,
117
  .itsec-notice a.itsec-notice-button {
118
- line-height : 15px;
119
- font-size : 14px;
120
- }
1
+ .updated.itsec-notice {
2
+ margin: 1em 0;
3
+ position: relative;
4
+ font-size: 14px;
5
+ line-height: 1.6;
6
+ -webkit-border-radius: 3px;
7
+ -moz-border-radius: 3px;
8
+ border-radius: 3px;
9
+ color: #3e85b5;
10
+ border: 1px solid #9fd0f1;
11
+ border-bottom-width: 3px;
12
+ background: #e3eef6;
13
+ -webkit-box-shadow: none;
14
+ -moz-box-shadow: none;
15
+ box-shadow: none;
16
+ padding: 10px 60px 10px 10px !important;
 
 
 
17
  }
18
 
19
+ .updated.itsec-notice p {
20
+ font-size: 14px;
 
 
21
  }
22
 
23
+ .updated.itsec-notice span.it-icon-itsec {
24
+ font-size: 2em;
25
+ line-height: .1;
26
+ vertical-align: middle;
27
+ margin: 0;
28
+ margin-right: .5em;
29
+ padding: 0;
30
+ display: inline;
 
 
31
  }
32
 
33
+ .updated.itsec-notice .itsec-notice-button {
34
+ background: #9fd0f1;
35
+ border: 1px solid #79afd3;
36
+ border-bottom-width: 2px;
37
+ border-radius: 3px;
38
+ display: inline-block;
39
+ margin: 4px 10px;
40
+ padding: 10px 18px;
41
+ -webkit-transition: all .1s linear;
42
+ -moz-transition: all .1s linear;
43
+ transition: all .1s linear;
44
+ color: #0071bc;
45
+ font-weight: bold;
46
+ text-decoration: none;
 
 
 
 
 
 
 
47
  }
48
 
49
  .itsec_notice_text {
50
+ display: block;
51
+ margin: 10px 0 10px 0;
52
  }
53
 
 
 
 
 
 
 
 
54
  .itsec-notice .itsec-notice-button:hover {
55
+ background: #eff7fd;
56
+ cursor: pointer;
57
  }
58
 
 
 
 
59
  .itsec-notice .itsec-notice-hide {
60
+ border: 1px solid transparent;
61
+ border-radius: 3px;
62
+ padding: 7px 14px;
63
+ -webkit-transition: all .1s linear;
64
+ -moz-transition: all .1s linear;
65
+ transition: all .1s linear;
66
+ background: none;
67
+ font-weight: bold;
68
+ text-decoration: none;
69
+ position: absolute;
70
+ top: 50%;
71
+ margin-top: -17px;
72
+ right: 10px;
 
 
 
 
 
 
73
  }
74
 
 
 
 
75
  .itsec-notice .itsec-notice-hide:hover {
76
+ background: #9fd0f1;
77
+ border: 1px solid #79afd3;
78
+ border-bottom-width: 2px;
79
+ border-radius: 3px;
80
+ cursor: pointer;
81
  }
82
 
 
83
  .itsec-notice a.itsec-notice-button {
84
+ line-height: 15px;
85
+ font-size: 14px;
86
+ }
core/history.txt CHANGED
@@ -397,3 +397,10 @@
397
  Bug Fix: Removed some status messages that would display after doing an import.
398
  2.3.7 - 2016-05-27 - Chris Jean & Aaron D. Campbell
399
  Bug Fix: Fixed SQL query for Database Backups when "Backup Full Database" is enabled.
 
 
 
 
 
 
 
397
  Bug Fix: Removed some status messages that would display after doing an import.
398
  2.3.7 - 2016-05-27 - Chris Jean & Aaron D. Campbell
399
  Bug Fix: Fixed SQL query for Database Backups when "Backup Full Database" is enabled.
400
+ 2.4.0 - 2016-06-07 - Chris Jean & Aaron D. Campbell
401
+ New Feature: Added a new File Permissions section on the settings page to bring back the directory and file permissions listing feature found on the Security > Dashboard page of older plugin versions.
402
+ Bug Fix: Fixed a situation where adding a very large list of IP's in the Ban Hosts list would generate an invalid .htaccess file on some servers.
403
+ Enhancement: The Database Backups, Local Brute Force Protection, Network Brute Force Protection, Strong Password Enforcement, and WordPress Tweaks features are now active by default on new installations.
404
+ Enhancement: The WordPress Tweaks feature now uses the "Disable File Editor" setting by default on new installations.
405
+ Enhancement: The WordPress Tweaks feature now sets the "Multiple Authentication Attempts per XML-RPC Request" setting to "Block" by default on new installations.
406
+ Enhancement: Improved the styling of notices.
core/lib/class-itsec-lib-config-file.php CHANGED
@@ -355,13 +355,38 @@ class ITSEC_Lib_Config_File {
355
  $line_ending = self::get_line_ending( $contents );
356
 
357
  $patterns = array(
358
- "$quoted_comment_delimiter+\s*BEGIN\s+iThemes\s+Security.*?$quoted_comment_delimiter+\s*END\s+iThemes\s+Security",
359
- "$quoted_comment_delimiter+\s*BEGIN\s+Better\s+WP\s+Security.*?$quoted_comment_delimiter+\s*END\s+Better\s+WP\s+Security",
 
 
 
 
 
 
360
  );
361
 
362
  // Remove matched content.
363
  foreach ( $patterns as $pattern ) {
364
- $contents = preg_replace( "/\s*{$pattern}[^\r\n]*\s*/is", "$line_ending$placeholder", $contents );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
  }
366
 
367
 
355
  $line_ending = self::get_line_ending( $contents );
356
 
357
  $patterns = array(
358
+ array(
359
+ 'begin' => "$quoted_comment_delimiter+\s*BEGIN\s+iThemes\s+Security",
360
+ 'end' => "$quoted_comment_delimiter+\s*END\s+iThemes\s+Security",
361
+ ),
362
+ array(
363
+ 'begin' => "$quoted_comment_delimiter+\s*BEGIN\s+Better\s+WP\s+Security",
364
+ 'end' => "$quoted_comment_delimiter+\s*END\s+Better\s+WP\s+Security",
365
+ ),
366
  );
367
 
368
  // Remove matched content.
369
  foreach ( $patterns as $pattern ) {
370
+ // Look for the first beginning tag
371
+ preg_match( "/\s*{$pattern['begin']}/i", $contents, $matches, PREG_OFFSET_CAPTURE );
372
+
373
+ // If the BEGIN string was matched
374
+ if ( ! empty( $matches ) && ! empty( $matches[0] ) ) {
375
+ $begin = $matches[0][1];
376
+
377
+ // Look for ALL end tags that occur after the BEGIN tag
378
+ preg_match_all( "/\s*{$pattern['end']}[^\r\n]*\s*/i", $contents, $matches, PREG_OFFSET_CAPTURE, $begin );
379
+
380
+ // If the END string was matched
381
+ if ( ! empty( $matches ) && ! empty( $matches[0] ) ) {
382
+ // We want the last occurrence of the END tag
383
+ $last_match = array_pop( $matches[0] );
384
+ // The end position should be the location of the end tag + the length of the end tag
385
+ $end = $last_match[1] + strlen( $last_match[0] );
386
+ // We have a start and end, so let's replace with our placeholder
387
+ $contents = substr_replace( $contents, "$line_ending$placeholder", $begin, $end - $begin );
388
+ }
389
+ }
390
  }
391
 
392
 
core/modules/backup/init.php CHANGED
@@ -1,3 +1,3 @@
1
  <?php
2
 
3
- ITSEC_Modules::register_module( 'backup', dirname( __FILE__ ) );
1
  <?php
2
 
3
+ ITSEC_Modules::register_module( 'backup', dirname( __FILE__ ), 'default-active' );
core/modules/brute-force/init.php CHANGED
@@ -1,3 +1,3 @@
1
  <?php
2
 
3
- ITSEC_Modules::register_module( 'brute-force', dirname( __FILE__ ) );
1
  <?php
2
 
3
+ ITSEC_Modules::register_module( 'brute-force', dirname( __FILE__ ), 'default-active' );
core/modules/file-permissions/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden.
core/modules/file-permissions/init.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+
3
+ ITSEC_Modules::register_module( 'file-permissions', dirname( __FILE__ ), 'always-active' );
core/modules/file-permissions/settings-page.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ final class ITSEC_File_Permissions_Settings_Page extends ITSEC_Module_Settings_Page {
4
+ public function __construct() {
5
+ $this->id = 'file-permissions';
6
+ $this->title = __( 'File Permissions', 'better-wp-security' );
7
+ $this->description = __( 'Lists file and directory permissions of key areas of the site.', 'better-wp-security' );
8
+ $this->type = 'recommended';
9
+ $this->information_only = true;
10
+ $this->can_save = false;
11
+
12
+ parent::__construct();
13
+ }
14
+
15
+ protected function render_description( $form ) {}
16
+
17
+ protected function render_settings( $form ) {
18
+ if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) {
19
+ echo '<p>' . __( 'Click the button to load the current file permissions.', 'better-wp-security' ) . '</p>';
20
+ echo '<p>' . $form->add_button( 'load_file_permissions', array( 'value' => __( 'Load File Permissions Details', 'better-wp-security' ), 'class' => 'button-primary itsec-reload-module' ) ) . '</p>';
21
+
22
+ return;
23
+ }
24
+
25
+
26
+ require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-config-file.php' );
27
+
28
+ $wp_upload_dir = ITSEC_Core::get_wp_upload_dir();
29
+
30
+ $path_data = array(
31
+ array(
32
+ ABSPATH,
33
+ 0755,
34
+ ),
35
+ array(
36
+ ABSPATH . WPINC,
37
+ 0755,
38
+ ),
39
+ array(
40
+ ABSPATH . 'wp-admin',
41
+ 0755,
42
+ ),
43
+ array(
44
+ ABSPATH . 'wp-admin/js',
45
+ 0755,
46
+ ),
47
+ array(
48
+ WP_CONTENT_DIR,
49
+ 0755,
50
+ ),
51
+ array(
52
+ get_theme_root(),
53
+ 0755,
54
+ ),
55
+ array(
56
+ WP_PLUGIN_DIR,
57
+ 0755
58
+ ),
59
+ array(
60
+ $wp_upload_dir['basedir'],
61
+ 0755,
62
+ ),
63
+ array(
64
+ ITSEC_Lib_Config_File::get_wp_config_file_path(),
65
+ 0444,
66
+ ),
67
+ array(
68
+ ITSEC_Lib_Config_File::get_server_config_file_path(),
69
+ 0444,
70
+ ),
71
+ );
72
+
73
+
74
+ $rows = array();
75
+
76
+ foreach ( $path_data as $path ) {
77
+ $row = array();
78
+
79
+ list( $path, $suggested_permissions ) = $path;
80
+
81
+ $display_path = preg_replace( '/^' . preg_quote( ABSPATH, '/' ) . '/', '', $path );
82
+ $display_path = ltrim( $display_path, '/' );
83
+
84
+ if ( empty( $display_path ) ) {
85
+ $display_path = '/';
86
+ }
87
+
88
+ $row[] = $display_path;
89
+ $row[] = sprintf( '%o', $suggested_permissions );
90
+
91
+ $permissions = fileperms( $path ) & 0777;
92
+ $row[] = sprintf( '%o', $permissions );
93
+
94
+ if ( ! $permissions || $permissions != $suggested_permissions ) {
95
+ $row[] = __( 'WARNING', 'better-wp-security' );
96
+ $row[] = '<div style="background-color: #FEFF7F; border: 1px solid #E2E2E2;">&nbsp;&nbsp;&nbsp;</div>';
97
+ } else {
98
+ $row[] = __( 'OK', 'better-wp-security' );
99
+ $row[] = '<div style="background-color: #22EE5B; border: 1px solid #E2E2E2;">&nbsp;&nbsp;&nbsp;</div>';
100
+ }
101
+
102
+ $rows[] = $row;
103
+ }
104
+
105
+
106
+ $class = 'entry-row';
107
+
108
+ ?>
109
+ <p><?php $form->add_button( 'reload_file_permissions', array( 'value' => __( 'Reload File Permissions Details', 'better-wp-security' ), 'class' => 'button-primary itsec-reload-module' ) ); ?></p>
110
+ <table class="widefat">
111
+ <thead>
112
+ <tr>
113
+ <th><?php _e( 'Relative Path', 'better-wp-security' ); ?></th>
114
+ <th><?php _e( 'Suggestion', 'better-wp-security' ); ?></th>
115
+ <th><?php _e( 'Value', 'better-wp-security' ); ?></th>
116
+ <th><?php _e( 'Result', 'better-wp-security' ); ?></th>
117
+ <th><?php _e( 'Status', 'better-wp-security' ); ?></th>
118
+ </tr>
119
+ </thead>
120
+ <tfoot>
121
+ <tr>
122
+ <th><?php _e( 'Relative Path', 'better-wp-security' ); ?></th>
123
+ <th><?php _e( 'Suggestion', 'better-wp-security' ); ?></th>
124
+ <th><?php _e( 'Value', 'better-wp-security' ); ?></th>
125
+ <th><?php _e( 'Result', 'better-wp-security' ); ?></th>
126
+ <th><?php _e( 'Status', 'better-wp-security' ); ?></th>
127
+ </tr>
128
+ </tfoot>
129
+ <tbody>
130
+ <?php foreach ( $rows as $row ) : ?>
131
+ <tr class="<?php echo $class; ?>">
132
+ <?php foreach ( $row as $column ) : ?>
133
+ <td><?php echo $column; ?></td>
134
+ <?php endforeach; ?>
135
+ </tr>
136
+ <?php $class = ( 'entry-row' === $class ) ? 'entry-row alternate' : 'entry-row'; ?>
137
+ <?php endforeach; ?>
138
+ </tbody>
139
+ </table>
140
+ <br />
141
+ <?php
142
+
143
+ }
144
+ }
145
+ new ITSEC_File_Permissions_Settings_Page();
core/modules/file-writing/settings-page.php CHANGED
@@ -8,7 +8,6 @@ final class ITSEC_Core_Server_Config_Rules_Settings_Page extends ITSEC_Module_Se
8
  $this->type = 'advanced';
9
  $this->information_only = true;
10
  $this->can_save = false;
11
- $this->always_active = true;
12
 
13
  parent::__construct();
14
  }
@@ -37,7 +36,6 @@ final class ITSEC_Core_WPConfig_File_Settings_Page extends ITSEC_Module_Settings
37
  $this->type = 'advanced';
38
  $this->information_only = true;
39
  $this->can_save = false;
40
- $this->always_active = true;
41
 
42
  parent::__construct();
43
  }
8
  $this->type = 'advanced';
9
  $this->information_only = true;
10
  $this->can_save = false;
 
11
 
12
  parent::__construct();
13
  }
36
  $this->type = 'advanced';
37
  $this->information_only = true;
38
  $this->can_save = false;
 
39
 
40
  parent::__construct();
41
  }
core/modules/ipcheck/init.php CHANGED
@@ -1,3 +1,3 @@
1
  <?php
2
 
3
- ITSEC_Modules::register_module( 'network-brute-force', dirname( __FILE__ ) );
1
  <?php
2
 
3
+ ITSEC_Modules::register_module( 'network-brute-force', dirname( __FILE__ ), 'default-active' );
core/modules/strong-passwords/init.php CHANGED
@@ -1,3 +1,3 @@
1
  <?php
2
 
3
- ITSEC_Modules::register_module( 'strong-passwords', dirname( __FILE__ ) );
1
  <?php
2
 
3
+ ITSEC_Modules::register_module( 'strong-passwords', dirname( __FILE__ ), 'default-active' );
core/modules/system-tweaks/validator.php CHANGED
@@ -4,7 +4,7 @@ class ITSEC_System_Tweaks_Validator extends ITSEC_Validator {
4
  public function get_id() {
5
  return 'system-tweaks';
6
  }
7
-
8
  protected function sanitize_settings() {
9
  $this->sanitize_setting( 'bool', 'protect_files', __( 'System Files', 'better-wp-security' ) );
10
  $this->sanitize_setting( 'bool', 'directory_browsing', __( 'Directory Browsing', 'better-wp-security' ) );
@@ -15,48 +15,51 @@ class ITSEC_System_Tweaks_Validator extends ITSEC_Validator {
15
  $this->sanitize_setting( 'bool', 'write_permissions', __( 'File Writing Permissions', 'better-wp-security' ) );
16
  $this->sanitize_setting( 'bool', 'uploads_php', __( 'Uploads', 'better-wp-security' ) );
17
  }
18
-
19
  protected function validate_settings() {
20
  if ( ! $this->can_save() ) {
21
  return;
22
  }
23
-
24
-
25
  $previous_settings = ITSEC_Modules::get_settings( $this->get_id() );
26
-
27
-
28
  $diff = array_diff_assoc( $this->settings, $previous_settings );
29
-
30
  if ( ! empty( $diff ) ) {
31
  ITSEC_Response::regenerate_server_config();
32
  }
33
-
34
-
35
  if ( $this->settings['write_permissions'] ) {
36
  // Always set permissions to 0444 when saving the settings.
37
  // This ensures that the file permissions are fixed each time the settings are saved.
38
-
39
  $new_permissions = 0444;
40
  } else if ( $this->settings['write_permissions'] !== $previous_settings['write_permissions'] ) {
41
  // Only revert the settings to the defaults when disabling the setting.
42
  // This avoids changing the file permissions when the setting has yet to be enabled and disabled.
43
-
44
  $new_permissions = 0664;
45
  }
46
-
47
  if ( isset( $new_permissions ) ) {
48
  // Only change the permissions when needed.
49
-
50
  require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-config-file.php' );
51
  require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-file.php' );
52
-
53
  $server_config_file = ITSEC_Lib_Config_File::get_server_config_file_path();
54
  $wp_config_file = ITSEC_Lib_Config_File::get_wp_config_file_path();
55
-
56
  ITSEC_Lib_File::chmod( $server_config_file, $new_permissions );
57
  ITSEC_Lib_File::chmod( $wp_config_file, $new_permissions );
 
 
58
  }
59
  }
 
60
  }
61
 
62
  ITSEC_Modules::register_validator( new ITSEC_System_Tweaks_Validator() );
4
  public function get_id() {
5
  return 'system-tweaks';
6
  }
7
+
8
  protected function sanitize_settings() {
9
  $this->sanitize_setting( 'bool', 'protect_files', __( 'System Files', 'better-wp-security' ) );
10
  $this->sanitize_setting( 'bool', 'directory_browsing', __( 'Directory Browsing', 'better-wp-security' ) );
15
  $this->sanitize_setting( 'bool', 'write_permissions', __( 'File Writing Permissions', 'better-wp-security' ) );
16
  $this->sanitize_setting( 'bool', 'uploads_php', __( 'Uploads', 'better-wp-security' ) );
17
  }
18
+
19
  protected function validate_settings() {
20
  if ( ! $this->can_save() ) {
21
  return;
22
  }
23
+
24
+
25
  $previous_settings = ITSEC_Modules::get_settings( $this->get_id() );
26
+
27
+
28
  $diff = array_diff_assoc( $this->settings, $previous_settings );
29
+
30
  if ( ! empty( $diff ) ) {
31
  ITSEC_Response::regenerate_server_config();
32
  }
33
+
34
+
35
  if ( $this->settings['write_permissions'] ) {
36
  // Always set permissions to 0444 when saving the settings.
37
  // This ensures that the file permissions are fixed each time the settings are saved.
38
+
39
  $new_permissions = 0444;
40
  } else if ( $this->settings['write_permissions'] !== $previous_settings['write_permissions'] ) {
41
  // Only revert the settings to the defaults when disabling the setting.
42
  // This avoids changing the file permissions when the setting has yet to be enabled and disabled.
43
+
44
  $new_permissions = 0664;
45
  }
46
+
47
  if ( isset( $new_permissions ) ) {
48
  // Only change the permissions when needed.
49
+
50
  require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-config-file.php' );
51
  require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-file.php' );
52
+
53
  $server_config_file = ITSEC_Lib_Config_File::get_server_config_file_path();
54
  $wp_config_file = ITSEC_Lib_Config_File::get_wp_config_file_path();
55
+
56
  ITSEC_Lib_File::chmod( $server_config_file, $new_permissions );
57
  ITSEC_Lib_File::chmod( $wp_config_file, $new_permissions );
58
+
59
+ ITSEC_Response::reload_module( 'file-permissions' );
60
  }
61
  }
62
+
63
  }
64
 
65
  ITSEC_Modules::register_validator( new ITSEC_System_Tweaks_Validator() );
core/modules/wordpress-tweaks/init.php CHANGED
@@ -1,3 +1,3 @@
1
  <?php
2
 
3
- ITSEC_Modules::register_module( 'wordpress-tweaks', dirname( __FILE__ ) );
1
  <?php
2
 
3
+ ITSEC_Modules::register_module( 'wordpress-tweaks', dirname( __FILE__ ), 'default-active' );
core/modules/wordpress-tweaks/settings.php CHANGED
@@ -4,15 +4,15 @@ final class ITSEC_Wordpress_Tweaks_Settings extends ITSEC_Settings {
4
  public function get_id() {
5
  return 'wordpress-tweaks';
6
  }
7
-
8
  public function get_defaults() {
9
  return array(
10
  'wlwmanifest_header' => false,
11
  'edituri_header' => false,
12
  'comment_spam' => false,
13
- 'file_editor' => false,
14
  'disable_xmlrpc' => 0,
15
- 'allow_xmlrpc_multiauth' => true,
16
  'safe_jquery' => false,
17
  'login_errors' => false,
18
  'force_unique_nicename' => false,
4
  public function get_id() {
5
  return 'wordpress-tweaks';
6
  }
7
+
8
  public function get_defaults() {
9
  return array(
10
  'wlwmanifest_header' => false,
11
  'edituri_header' => false,
12
  'comment_spam' => false,
13
+ 'file_editor' => true,
14
  'disable_xmlrpc' => 0,
15
+ 'allow_xmlrpc_multiauth' => false,
16
  'safe_jquery' => false,
17
  'login_errors' => false,
18
  'force_unique_nicename' => false,
history.txt CHANGED
@@ -523,3 +523,10 @@
523
  Bug Fix: Fixed bug that could cause some sites to lose settings when upgrading.
524
  5.4.5 - 2016-05-27 - Chris Jean & Aaron D. Campbell
525
  Bug Fix: Fixed SQL query for Database Backups when "Backup Full Database" is enabled.
 
 
 
 
 
 
 
523
  Bug Fix: Fixed bug that could cause some sites to lose settings when upgrading.
524
  5.4.5 - 2016-05-27 - Chris Jean & Aaron D. Campbell
525
  Bug Fix: Fixed SQL query for Database Backups when "Backup Full Database" is enabled.
526
+ 5.5.0 - 2016-06-07 - Chris Jean & Aaron D. Campbell
527
+ New Feature: Added a new File Permissions section on the settings page to bring back the directory and file permissions listing feature found on the Security > Dashboard page of older plugin versions.
528
+ Bug Fix: Fixed a situation where adding a very large list of IP's in the Ban Hosts list would generate an invalid .htaccess file on some servers.
529
+ Enhancement: The Database Backups, Local Brute Force Protection, Network Brute Force Protection, Strong Password Enforcement, and WordPress Tweaks features are now active by default on new installations.
530
+ Enhancement: The WordPress Tweaks feature now uses the "Disable File Editor" setting by default on new installations.
531
+ Enhancement: The WordPress Tweaks feature now sets the "Multiple Authentication Attempts per XML-RPC Request" setting to "Block" by default on new installations.
532
+ Enhancement: Improved the styling of notices.
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: ithemes, chrisjean, aaroncampbell, gerroald, mattdanner
3
  Tags: security, security plugin, malware, hack, secure, block, SSL, admin, htaccess, lockdown, login, protect, protection, anti virus, attack, injection, login security, maintenance, permissions, prevention, authentication, administration, password, brute force, ban, permissions, bots, user agents, xml rpc, security log
4
  Requires at least: 4.1
5
  Tested up to: 4.5.2
6
- Stable tag: 5.4.5
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -188,6 +188,14 @@ Free support may be available with the help of the community in the <a href="htt
188
 
189
  == Changelog ==
190
 
 
 
 
 
 
 
 
 
191
  = 5.4.5 =
192
  * Bug Fix: Fixed SQL query for Database Backups when "Backup Full Database" is enabled.
193
 
@@ -1546,6 +1554,9 @@ This release is a complete rewrite from the ground up. Special thanks to Cory Mi
1546
 
1547
  == Upgrade Notice ==
1548
 
 
 
 
1549
  = 5.4.5 =
1550
  Version 5.4.5 contains a bug fix that fixes the listing of tables to exclude from database backups when "Backup Full Database" is enabled.
1551
 
3
  Tags: security, security plugin, malware, hack, secure, block, SSL, admin, htaccess, lockdown, login, protect, protection, anti virus, attack, injection, login security, maintenance, permissions, prevention, authentication, administration, password, brute force, ban, permissions, bots, user agents, xml rpc, security log
4
  Requires at least: 4.1
5
  Tested up to: 4.5.2
6
+ Stable tag: 5.5.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
188
 
189
  == Changelog ==
190
 
191
+ = 5.5.0 =
192
+ * New Feature: Added a new File Permissions section on the settings page to bring back the directory and file permissions listing feature found on the Security > Dashboard page of older plugin versions.
193
+ * Bug Fix: Fixed a situation where adding a very large list of IP's in the Ban Hosts list would generate an invalid .htaccess file on some servers.
194
+ * Enhancement: The Database Backups, Local Brute Force Protection, Network Brute Force Protection, Strong Password Enforcement, and WordPress Tweaks features are now active by default on new installations.
195
+ * Enhancement: The WordPress Tweaks feature now uses the "Disable File Editor" setting by default on new installations.
196
+ * Enhancement: The WordPress Tweaks feature now sets the "Multiple Authentication Attempts per XML-RPC Request" setting to "Block" by default on new installations.
197
+ * Enhancement: Improved the styling of notices.
198
+
199
  = 5.4.5 =
200
  * Bug Fix: Fixed SQL query for Database Backups when "Backup Full Database" is enabled.
201
 
1554
 
1555
  == Upgrade Notice ==
1556
 
1557
+ = 5.5.0 =
1558
+ Version 5.5.0 contains important bug fixes, a new File Permissions feature, and numerous enhancements. It is recommended for all users.
1559
+
1560
  = 5.4.5 =
1561
  Version 5.4.5 contains a bug fix that fixes the listing of tables to exclude from database backups when "Backup Full Database" is enabled.
1562