iThemes Security (formerly Better WP Security) - Version 5.6.0

Version Description

  • New Feature: Added a new Security Check section on the settings page. This new feature adds a tool to quickly ensure that the recommended features are enabled and the recommended settings are used.
    • Bug Fix: Fixed the ability to remove the itsec_away.confg file in order to disable Away Mode.
    • Enhancement: The "Ban Lists" setting of Banned Users is now enabled by default.
Download this release

Release Info

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

Code changes from version 5.5.0 to 5.6.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.5.0
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.6.0
10
  * Text Domain: better-wp-security
11
  * Network: True
12
  * License: GPLv2
core/admin-pages/css/style.css CHANGED
@@ -381,13 +381,13 @@ body.itsec-modal-open {
381
  * List View
382
  */
383
  .list .itsec-module-card {
384
- cursor: pointer;
385
  max-width: 100%;
386
  padding: 0;
387
  float: none;
388
  margin-bottom: 1px;
389
  }
390
  .list .itsec-module-card-content {
 
391
  padding: .5em .5em .5em .75em;
392
  }
393
  .list .itsec-module-card-content:after {
@@ -562,3 +562,60 @@ body.itsec-modal-open {
562
  background: #ffd4d4;
563
  color: #9c3e3e;
564
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  * List View
382
  */
383
  .list .itsec-module-card {
 
384
  max-width: 100%;
385
  padding: 0;
386
  float: none;
387
  margin-bottom: 1px;
388
  }
389
  .list .itsec-module-card-content {
390
+ cursor: pointer;
391
  padding: .5em .5em .5em .75em;
392
  }
393
  .list .itsec-module-card-content:after {
562
  background: #ffd4d4;
563
  color: #9c3e3e;
564
  }
565
+
566
+ /*
567
+ * Security Check
568
+ */
569
+
570
+ .itsec-security-check-list {
571
+ font-size: 13px;
572
+ margin: 0 0 2em 1em;
573
+ }
574
+
575
+ .itsec-security-check-list p {
576
+ margin: 0;
577
+ }
578
+
579
+ .itsec-security-check-container {
580
+ padding: 0 10px 0 50px;
581
+ border: 1px solid #ddd;
582
+ border-left-width: 4px;
583
+ margin: 0 0 8px;
584
+ position: relative;
585
+ }
586
+
587
+ .itsec-security-check-container:before {
588
+ font-family: 'Dashicons';
589
+ font-size: 1.75em;
590
+ position: absolute;
591
+ left: 7px;
592
+ top: 50%;
593
+ margin: -9px 0 0 0;
594
+ }
595
+
596
+ .itsec-security-check-container-complete:before {
597
+ content: "\f147";
598
+ color: #46b450;
599
+ }
600
+
601
+ .itsec-security-check-container-incomplete:before {
602
+ content: "\f534";
603
+ color: #f2dd28;
604
+ }
605
+
606
+ .itsec-security-check-container-error:before {
607
+ content: "\f534";
608
+ color: #dc3232;
609
+ }
610
+
611
+ .itsec-security-check-container-complete {
612
+ border-left-color: #46b450;
613
+ }
614
+
615
+ .itsec-security-check-container-incomplete {
616
+ border-left-color: #f2dd28;
617
+ }
618
+
619
+ .itsec-security-check-container-error {
620
+ border-left-color: #dc3232;
621
+ }
core/admin-pages/init.php CHANGED
@@ -28,6 +28,7 @@ final class ITSEC_Admin_Page_Loader {
28
 
29
  add_menu_page( __( 'Settings', 'better-wp-security' ), __( 'Security', 'better-wp-security' ), $capability, 'itsec', array( $this, 'show_page' ) );
30
  $page_refs[] = add_submenu_page( 'itsec', __( 'iThemes Security Settings', 'better-wp-security' ), __( 'Settings', 'better-wp-security' ), $capability, 'itsec', array( $this, 'show_page' ) );
 
31
  $page_refs[] = add_submenu_page( 'itsec', __( 'iThemes Security Logs', 'better-wp-security' ), __( 'Logs', 'better-wp-security' ), $capability, 'itsec-logs', array( $this, 'show_page' ) );
32
 
33
  if ( ! ITSEC_Core::is_pro() ) {
28
 
29
  add_menu_page( __( 'Settings', 'better-wp-security' ), __( 'Security', 'better-wp-security' ), $capability, 'itsec', array( $this, 'show_page' ) );
30
  $page_refs[] = add_submenu_page( 'itsec', __( 'iThemes Security Settings', 'better-wp-security' ), __( 'Settings', 'better-wp-security' ), $capability, 'itsec', array( $this, 'show_page' ) );
31
+ $page_refs[] = add_submenu_page( 'itsec', '', __( 'Security Check', 'better-wp-security' ), $capability, 'itsec-security-check', array( $this, 'show_page' ) );
32
  $page_refs[] = add_submenu_page( 'itsec', __( 'iThemes Security Logs', 'better-wp-security' ), __( 'Logs', 'better-wp-security' ), $capability, 'itsec-logs', array( $this, 'show_page' ) );
33
 
34
  if ( ! ITSEC_Core::is_pro() ) {
core/admin-pages/js/script.js CHANGED
@@ -415,6 +415,26 @@ var itsecSettingsPage = {
415
  itsecSettingsPage.sendAJAXRequest( module, method, {}, itsecSettingsPage.toggleModuleActivationCallback );
416
  },
417
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
  toggleModuleActivationCallback: function( results ) {
419
  var module = results.module;
420
  var method = results.method;
@@ -660,6 +680,12 @@ var itsecSettingsPage = {
660
  jQuery(document).ready(function() {
661
  itsecSettingsPage.init();
662
 
 
 
 
 
 
 
663
 
664
  jQuery( '.dialog' ).click( function ( event ) {
665
 
415
  itsecSettingsPage.sendAJAXRequest( module, method, {}, itsecSettingsPage.toggleModuleActivationCallback );
416
  },
417
 
418
+ setModuleToActive: function( module ) {
419
+ var args = {
420
+ 'module': module,
421
+ 'method': 'activate',
422
+ 'errors': []
423
+ };
424
+
425
+ itsecSettingsPage.toggleModuleActivationCallback( args );
426
+ },
427
+
428
+ setModuleToInactive: function( module ) {
429
+ var args = {
430
+ 'module': module,
431
+ 'method': 'deactivate',
432
+ 'errors': []
433
+ };
434
+
435
+ itsecSettingsPage.toggleModuleActivationCallback( args );
436
+ },
437
+
438
  toggleModuleActivationCallback: function( results ) {
439
  var module = results.module;
440
  var method = results.method;
680
  jQuery(document).ready(function() {
681
  itsecSettingsPage.init();
682
 
683
+ if ( itsec_page.show_security_check ) {
684
+ jQuery( '.itsec-settings-view-toggle a.itsec-grid' ).trigger( 'click' );
685
+ jQuery( '#itsec-module-card-security-check .itsec-toggle-settings' ).trigger( 'click' );
686
+ }
687
+
688
+
689
 
690
  jQuery( '.dialog' ).click( function ( event ) {
691
 
core/admin-pages/page-logs.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
 
4
  final class ITSEC_Logs_Page {
5
- private $version = 1.2;
6
 
7
  private $self_url = '';
8
  private $modules = array();
@@ -10,82 +10,82 @@ final class ITSEC_Logs_Page {
10
  private $translations = array();
11
  private $logger_modules = array();
12
  private $logger_displays = array();
13
-
14
-
15
  public function __construct() {
16
  add_action( 'itsec-logs-page-register-widget', array( $this, 'register_widget' ) );
17
-
18
  add_action( 'itsec-page-show', array( $this, 'handle_page_load' ) );
19
  add_action( 'itsec-page-ajax', array( $this, 'handle_ajax_request' ) );
20
  add_action( 'admin_print_scripts', array( $this, 'add_scripts' ) );
21
  add_action( 'admin_print_styles', array( $this, 'add_styles' ) );
22
-
23
  $this->set_translation_strings();
24
-
25
-
26
  $this->logger_modules = apply_filters( 'itsec_logger_modules', array() );
27
  $this->logger_displays = apply_filters( 'itsec_logger_displays', array() );
28
-
29
-
30
  require( dirname( __FILE__ ) . '/module-settings.php' );
31
  require( dirname( __FILE__ ) . '/sidebar-widget.php' );
32
-
33
  require_once( ITSEC_Core::get_core_dir() . '/lib/form.php' );
34
-
35
-
36
  do_action( 'itsec-logs-page-init' );
37
  do_action( 'itsec-logs-page-register-widgets' );
38
-
39
-
40
  if ( ! empty( $_POST ) && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) {
41
  $this->handle_post();
42
  }
43
  }
44
-
45
  public function add_scripts() {
46
  foreach ( $this->modules as $id => $module ) {
47
  $module->enqueue_scripts_and_styles();
48
  }
49
-
50
  foreach ( $this->widgets as $id => $widget ) {
51
  $widget->enqueue_scripts_and_styles();
52
  }
53
-
54
  $vars = array(
55
  'ajax_action' => 'itsec_settings_page',
56
  'ajax_nonce' => wp_create_nonce( 'itsec-settings-nonce' ),
57
  'logs_page_url' => ITSEC_Core::get_logs_page_url(),
58
  'translations' => $this->translations,
59
  );
60
-
61
  wp_enqueue_script( 'itsec-settings-page-script', plugins_url( 'js/script.js', __FILE__ ), array( 'jquery-ui-dialog' ), $this->version, true );
62
  wp_localize_script( 'itsec-settings-page-script', 'itsec_page', $vars );
63
  }
64
-
65
  public function add_styles() {
66
  wp_enqueue_style( 'itsec-settings-page-style', plugins_url( 'css/style.css', __FILE__ ), array(), $this->version );
67
  wp_enqueue_style( 'wp-jquery-ui-dialog' );
68
  }
69
-
70
  private function set_translation_strings() {
71
  $this->translations = array(
72
  'successful_save' => __( 'Settings saved successfully for %1$s.', 'better-wp-security' ),
73
-
74
  'ajax_invalid' => new WP_Error( 'itsec-settings-page-invalid-ajax-response', __( 'An "invalid format" error prevented the request from completing as expected. The format of data returned could not be recognized. This could be due to a plugin/theme conflict or a server configuration issue.', 'better-wp-security' ) ),
75
-
76
  'ajax_forbidden' => new WP_Error( 'itsec-settings-page-forbidden-ajax-response: %1$s "%2$s"', __( 'A "request forbidden" error prevented the request from completing as expected. The server returned a 403 status code, indicating that the server configuration is prohibiting this request. This could be due to a plugin/theme conflict or a server configuration issue. Please try refreshing the page and trying again. If the request continues to fail, you may have to alter plugin settings or server configuration that could account for this AJAX request being blocked.', 'better-wp-security' ) ),
77
-
78
  'ajax_not_found' => new WP_Error( 'itsec-settings-page-not-found-ajax-response: %1$s "%2$s"', __( 'A "not found" error prevented the request from completing as expected. The server returned a 404 status code, indicating that the server was unable to find the requested admin-ajax.php file. This could be due to a plugin/theme conflict, a server configuration issue, or an incomplete WordPress installation. Please try refreshing the page and trying again. If the request continues to fail, you may have to alter plugin settings, alter server configurations, or reinstall WordPress.', 'better-wp-security' ) ),
79
-
80
  'ajax_server_error' => new WP_Error( 'itsec-settings-page-server-error-ajax-response: %1$s "%2$s"', __( 'A "internal server" error prevented the request from completing as expected. The server returned a 500 status code, indicating that the server was unable to complete the request due to a fatal PHP error or a server problem. This could be due to a plugin/theme conflict, a server configuration issue, a temporary hosting issue, or invalid custom PHP modifications. Please check your server\'s error logs for details about the source of the error and contact your hosting company for assistance if required.', 'better-wp-security' ) ),
81
-
82
  'ajax_unknown' => new WP_Error( 'itsec-settings-page-ajax-error-unknown: %1$s "%2$s"', __( 'An unknown error prevented the request from completing as expected. This could be due to a plugin/theme conflict or a server configuration issue.', 'better-wp-security' ) ),
83
-
84
  'ajax_timeout' => new WP_Error( 'itsec-settings-page-ajax-error-timeout: %1$s "%2$s"', __( 'A timeout error prevented the request from completing as expected. The site took too long to respond. This could be due to a plugin/theme conflict or a server configuration issue.', 'better-wp-security' ) ),
85
-
86
  'ajax_parsererror' => new WP_Error( 'itsec-settings-page-ajax-error-parsererror: %1$s "%2$s"', __( 'A parser error prevented the request from completing as expected. The site sent a response that jQuery could not process. This could be due to a plugin/theme conflict or a server configuration issue.', 'better-wp-security' ) ),
87
  );
88
-
89
  foreach ( $this->translations as $key => $message ) {
90
  if ( is_wp_error( $message ) ) {
91
  $messages = ITSEC_Response::get_error_strings( $message );
@@ -93,47 +93,47 @@ final class ITSEC_Logs_Page {
93
  }
94
  }
95
  }
96
-
97
  public function register_widget( $widget ) {
98
  if ( ! is_object( $widget ) || ! is_a( $widget, 'ITSEC_Settings_Page_Sidebar_Widget' ) ) {
99
  trigger_error( 'An invalid widget was registered.', E_USER_ERROR );
100
  return;
101
  }
102
-
103
  if ( isset( $this->modules[$widget->id] ) ) {
104
  trigger_error( "A widget with the id of {$widget->id} is registered. Widget id's must be unique from any other module or widget." );
105
  return;
106
  }
107
-
108
  if ( isset( $this->widgets[$widget->id] ) ) {
109
  trigger_error( "A widget with the id of {$widget->id} is already registered. Widget id's must be unique from any other module or widget." );
110
  return;
111
  }
112
-
113
-
114
  $this->widgets[$widget->id] = $widget;
115
  }
116
-
117
  private function handle_post() {
118
  if ( ! empty( $_POST['itsec_clear_logs'] ) && 'clear_logs' === $_POST['itsec_clear_logs'] ) {
119
  if ( ! wp_verify_nonce( $_POST['wp_nonce'], 'itsec_clear_logs' ) ) {
120
  die( __( 'Security error!', 'better-wp-security' ) );
121
  }
122
-
123
  global $itsec_logger;
124
-
125
  $itsec_logger->purge_logs( true );
126
  } else {
127
  $post_data = ITSEC_Form::get_post_data();
128
  $saved = true;
129
  $js_function_calls = array();
130
-
131
  if ( ! empty( $_POST['widget-id'] ) ) {
132
  $id = $_POST['widget-id'];
133
-
134
  if ( isset( $post_data[$id] ) && isset( $this->widgets[$id] ) ) {
135
  $widget = $this->widgets[$id];
136
-
137
  $widget->handle_form_post( $post_data[$id] );
138
  }
139
  } else {
@@ -147,13 +147,13 @@ final class ITSEC_Logs_Page {
147
  } else {
148
  $modules = $this->modules;
149
  }
150
-
151
  foreach ( $modules as $id => $module ) {
152
  if ( isset( $post_data[$id] ) ) {
153
  $results = $module->handle_form_post( $post_data[$id] );
154
  }
155
  }
156
-
157
  if ( ITSEC_Response::is_success() ) {
158
  if ( ITSEC_Response::get_show_default_success_message() ) {
159
  ITSEC_Response::add_message( __( 'The settings saved successfully.', 'better-wp-security' ) );
@@ -161,7 +161,7 @@ final class ITSEC_Logs_Page {
161
  } else {
162
  if ( ITSEC_Response::get_show_default_error_message() ) {
163
  $error_count = ITSEC_Response::get_error_count();
164
-
165
  if ( $error_count > 0 ) {
166
  ITSEC_Response::add_error( new WP_Error( 'itsec-settings-data-not-saved', _n( 'The settings could not be saved. Please correct the error above and try again.', 'The settings could not be saved. Please correct the errors above and try again.', $error_count, 'better-wp-security' ) ) );
167
  } else {
@@ -170,83 +170,83 @@ final class ITSEC_Logs_Page {
170
  }
171
  }
172
  }
173
-
174
-
175
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
176
  return;
177
  }
178
-
179
  ITSEC_Response::maybe_regenerate_wp_config();
180
  ITSEC_Response::maybe_regenerate_server_config();
181
  ITSEC_Response::maybe_do_force_logout();
182
  ITSEC_Response::maybe_do_redirect();
183
  }
184
  }
185
-
186
  public function handle_page_load( $self_url ) {
187
  $this->self_url = $self_url;
188
-
189
  $this->show_settings_page();
190
  }
191
-
192
  private function get_widget_settings( $id, $form = false, $echo = false ) {
193
  if ( ! isset( $this->widgets[$id] ) ) {
194
  $error = new WP_Error( 'itsec-settings-page-get-widget-settings-invalid-id', sprintf( __( 'The requested widget (%s) does not exist. Logs for it cannot be rendered.', 'better-wp-security' ), $id ) );
195
-
196
  if ( $echo ) {
197
  ITSEC_Lib::show_error_message( $error );
198
  } else {
199
  return $error;
200
  }
201
  }
202
-
203
  if ( false === $form ) {
204
  $form = new ITSEC_Form();
205
  }
206
-
207
  $widget = $this->widgets[$id];
208
-
209
  $form->add_input_group( $id );
210
  $form->set_defaults( $widget->get_defaults() );
211
-
212
  if ( ! $echo ) {
213
  ob_start();
214
  }
215
-
216
  $widget->render( $form );
217
-
218
  $form->remove_all_input_groups();
219
-
220
  if ( ! $echo ) {
221
  return ob_get_clean();
222
  }
223
  }
224
-
225
  private function show_settings_page() {
226
  require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-wp-list-table.php' );
227
-
228
-
229
  if ( isset( $_GET['filter'] ) ) {
230
  $filter = $_GET['filter'];
231
  } else {
232
  $filter = 'all';
233
  }
234
-
235
-
236
  $form = new ITSEC_Form();
237
-
238
-
239
  $filters = array(
240
  'all' => __( 'All Log Data', 'better-wp-security' ),
241
  );
242
-
243
  foreach ( $this->logger_displays as $log_provider ) {
244
  $filters[$log_provider['module']] = $log_provider['title'];
245
  }
246
-
247
-
248
  $form->set_option( 'filter', $filter );
249
-
250
  ?>
251
  <div class="wrap">
252
  <h1>
@@ -254,19 +254,19 @@ final class ITSEC_Logs_Page {
254
  <a href="<?php echo esc_url( ITSEC_Core::get_settings_page_url() ); ?>" class="page-title-action"><?php _e( 'Manage Settings', 'better-wp-security' ); ?></a>
255
  <a href="<?php echo esc_url( apply_filters( 'itsec_support_url', 'https://wordpress.org/support/plugin/better-wp-security' ) ); ?>" class="page-title-action"><?php _e( 'Support', 'better-wp-security' ); ?></a>
256
  </h1>
257
-
258
  <div id="itsec-settings-messages-container">
259
  <?php
260
  foreach ( ITSEC_Response::get_errors() as $error ) {
261
  ITSEC_Lib::show_error_message( $error );
262
  }
263
-
264
  foreach ( ITSEC_Response::get_messages() as $message ) {
265
  ITSEC_Lib::show_status_message( $message );
266
  }
267
  ?>
268
  </div>
269
-
270
  <div id="poststuff">
271
  <div id="post-body" class="metabox-holder columns-2 hide-if-no-js">
272
  <div id="postbox-container-2" class="postbox-container">
@@ -276,19 +276,19 @@ final class ITSEC_Logs_Page {
276
  <div class="itsec-module-cards-container list">
277
  <p><?php _e( 'Below are various logs of information collected by iThemes Security Pro. This information can help you get a picture of what is happening with your site and the level of success you have achieved in your security efforts.', 'better-wp-security' ); ?></p>
278
  <p><?php _e( 'Logging settings can be managed in the Global Settings.', 'better-wp-security' ); ?></p>
279
-
280
-
281
  <?php $form->start_form( 'itsec-module-settings-form' ); ?>
282
  <?php $form->add_nonce( 'itsec-settings-page' ); ?>
283
  <p><?php $form->add_select( 'filter', $filters ); ?></p>
284
  <?php $form->end_form(); ?>
285
-
286
  <?php $this->show_filtered_logs( $filter ); ?>
287
  </div>
288
  <?php endif; ?>
289
  </div>
290
  <div class="itsec-modal-background"></div>
291
-
292
  <div id="postbox-container-1" class="postbox-container">
293
  <?php foreach ( $this->widgets as $id => $widget ) : ?>
294
  <?php $form->start_form( "itsec-sidebar-widget-form-$id" ); ?>
@@ -304,16 +304,16 @@ final class ITSEC_Logs_Page {
304
  <?php endforeach; ?>
305
  </div>
306
  </div>
307
-
308
  <div class="hide-if-js">
309
  <p class="itsec-warning-message"><?php _e( 'iThemes Security requires Javascript in order for the settings to be modified. Please enable Javascript to configure the settings.', 'better-wp-security' ); ?></p>
310
  </div>
311
  </div>
312
  </div>
313
  <?php
314
-
315
  }
316
-
317
  private function show_filtered_logs( $filter ) {
318
  foreach ( $this->logger_displays as $display ) {
319
  if ( $display['module'] === $filter ) {
@@ -321,11 +321,11 @@ final class ITSEC_Logs_Page {
321
  break;
322
  }
323
  }
324
-
325
  if ( ! isset( $callback ) ) {
326
  $callback = array( $this, 'all_logs_content' );
327
  }
328
-
329
  call_user_func_array( $callback, array() );
330
  }
331
 
2
 
3
 
4
  final class ITSEC_Logs_Page {
5
+ private $version = 1.3;
6
 
7
  private $self_url = '';
8
  private $modules = array();
10
  private $translations = array();
11
  private $logger_modules = array();
12
  private $logger_displays = array();
13
+
14
+
15
  public function __construct() {
16
  add_action( 'itsec-logs-page-register-widget', array( $this, 'register_widget' ) );
17
+
18
  add_action( 'itsec-page-show', array( $this, 'handle_page_load' ) );
19
  add_action( 'itsec-page-ajax', array( $this, 'handle_ajax_request' ) );
20
  add_action( 'admin_print_scripts', array( $this, 'add_scripts' ) );
21
  add_action( 'admin_print_styles', array( $this, 'add_styles' ) );
22
+
23
  $this->set_translation_strings();
24
+
25
+
26
  $this->logger_modules = apply_filters( 'itsec_logger_modules', array() );
27
  $this->logger_displays = apply_filters( 'itsec_logger_displays', array() );
28
+
29
+
30
  require( dirname( __FILE__ ) . '/module-settings.php' );
31
  require( dirname( __FILE__ ) . '/sidebar-widget.php' );
32
+
33
  require_once( ITSEC_Core::get_core_dir() . '/lib/form.php' );
34
+
35
+
36
  do_action( 'itsec-logs-page-init' );
37
  do_action( 'itsec-logs-page-register-widgets' );
38
+
39
+
40
  if ( ! empty( $_POST ) && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) ) {
41
  $this->handle_post();
42
  }
43
  }
44
+
45
  public function add_scripts() {
46
  foreach ( $this->modules as $id => $module ) {
47
  $module->enqueue_scripts_and_styles();
48
  }
49
+
50
  foreach ( $this->widgets as $id => $widget ) {
51
  $widget->enqueue_scripts_and_styles();
52
  }
53
+
54
  $vars = array(
55
  'ajax_action' => 'itsec_settings_page',
56
  'ajax_nonce' => wp_create_nonce( 'itsec-settings-nonce' ),
57
  'logs_page_url' => ITSEC_Core::get_logs_page_url(),
58
  'translations' => $this->translations,
59
  );
60
+
61
  wp_enqueue_script( 'itsec-settings-page-script', plugins_url( 'js/script.js', __FILE__ ), array( 'jquery-ui-dialog' ), $this->version, true );
62
  wp_localize_script( 'itsec-settings-page-script', 'itsec_page', $vars );
63
  }
64
+
65
  public function add_styles() {
66
  wp_enqueue_style( 'itsec-settings-page-style', plugins_url( 'css/style.css', __FILE__ ), array(), $this->version );
67
  wp_enqueue_style( 'wp-jquery-ui-dialog' );
68
  }
69
+
70
  private function set_translation_strings() {
71
  $this->translations = array(
72
  'successful_save' => __( 'Settings saved successfully for %1$s.', 'better-wp-security' ),
73
+
74
  'ajax_invalid' => new WP_Error( 'itsec-settings-page-invalid-ajax-response', __( 'An "invalid format" error prevented the request from completing as expected. The format of data returned could not be recognized. This could be due to a plugin/theme conflict or a server configuration issue.', 'better-wp-security' ) ),
75
+
76
  'ajax_forbidden' => new WP_Error( 'itsec-settings-page-forbidden-ajax-response: %1$s "%2$s"', __( 'A "request forbidden" error prevented the request from completing as expected. The server returned a 403 status code, indicating that the server configuration is prohibiting this request. This could be due to a plugin/theme conflict or a server configuration issue. Please try refreshing the page and trying again. If the request continues to fail, you may have to alter plugin settings or server configuration that could account for this AJAX request being blocked.', 'better-wp-security' ) ),
77
+
78
  'ajax_not_found' => new WP_Error( 'itsec-settings-page-not-found-ajax-response: %1$s "%2$s"', __( 'A "not found" error prevented the request from completing as expected. The server returned a 404 status code, indicating that the server was unable to find the requested admin-ajax.php file. This could be due to a plugin/theme conflict, a server configuration issue, or an incomplete WordPress installation. Please try refreshing the page and trying again. If the request continues to fail, you may have to alter plugin settings, alter server configurations, or reinstall WordPress.', 'better-wp-security' ) ),
79
+
80
  'ajax_server_error' => new WP_Error( 'itsec-settings-page-server-error-ajax-response: %1$s "%2$s"', __( 'A "internal server" error prevented the request from completing as expected. The server returned a 500 status code, indicating that the server was unable to complete the request due to a fatal PHP error or a server problem. This could be due to a plugin/theme conflict, a server configuration issue, a temporary hosting issue, or invalid custom PHP modifications. Please check your server\'s error logs for details about the source of the error and contact your hosting company for assistance if required.', 'better-wp-security' ) ),
81
+
82
  'ajax_unknown' => new WP_Error( 'itsec-settings-page-ajax-error-unknown: %1$s "%2$s"', __( 'An unknown error prevented the request from completing as expected. This could be due to a plugin/theme conflict or a server configuration issue.', 'better-wp-security' ) ),
83
+
84
  'ajax_timeout' => new WP_Error( 'itsec-settings-page-ajax-error-timeout: %1$s "%2$s"', __( 'A timeout error prevented the request from completing as expected. The site took too long to respond. This could be due to a plugin/theme conflict or a server configuration issue.', 'better-wp-security' ) ),
85
+
86
  'ajax_parsererror' => new WP_Error( 'itsec-settings-page-ajax-error-parsererror: %1$s "%2$s"', __( 'A parser error prevented the request from completing as expected. The site sent a response that jQuery could not process. This could be due to a plugin/theme conflict or a server configuration issue.', 'better-wp-security' ) ),
87
  );
88
+
89
  foreach ( $this->translations as $key => $message ) {
90
  if ( is_wp_error( $message ) ) {
91
  $messages = ITSEC_Response::get_error_strings( $message );
93
  }
94
  }
95
  }
96
+
97
  public function register_widget( $widget ) {
98
  if ( ! is_object( $widget ) || ! is_a( $widget, 'ITSEC_Settings_Page_Sidebar_Widget' ) ) {
99
  trigger_error( 'An invalid widget was registered.', E_USER_ERROR );
100
  return;
101
  }
102
+
103
  if ( isset( $this->modules[$widget->id] ) ) {
104
  trigger_error( "A widget with the id of {$widget->id} is registered. Widget id's must be unique from any other module or widget." );
105
  return;
106
  }
107
+
108
  if ( isset( $this->widgets[$widget->id] ) ) {
109
  trigger_error( "A widget with the id of {$widget->id} is already registered. Widget id's must be unique from any other module or widget." );
110
  return;
111
  }
112
+
113
+
114
  $this->widgets[$widget->id] = $widget;
115
  }
116
+
117
  private function handle_post() {
118
  if ( ! empty( $_POST['itsec_clear_logs'] ) && 'clear_logs' === $_POST['itsec_clear_logs'] ) {
119
  if ( ! wp_verify_nonce( $_POST['wp_nonce'], 'itsec_clear_logs' ) ) {
120
  die( __( 'Security error!', 'better-wp-security' ) );
121
  }
122
+
123
  global $itsec_logger;
124
+
125
  $itsec_logger->purge_logs( true );
126
  } else {
127
  $post_data = ITSEC_Form::get_post_data();
128
  $saved = true;
129
  $js_function_calls = array();
130
+
131
  if ( ! empty( $_POST['widget-id'] ) ) {
132
  $id = $_POST['widget-id'];
133
+
134
  if ( isset( $post_data[$id] ) && isset( $this->widgets[$id] ) ) {
135
  $widget = $this->widgets[$id];
136
+
137
  $widget->handle_form_post( $post_data[$id] );
138
  }
139
  } else {
147
  } else {
148
  $modules = $this->modules;
149
  }
150
+
151
  foreach ( $modules as $id => $module ) {
152
  if ( isset( $post_data[$id] ) ) {
153
  $results = $module->handle_form_post( $post_data[$id] );
154
  }
155
  }
156
+
157
  if ( ITSEC_Response::is_success() ) {
158
  if ( ITSEC_Response::get_show_default_success_message() ) {
159
  ITSEC_Response::add_message( __( 'The settings saved successfully.', 'better-wp-security' ) );
161
  } else {
162
  if ( ITSEC_Response::get_show_default_error_message() ) {
163
  $error_count = ITSEC_Response::get_error_count();
164
+
165
  if ( $error_count > 0 ) {
166
  ITSEC_Response::add_error( new WP_Error( 'itsec-settings-data-not-saved', _n( 'The settings could not be saved. Please correct the error above and try again.', 'The settings could not be saved. Please correct the errors above and try again.', $error_count, 'better-wp-security' ) ) );
167
  } else {
170
  }
171
  }
172
  }
173
+
174
+
175
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
176
  return;
177
  }
178
+
179
  ITSEC_Response::maybe_regenerate_wp_config();
180
  ITSEC_Response::maybe_regenerate_server_config();
181
  ITSEC_Response::maybe_do_force_logout();
182
  ITSEC_Response::maybe_do_redirect();
183
  }
184
  }
185
+
186
  public function handle_page_load( $self_url ) {
187
  $this->self_url = $self_url;
188
+
189
  $this->show_settings_page();
190
  }
191
+
192
  private function get_widget_settings( $id, $form = false, $echo = false ) {
193
  if ( ! isset( $this->widgets[$id] ) ) {
194
  $error = new WP_Error( 'itsec-settings-page-get-widget-settings-invalid-id', sprintf( __( 'The requested widget (%s) does not exist. Logs for it cannot be rendered.', 'better-wp-security' ), $id ) );
195
+
196
  if ( $echo ) {
197
  ITSEC_Lib::show_error_message( $error );
198
  } else {
199
  return $error;
200
  }
201
  }
202
+
203
  if ( false === $form ) {
204
  $form = new ITSEC_Form();
205
  }
206
+
207
  $widget = $this->widgets[$id];
208
+
209
  $form->add_input_group( $id );
210
  $form->set_defaults( $widget->get_defaults() );
211
+
212
  if ( ! $echo ) {
213
  ob_start();
214
  }
215
+
216
  $widget->render( $form );
217
+
218
  $form->remove_all_input_groups();
219
+
220
  if ( ! $echo ) {
221
  return ob_get_clean();
222
  }
223
  }
224
+
225
  private function show_settings_page() {
226
  require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-wp-list-table.php' );
227
+
228
+
229
  if ( isset( $_GET['filter'] ) ) {
230
  $filter = $_GET['filter'];
231
  } else {
232
  $filter = 'all';
233
  }
234
+
235
+
236
  $form = new ITSEC_Form();
237
+
238
+
239
  $filters = array(
240
  'all' => __( 'All Log Data', 'better-wp-security' ),
241
  );
242
+
243
  foreach ( $this->logger_displays as $log_provider ) {
244
  $filters[$log_provider['module']] = $log_provider['title'];
245
  }
246
+
247
+
248
  $form->set_option( 'filter', $filter );
249
+
250
  ?>
251
  <div class="wrap">
252
  <h1>
254
  <a href="<?php echo esc_url( ITSEC_Core::get_settings_page_url() ); ?>" class="page-title-action"><?php _e( 'Manage Settings', 'better-wp-security' ); ?></a>
255
  <a href="<?php echo esc_url( apply_filters( 'itsec_support_url', 'https://wordpress.org/support/plugin/better-wp-security' ) ); ?>" class="page-title-action"><?php _e( 'Support', 'better-wp-security' ); ?></a>
256
  </h1>
257
+
258
  <div id="itsec-settings-messages-container">
259
  <?php
260
  foreach ( ITSEC_Response::get_errors() as $error ) {
261
  ITSEC_Lib::show_error_message( $error );
262
  }
263
+
264
  foreach ( ITSEC_Response::get_messages() as $message ) {
265
  ITSEC_Lib::show_status_message( $message );
266
  }
267
  ?>
268
  </div>
269
+
270
  <div id="poststuff">
271
  <div id="post-body" class="metabox-holder columns-2 hide-if-no-js">
272
  <div id="postbox-container-2" class="postbox-container">
276
  <div class="itsec-module-cards-container list">
277
  <p><?php _e( 'Below are various logs of information collected by iThemes Security Pro. This information can help you get a picture of what is happening with your site and the level of success you have achieved in your security efforts.', 'better-wp-security' ); ?></p>
278
  <p><?php _e( 'Logging settings can be managed in the Global Settings.', 'better-wp-security' ); ?></p>
279
+
280
+
281
  <?php $form->start_form( 'itsec-module-settings-form' ); ?>
282
  <?php $form->add_nonce( 'itsec-settings-page' ); ?>
283
  <p><?php $form->add_select( 'filter', $filters ); ?></p>
284
  <?php $form->end_form(); ?>
285
+
286
  <?php $this->show_filtered_logs( $filter ); ?>
287
  </div>
288
  <?php endif; ?>
289
  </div>
290
  <div class="itsec-modal-background"></div>
291
+
292
  <div id="postbox-container-1" class="postbox-container">
293
  <?php foreach ( $this->widgets as $id => $widget ) : ?>
294
  <?php $form->start_form( "itsec-sidebar-widget-form-$id" ); ?>
304
  <?php endforeach; ?>
305
  </div>
306
  </div>
307
+
308
  <div class="hide-if-js">
309
  <p class="itsec-warning-message"><?php _e( 'iThemes Security requires Javascript in order for the settings to be modified. Please enable Javascript to configure the settings.', 'better-wp-security' ); ?></p>
310
  </div>
311
  </div>
312
  </div>
313
  <?php
314
+
315
  }
316
+
317
  private function show_filtered_logs( $filter ) {
318
  foreach ( $this->logger_displays as $display ) {
319
  if ( $display['module'] === $filter ) {
321
  break;
322
  }
323
  }
324
+
325
  if ( ! isset( $callback ) ) {
326
  $callback = array( $this, 'all_logs_content' );
327
  }
328
+
329
  call_user_func_array( $callback, array() );
330
  }
331
 
core/admin-pages/page-security-check.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+
3
+ wp_redirect( ITSEC_Core::get_security_check_page_url() );
4
+ exit;
core/admin-pages/page-settings.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
 
4
  final class ITSEC_Settings_Page {
5
- private $version = 1.2;
6
 
7
  private $self_url = '';
8
  private $modules = array();
@@ -69,11 +69,20 @@ final class ITSEC_Settings_Page {
69
  }
70
 
71
  $vars = array(
72
- 'ajax_action' => 'itsec_settings_page',
73
- 'ajax_nonce' => wp_create_nonce( 'itsec-settings-nonce' ),
74
- 'translations' => $this->translations,
 
75
  );
76
 
 
 
 
 
 
 
 
 
77
  wp_enqueue_script( 'itsec-settings-page-script', plugins_url( 'js/script.js', __FILE__ ), array(), $this->version, true );
78
  wp_localize_script( 'itsec-settings-page-script', 'itsec_page', $vars );
79
  }
2
 
3
 
4
  final class ITSEC_Settings_Page {
5
+ private $version = 1.3;
6
 
7
  private $self_url = '';
8
  private $modules = array();
69
  }
70
 
71
  $vars = array(
72
+ 'ajax_action' => 'itsec_settings_page',
73
+ 'ajax_nonce' => wp_create_nonce( 'itsec-settings-nonce' ),
74
+ 'show_security_check' => ITSEC_Modules::get_setting( 'global', 'show_security_check' ),
75
+ 'translations' => $this->translations,
76
  );
77
 
78
+ if ( $vars['show_security_check'] ) {
79
+ ITSEC_Modules::set_setting( 'global', 'show_security_check', false );
80
+
81
+ if ( ! empty( $_GET['module'] ) && 'security-check' === $_GET['module'] ) {
82
+ $vars['show_security_check'] = false;
83
+ }
84
+ }
85
+
86
  wp_enqueue_script( 'itsec-settings-page-script', plugins_url( 'js/script.js', __FILE__ ), array(), $this->version, true );
87
  wp_localize_script( 'itsec-settings-page-script', 'itsec_page', $vars );
88
  }
core/class-itsec-core.php CHANGED
@@ -213,6 +213,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
213
  public function register_modules() {
214
  $path = dirname( __FILE__ );
215
 
 
216
  include( "$path/modules/global/init.php" );
217
  include( "$path/modules/404-detection/init.php" );
218
  include( "$path/modules/away-mode/init.php" );
@@ -329,6 +330,15 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
329
  )
330
  );
331
 
 
 
 
 
 
 
 
 
 
332
  $wp_admin_bar->add_menu(
333
  array(
334
  'id' => 'itsec_admin_bar_logs',
@@ -517,7 +527,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
517
  $self = self::get_instance();
518
 
519
  if ( ! $self->notices_loaded ) {
520
- wp_enqueue_style( 'itsec-notice', plugins_url( 'core/css/itsec_notice.css', ITSEC_Core::get_core_dir() ), array(), '20160512' );
521
  wp_enqueue_script( 'itsec-notice', plugins_url( 'core/js/itsec-notice.js', ITSEC_Core::get_core_dir() ), array(), '20160512' );
522
 
523
  $self->notices_loaded = true;
@@ -606,6 +616,10 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
606
  return $url;
607
  }
608
 
 
 
 
 
609
  public static function set_interactive( $interactive ) {
610
  $self = self::get_instance();
611
  $self->interactive = (bool) $interactive;
213
  public function register_modules() {
214
  $path = dirname( __FILE__ );
215
 
216
+ include( "$path/modules/security-check/init.php" );
217
  include( "$path/modules/global/init.php" );
218
  include( "$path/modules/404-detection/init.php" );
219
  include( "$path/modules/away-mode/init.php" );
330
  )
331
  );
332
 
333
+ $wp_admin_bar->add_menu(
334
+ array(
335
+ 'id' => 'itsec_admin_bar_security_check',
336
+ 'title' => __( 'Security Check', 'better-wp-security' ),
337
+ 'href' => self::get_security_check_page_url(),
338
+ 'parent' => 'itsec_admin_bar_menu',
339
+ )
340
+ );
341
+
342
  $wp_admin_bar->add_menu(
343
  array(
344
  'id' => 'itsec_admin_bar_logs',
527
  $self = self::get_instance();
528
 
529
  if ( ! $self->notices_loaded ) {
530
+ wp_enqueue_style( 'itsec-notice', plugins_url( 'core/css/itsec_notice.css', ITSEC_Core::get_core_dir() ), array(), '20160609' );
531
  wp_enqueue_script( 'itsec-notice', plugins_url( 'core/js/itsec-notice.js', ITSEC_Core::get_core_dir() ), array(), '20160512' );
532
 
533
  $self->notices_loaded = true;
616
  return $url;
617
  }
618
 
619
+ public static function get_security_check_page_url() {
620
+ return admin_url( 'admin.php?page=itsec&module=security-check' );
621
+ }
622
+
623
  public static function set_interactive( $interactive ) {
624
  $self = self::get_instance();
625
  $self->interactive = (bool) $interactive;
core/class-itsec-response.php CHANGED
@@ -98,9 +98,13 @@ final class ITSEC_Response {
98
  $self = self::get_instance();
99
 
100
  if ( is_null( $args ) ) {
101
- $self->js_function_calls[] = array( $js_function );
102
  } else {
103
- $self->js_function_calls[] = array( $js_function, $args );
 
 
 
 
104
  }
105
  }
106
 
98
  $self = self::get_instance();
99
 
100
  if ( is_null( $args ) ) {
101
+ $call = array( $js_function );
102
  } else {
103
+ $call = array( $js_function, $args );
104
+ }
105
+
106
+ if ( ! in_array( $call, $self->js_function_calls ) ) {
107
+ $self->js_function_calls[] = $call;
108
  }
109
  }
110
 
core/css/itsec_notice.css CHANGED
@@ -44,6 +44,7 @@
44
  color: #0071bc;
45
  font-weight: bold;
46
  text-decoration: none;
 
47
  }
48
 
49
  .itsec_notice_text {
@@ -51,11 +52,6 @@
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;
@@ -80,6 +76,12 @@
80
  cursor: pointer;
81
  }
82
 
 
 
 
 
 
 
83
  .itsec-notice a.itsec-notice-button {
84
  line-height: 15px;
85
  font-size: 14px;
44
  color: #0071bc;
45
  font-weight: bold;
46
  text-decoration: none;
47
+ position: inherit;
48
  }
49
 
50
  .itsec_notice_text {
52
  margin: 10px 0 10px 0;
53
  }
54
 
 
 
 
 
 
55
  .itsec-notice .itsec-notice-hide {
56
  border: 1px solid transparent;
57
  border-radius: 3px;
76
  cursor: pointer;
77
  }
78
 
79
+ /* Specified after '.itsec-notice .itsec-notice-hide:hover' for preference on buttons with both .itsec-notice-hide and .itsec-notice-button */
80
+ .itsec-notice .itsec-notice-button:hover {
81
+ background: #eff7fd;
82
+ cursor: pointer;
83
+ }
84
+
85
  .itsec-notice a.itsec-notice-button {
86
  line-height: 15px;
87
  font-size: 14px;
core/history.txt CHANGED
@@ -404,3 +404,7 @@
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.
 
 
 
 
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.
407
+ 2.5.0 - 2016-06-15 - Chris Jean & Aaron D. Campbell
408
+ New Feature: Added a new Security Check section on the settings page. This new feature adds a tool to quickly ensure that the recommended features are enabled and the recommended settings are used.
409
+ Bug Fix: Fixed the ability to remove the itsec_away.confg file in order to disable Away Mode.
410
+ Enhancement: The "Ban Lists" setting of Banned Users is now enabled by default.
core/modules/away-mode/class-itsec-away-mode.php CHANGED
@@ -13,7 +13,7 @@ final class ITSEC_Away_Mode {
13
  add_filter( 'itsec_sync_modules', array( $this, 'register_sync' ) );
14
 
15
  }
16
-
17
  /**
18
  * Check if away mode is active
19
  *
@@ -26,42 +26,47 @@ final class ITSEC_Away_Mode {
26
  */
27
  public static function is_active( $get_details = false ) {
28
  require_once( dirname( __FILE__ ) . '/utilities.php' );
29
-
30
  $settings = ITSEC_Modules::get_settings( 'away-mode' );
31
-
32
  if ( 'daily' === $settings['type'] ) {
33
  $details = ITSEC_Away_Mode_Utilities::is_current_time_active( $settings['start_time'], $settings['end_time'], true );
34
  } else {
35
  $details = ITSEC_Away_Mode_Utilities::is_current_timestamp_active( $settings['start'], $settings['end'], true );
36
  }
37
-
38
-
39
  $details['override_type'] = $settings['override_type'];
40
  $details['override_end'] = $settings['override_end'];
41
-
42
  if ( empty( $settings['override_type'] ) || ( ITSEC_Core::get_current_time() > $settings['override_end'] ) ) {
43
  $details['override_active'] = false;
44
  } else {
45
  $details['override_active'] = true;
46
-
47
  if ( 'activate' === $details['override_type'] ) {
48
  $details['active'] = true;
49
  } else {
50
  $details['active'] = false;
51
  }
52
  }
53
-
54
-
 
 
 
 
 
 
55
  if ( ! isset( $details['error'] ) ) {
56
  $details['error'] = false;
57
  }
58
-
59
-
60
-
61
  if ( $get_details ) {
62
  return $details;
63
  }
64
-
65
  return $details['active'];
66
  }
67
 
13
  add_filter( 'itsec_sync_modules', array( $this, 'register_sync' ) );
14
 
15
  }
16
+
17
  /**
18
  * Check if away mode is active
19
  *
26
  */
27
  public static function is_active( $get_details = false ) {
28
  require_once( dirname( __FILE__ ) . '/utilities.php' );
29
+
30
  $settings = ITSEC_Modules::get_settings( 'away-mode' );
31
+
32
  if ( 'daily' === $settings['type'] ) {
33
  $details = ITSEC_Away_Mode_Utilities::is_current_time_active( $settings['start_time'], $settings['end_time'], true );
34
  } else {
35
  $details = ITSEC_Away_Mode_Utilities::is_current_timestamp_active( $settings['start'], $settings['end'], true );
36
  }
37
+
38
+ $details['has_active_file'] = ITSEC_Away_Mode_Utilities::has_active_file();
39
  $details['override_type'] = $settings['override_type'];
40
  $details['override_end'] = $settings['override_end'];
41
+
42
  if ( empty( $settings['override_type'] ) || ( ITSEC_Core::get_current_time() > $settings['override_end'] ) ) {
43
  $details['override_active'] = false;
44
  } else {
45
  $details['override_active'] = true;
46
+
47
  if ( 'activate' === $details['override_type'] ) {
48
  $details['active'] = true;
49
  } else {
50
  $details['active'] = false;
51
  }
52
  }
53
+
54
+ if ( ! $details['has_active_file'] ) {
55
+ $details['active'] = false;
56
+ $details['remaining'] = false;
57
+ $details['next'] = false;
58
+ $details['length'] = false;
59
+ }
60
+
61
  if ( ! isset( $details['error'] ) ) {
62
  $details['error'] = false;
63
  }
64
+
65
+
 
66
  if ( $get_details ) {
67
  return $details;
68
  }
69
+
70
  return $details['active'];
71
  }
72
 
core/modules/ban-users/settings.php CHANGED
@@ -4,11 +4,11 @@ final class ITSEC_Ban_Users_Settings extends ITSEC_Settings {
4
  public function get_id() {
5
  return 'ban-users';
6
  }
7
-
8
  public function get_defaults() {
9
  return array(
10
  'default' => false,
11
- 'enable_ban_lists' => false,
12
  'host_list' => array(),
13
  'agent_list' => array(),
14
  );
4
  public function get_id() {
5
  return 'ban-users';
6
  }
7
+
8
  public function get_defaults() {
9
  return array(
10
  'default' => false,
11
+ 'enable_ban_lists' => true,
12
  'host_list' => array(),
13
  'agent_list' => array(),
14
  );
core/modules/global/active.php CHANGED
@@ -39,7 +39,7 @@ function itsec_network_brute_force_add_notice() {
39
  add_action( 'admin_init', 'itsec_network_brute_force_add_notice' );
40
 
41
  function itsec_network_brute_force_show_notice() {
42
- echo '<div class="updated itsec-notice"><span class="it-icon-itsec"></span>'
43
  . __( 'New! Take your site security to the next level by activating iThemes Brute Force Network Protection.', 'better-wp-security' )
44
  . '<a class="itsec-notice-button" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'module' => 'network-brute-force', 'enable' => 'network-brute-force' ), ITSEC_Core::get_settings_page_url() ), 'itsec-enable-network-brute-force', 'itsec-enable-nonce' ) ) . '" onclick="document.location.href=\'?itsec_no_api_nag=off&_wpnonce=' . wp_create_nonce( 'itsec-nag' ) . '\';">' . __( 'Get Free API Key', 'better-wp-security' ) . '</a>'
45
  . '<button class="itsec-notice-hide" data-nonce="' . wp_create_nonce( 'dismiss-brute-force-network-notice' ) . '" data-source="brute_force_network">&times;</button>'
39
  add_action( 'admin_init', 'itsec_network_brute_force_add_notice' );
40
 
41
  function itsec_network_brute_force_show_notice() {
42
+ echo '<div id="itsec-notice-network-brute-force" class="updated itsec-notice"><span class="it-icon-itsec"></span>'
43
  . __( 'New! Take your site security to the next level by activating iThemes Brute Force Network Protection.', 'better-wp-security' )
44
  . '<a class="itsec-notice-button" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'module' => 'network-brute-force', 'enable' => 'network-brute-force' ), ITSEC_Core::get_settings_page_url() ), 'itsec-enable-network-brute-force', 'itsec-enable-nonce' ) ) . '" onclick="document.location.href=\'?itsec_no_api_nag=off&_wpnonce=' . wp_create_nonce( 'itsec-nag' ) . '\';">' . __( 'Get Free API Key', 'better-wp-security' ) . '</a>'
45
  . '<button class="itsec-notice-hide" data-nonce="' . wp_create_nonce( 'dismiss-brute-force-network-notice' ) . '" data-source="brute_force_network">&times;</button>'
core/modules/global/settings.php CHANGED
@@ -37,6 +37,7 @@ final class ITSEC_Global_Settings_New extends ITSEC_Settings {
37
  'hide_admin_bar' => false,
38
  'show_error_codes' => false,
39
  'show_new_dashboard_notice' => true,
 
40
  );
41
  }
42
 
37
  'hide_admin_bar' => false,
38
  'show_error_codes' => false,
39
  'show_new_dashboard_notice' => true,
40
+ 'show_security_check' => true,
41
  );
42
  }
43
 
core/modules/global/validator.php CHANGED
@@ -27,7 +27,7 @@ class ITSEC_Global_Validator extends ITSEC_Validator {
27
  }
28
 
29
 
30
- $this->set_previous_if_empty( array( 'did_upgrade', 'log_info', 'show_new_dashboard_notice' ) );
31
  $this->set_default_if_empty( array( 'log_location', 'nginx_file' ) );
32
 
33
 
27
  }
28
 
29
 
30
+ $this->set_previous_if_empty( array( 'did_upgrade', 'log_info', 'show_new_dashboard_notice', 'show_security_check' ) );
31
  $this->set_default_if_empty( array( 'log_location', 'nginx_file' ) );
32
 
33
 
core/modules/ipcheck/js/settings-page.js CHANGED
@@ -1,28 +1,28 @@
1
  jQuery( document ).ready(function ( $ ) {
2
  var $container = jQuery( '#wpcontent' );
3
-
4
  $container.on( 'click', '#itsec-network-brute-force-reset_api_key', function( e ) {
5
  e.preventDefault();
6
-
7
  if ( ! itsec_network_brute_force.original_button_text ) {
8
  itsec_network_brute_force.original_button_text = $( '#itsec-network-brute-force-reset_api_key' ).prop( 'value' );
9
  }
10
-
11
  $( '#itsec-network-brute-force-reset_api_key' )
12
  .removeClass( 'button-primary' )
13
  .addClass( 'button-secondary' )
14
  .prop( 'value', itsec_network_brute_force.resetting_button_text )
15
  .prop( 'disabled', true );
16
-
17
  var data = {
18
  'method': 'reset-api-key'
19
  };
20
-
21
  $( '#itsec-network-brute-force-reset-status' ).html( '' );
22
-
23
  itsecSettingsPage.sendModuleAJAXRequest( 'network-brute-force', data, function( results ) {
24
  $( '#itsec-network-brute-force-reset-status' ).html( '' );
25
-
26
  if ( true !== results.response ) {
27
  if ( results.errors && results.errors.length > 0 ) {
28
  $.each( results.errors, function( index, error ) {
@@ -31,13 +31,13 @@ jQuery( document ).ready(function ( $ ) {
31
  } else if ( 0 == results.response ) {
32
  $( '#itsec-network-brute-force-reset-status' ).append( '<div class="updated fade inline"><p><strong>' + itsec_network_brute_force.no_changes + '</strong></p></div>' );
33
  }
34
-
35
  $( '#itsec-network-brute-force-reset_api_key' )
36
  .removeClass( 'button-secondary' )
37
  .addClass( 'button-primary' )
38
  .prop( 'value', itsec_network_brute_force.original_button_text )
39
  .prop( 'disabled', false );
40
- }
41
  } );
42
  } );
43
  });
1
  jQuery( document ).ready(function ( $ ) {
2
  var $container = jQuery( '#wpcontent' );
3
+
4
  $container.on( 'click', '#itsec-network-brute-force-reset_api_key', function( e ) {
5
  e.preventDefault();
6
+
7
  if ( ! itsec_network_brute_force.original_button_text ) {
8
  itsec_network_brute_force.original_button_text = $( '#itsec-network-brute-force-reset_api_key' ).prop( 'value' );
9
  }
10
+
11
  $( '#itsec-network-brute-force-reset_api_key' )
12
  .removeClass( 'button-primary' )
13
  .addClass( 'button-secondary' )
14
  .prop( 'value', itsec_network_brute_force.resetting_button_text )
15
  .prop( 'disabled', true );
16
+
17
  var data = {
18
  'method': 'reset-api-key'
19
  };
20
+
21
  $( '#itsec-network-brute-force-reset-status' ).html( '' );
22
+
23
  itsecSettingsPage.sendModuleAJAXRequest( 'network-brute-force', data, function( results ) {
24
  $( '#itsec-network-brute-force-reset-status' ).html( '' );
25
+
26
  if ( true !== results.response ) {
27
  if ( results.errors && results.errors.length > 0 ) {
28
  $.each( results.errors, function( index, error ) {
31
  } else if ( 0 == results.response ) {
32
  $( '#itsec-network-brute-force-reset-status' ).append( '<div class="updated fade inline"><p><strong>' + itsec_network_brute_force.no_changes + '</strong></p></div>' );
33
  }
34
+
35
  $( '#itsec-network-brute-force-reset_api_key' )
36
  .removeClass( 'button-secondary' )
37
  .addClass( 'button-primary' )
38
  .prop( 'value', itsec_network_brute_force.original_button_text )
39
  .prop( 'disabled', false );
40
+ }
41
  } );
42
  } );
43
  });
core/modules/ipcheck/settings-page.php CHANGED
@@ -1,38 +1,38 @@
1
  <?php
2
 
3
  final class ITSEC_Network_Brute_Force_Settings_Page extends ITSEC_Module_Settings_Page {
4
- protected $script_version = 1;
5
-
6
-
7
  public function __construct() {
8
  $this->id = 'network-brute-force';
9
  $this->title = __( 'Network Brute Force Protection', 'better-wp-security' );
10
  $this->description = __( 'Join a network of sites that reports and protects against bad actors on the internet.', 'better-wp-security' );
11
  $this->type = 'recommended';
12
-
13
  parent::__construct();
14
  }
15
-
16
  public function enqueue_scripts_and_styles() {
17
  $settings = ITSEC_Modules::get_settings( $this->id );
18
-
19
  $vars = array(
20
  'resetting_button_text' => __( 'Resetting...', 'better-wp-security' ),
21
  );
22
-
23
  wp_enqueue_script( 'itsec-network-brute-force-settings-page-script', plugins_url( 'js/settings-page.js', __FILE__ ), array( 'jquery' ), $this->script_version, true );
24
  wp_localize_script( 'itsec-network-brute-force-settings-page-script', 'itsec_network_brute_force', $vars );
25
  }
26
-
27
  public function handle_ajax_request( $data ) {
28
  if ( 'reset-api-key' === $data['method'] ) {
29
  $defaults = ITSEC_Modules::get_defaults( $this->id );
30
  $results = ITSEC_Modules::set_settings( $this->id, $defaults );
31
-
32
  ITSEC_Response::set_response( $results['saved'] );
33
  ITSEC_Response::add_errors( $results['errors'] );
34
  ITSEC_Response::add_messages( $results['messages'] );
35
-
36
  if ( $results['saved'] ) {
37
  ITSEC_Response::reload_module( $this->id );
38
  } else if ( empty( $results['errors'] ) ) {
@@ -40,18 +40,18 @@ final class ITSEC_Network_Brute_Force_Settings_Page extends ITSEC_Module_Setting
40
  }
41
  }
42
  }
43
-
44
  protected function render_description( $form ) {
45
-
46
  ?>
47
  <p><?php _e( 'If one had unlimited time and wanted to try an unlimited number of password combinations to get into your site they eventually would, right? This method of attack, known as a brute force attack, is something that WordPress is acutely susceptible to as, by default, the system doesn\'t care how many attempts a user makes to login. It will always let you try again. Enabling login limits will ban the host user from attempting to login again after the specified bad login threshold has been reached.', 'better-wp-security' ); ?></p>
48
  <?php
49
-
50
  }
51
-
52
  protected function render_settings( $form ) {
53
  $settings = $form->get_options();
54
-
55
  ?>
56
  <p>
57
  <strong><?php _e( 'Network vs Local Brute Force Protection', 'better-wp-security' ); ?></strong>
@@ -96,7 +96,7 @@ final class ITSEC_Network_Brute_Force_Settings_Page extends ITSEC_Module_Setting
96
  </table>
97
  <?php endif; ?>
98
  <?php
99
-
100
  }
101
  }
102
 
1
  <?php
2
 
3
  final class ITSEC_Network_Brute_Force_Settings_Page extends ITSEC_Module_Settings_Page {
4
+ protected $script_version = 2;
5
+
6
+
7
  public function __construct() {
8
  $this->id = 'network-brute-force';
9
  $this->title = __( 'Network Brute Force Protection', 'better-wp-security' );
10
  $this->description = __( 'Join a network of sites that reports and protects against bad actors on the internet.', 'better-wp-security' );
11
  $this->type = 'recommended';
12
+
13
  parent::__construct();
14
  }
15
+
16
  public function enqueue_scripts_and_styles() {
17
  $settings = ITSEC_Modules::get_settings( $this->id );
18
+
19
  $vars = array(
20
  'resetting_button_text' => __( 'Resetting...', 'better-wp-security' ),
21
  );
22
+
23
  wp_enqueue_script( 'itsec-network-brute-force-settings-page-script', plugins_url( 'js/settings-page.js', __FILE__ ), array( 'jquery' ), $this->script_version, true );
24
  wp_localize_script( 'itsec-network-brute-force-settings-page-script', 'itsec_network_brute_force', $vars );
25
  }
26
+
27
  public function handle_ajax_request( $data ) {
28
  if ( 'reset-api-key' === $data['method'] ) {
29
  $defaults = ITSEC_Modules::get_defaults( $this->id );
30
  $results = ITSEC_Modules::set_settings( $this->id, $defaults );
31
+
32
  ITSEC_Response::set_response( $results['saved'] );
33
  ITSEC_Response::add_errors( $results['errors'] );
34
  ITSEC_Response::add_messages( $results['messages'] );
35
+
36
  if ( $results['saved'] ) {
37
  ITSEC_Response::reload_module( $this->id );
38
  } else if ( empty( $results['errors'] ) ) {
40
  }
41
  }
42
  }
43
+
44
  protected function render_description( $form ) {
45
+
46
  ?>
47
  <p><?php _e( 'If one had unlimited time and wanted to try an unlimited number of password combinations to get into your site they eventually would, right? This method of attack, known as a brute force attack, is something that WordPress is acutely susceptible to as, by default, the system doesn\'t care how many attempts a user makes to login. It will always let you try again. Enabling login limits will ban the host user from attempting to login again after the specified bad login threshold has been reached.', 'better-wp-security' ); ?></p>
48
  <?php
49
+
50
  }
51
+
52
  protected function render_settings( $form ) {
53
  $settings = $form->get_options();
54
+
55
  ?>
56
  <p>
57
  <strong><?php _e( 'Network vs Local Brute Force Protection', 'better-wp-security' ); ?></strong>
96
  </table>
97
  <?php endif; ?>
98
  <?php
99
+
100
  }
101
  }
102
 
core/modules/security-check/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden.
core/modules/security-check/init.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+
3
+ ITSEC_Modules::register_module( 'security-check', dirname( __FILE__ ), 'always-active' );
core/modules/security-check/js/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php //You don't belong here. ?>
core/modules/security-check/js/settings-page.js ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( document ).ready( function ( $ ) {
2
+ var $container = $( '#itsec-module-card-security-check' )
3
+
4
+ $container.on( 'click', '#itsec-security-check-secure_site', function( e ) {
5
+ e.preventDefault();
6
+
7
+ $( '#itsec-security-check-secure_site' )
8
+ .removeClass( 'button-primary' )
9
+ .addClass( 'button-secondary' )
10
+ .attr( 'value', itsec_security_check_settings.securing_site )
11
+ .prop( 'disabled', true );
12
+
13
+ $( '#itsec-security-check-details-container' ).html( '' );
14
+
15
+ var data = {
16
+ 'method': 'secure-site'
17
+ };
18
+
19
+ itsecSettingsPage.sendModuleAJAXRequest( 'security-check', data, function( results ) {
20
+ $( '#itsec-security-check-secure_site' )
21
+ .addClass( 'button-primary' )
22
+ .removeClass( 'button-secondary' )
23
+ .attr( 'value', itsec_security_check_settings.rerun_secure_site )
24
+ .prop( 'disabled', false );
25
+
26
+ $( '#itsec-security-check-details-container' ).html( results.response );
27
+ } );
28
+ } );
29
+
30
+ $container.on( 'click', '#itsec-security-check-enable_network_brute_force', function( e ) {
31
+ e.preventDefault();
32
+
33
+ var original_button_name = $( '#itsec-security-check-enable_network_brute_force' ).attr( 'value' );
34
+
35
+ $( '#itsec-security-check-enable_network_brute_force' )
36
+ .removeClass( 'button-primary' )
37
+ .addClass( 'button-secondary' )
38
+ .attr( 'value', itsec_security_check_settings.activating_network_brute_force )
39
+ .prop( 'disabled', true );
40
+
41
+ var data = {
42
+ 'method': 'activate-network-brute-force',
43
+ 'email': $( '#itsec-security-check-email' ).attr( 'value' ),
44
+ 'updates_optin': $( '#itsec-security-check-updates_optin option:selected' ).text()
45
+ };
46
+
47
+ itsecSettingsPage.sendModuleAJAXRequest( 'security-check', data, function( results ) {
48
+ $( '#itsec-security-check-enable_network_brute_force' )
49
+ .addClass( 'button-primary' )
50
+ .removeClass( 'button-secondary' )
51
+ .attr( 'value', original_button_name )
52
+ .prop( 'disabled', false );
53
+
54
+ $( '#itsec-security-check-network-brute-force-errors' ).html( '' );
55
+ var $container = $( '#itsec-module-card-security-check #itsec-security-check-network-brute-force-container' );
56
+
57
+ if ( results.errors && results.errors.length > 0 ) {
58
+ $container
59
+ .removeClass( 'itsec-security-check-container-incomplete' )
60
+ .removeClass( 'itsec-security-check-container-complete' )
61
+ .addClass( 'itsec-security-check-container-error' );
62
+
63
+ $.each( results.errors, function( index, error ) {
64
+ $( '#itsec-security-check-network-brute-force-errors' ).append( '<div class="error inline"><p><strong>' + error + '</strong></p></div>' );
65
+ } );
66
+ } else {
67
+ $container
68
+ .removeClass( 'itsec-security-check-container-incomplete' )
69
+ .removeClass( 'itsec-security-check-container-error' )
70
+ .addClass( 'itsec-security-check-container-complete' );
71
+
72
+ $container.html( results.response );
73
+ $( '#itsec-notice-network-brute-force' ).hide();
74
+ }
75
+ } );
76
+ } );
77
+ } );
core/modules/security-check/scanner.php ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ final class ITSEC_Security_Check_Scanner {
4
+ private static $available_modules;
5
+ private static $calls_to_action = array();
6
+ private static $actions_taken = array();
7
+ private static $confirmations = array();
8
+
9
+
10
+ public static function run() {
11
+ self::$available_modules = ITSEC_Modules::get_available_modules();
12
+
13
+ self::enforce_activation( 'ban-users', __( 'Banned Users', 'better-wp-security' ) );
14
+ self::enforce_setting( 'ban-users', 'enable_ban_lists', true, __( 'Enabled the Enable Ban Lists setting in Banned Users.', 'better-wp-security' ) );
15
+
16
+ self::enforce_activation( 'backup', __( 'Database Backups', 'better-wp-security' ) );
17
+ self::enforce_activation( 'brute-force', __( 'Local Brute Force Protection', 'better-wp-security' ) );
18
+ self::enforce_activation( 'malware-scheduling', __( 'Malware Scan Scheduling', 'better-wp-security' ) );
19
+ self::enforce_setting( 'malware-scheduling', 'email_notifications', true, __( 'Enabled the Email Notifications setting in Malware Scan Scheduling.', 'better-wp-security' ) );
20
+
21
+ self::add_network_brute_force_signup();
22
+
23
+ self::enforce_activation( 'strong-passwords', __( 'Strong Password Enforcement', 'better-wp-security' ) );
24
+ self::enforce_activation( 'two-factor', __( 'Two-Factor Authentication', 'better-wp-security' ) );
25
+ self::enable_all_two_factor_providers();
26
+
27
+ self::enforce_activation( 'user-logging', __( 'User Logging', 'better-wp-security' ) );
28
+ self::enforce_activation( 'wordpress-tweaks', __( 'WordPress Tweaks', 'better-wp-security' ) );
29
+ self::enforce_setting( 'wordpress-tweaks', 'file_editor', true, __( 'Disabled the File Editor in WordPress Tweaks.', 'better-wp-security' ) );
30
+ self::enforce_setting( 'wordpress-tweaks', 'allow_xmlrpc_multiauth', false, __( 'Changed the Multiple Authentication Attempts per XML-RPC Request setting in WordPress Tweaks to "Block".', 'better-wp-security' ) );
31
+
32
+ self::enforce_setting( 'global', 'write_files', true, __( 'Enabled the Write to Files setting in Global Settings.', 'better-wp-security' ) );
33
+
34
+
35
+ ob_start();
36
+
37
+ echo implode( "\n", self::$calls_to_action );
38
+ echo implode( "\n", self::$actions_taken );
39
+ echo implode( "\n", self::$confirmations );
40
+
41
+ ITSEC_Response::set_response( ob_get_clean() );
42
+ }
43
+
44
+ private static function add_network_brute_force_signup() {
45
+ if ( ! in_array( 'network-brute-force', self::$available_modules ) ) {
46
+ return;
47
+ }
48
+
49
+
50
+ $settings = ITSEC_Modules::get_settings( 'network-brute-force' );
51
+
52
+ if ( ! empty( $settings['api_key'] ) && ! empty( $settings['api_secret'] ) ) {
53
+ self::enforce_activation( 'network-brute-force', __( 'Network Brute Force Protection', 'better-wp-security' ) );
54
+ return;
55
+ }
56
+
57
+
58
+ require_once( ITSEC_Core::get_core_dir() . '/lib/form.php' );
59
+ $form = new ITSEC_Form();
60
+ $form->add_input_group( 'security-check' );
61
+
62
+ ob_start();
63
+
64
+ self::open_container( 'incomplete', 'itsec-security-check-network-brute-force-container' );
65
+
66
+ echo '<p>' . __( 'With Network Brute Force Protection, your site is protected against attackers found by other sites running iThemes Security. If your site identifies a new attacker, it automatically notifies the network so that other sites are protected as well. To join this site to the network and enable the protection, click the button below.', 'better-wp-security' ) . '</p>';
67
+
68
+ ob_start();
69
+ $form->add_text( 'email', array( 'class' => 'regular-text', 'value' => get_option( 'admin_email' ) ) );
70
+ $email_input = ob_get_clean();
71
+ /* translators: 1: email text input */
72
+ echo '<p><label for="itsec-security-check-email">' . sprintf( __( 'Email Address: %1$s', 'better-wp-security' ), $email_input ) . '</p>';
73
+
74
+ ob_start();
75
+ $form->add_select( 'updates_optin', array( 'true' => __( 'Yes', 'better-wp-security' ), 'false' => __( 'No', 'better-wp-security' ) ) );
76
+ $optin_input = ob_get_clean();
77
+ /* translators: 1: opt-in input */
78
+ echo '<p><label for="itsec-security-check-updates_optin">' . sprintf( __( 'Receive email updates about WordPress Security from iThemes: %1$s', 'better-wp-security' ), $optin_input ) . '</p>';
79
+
80
+ ob_start();
81
+ $form->add_button( 'enable_network_brute_force', array( 'class' => 'button-primary', 'value' => __( 'Activate Network Brute Force Protection', 'better-wp-security' ) ) );
82
+ echo '<p>' . ob_get_clean() . '</p>';
83
+
84
+ echo '<div id="itsec-security-check-network-brute-force-errors"></div>';
85
+
86
+ echo '</div>';
87
+
88
+ self::$calls_to_action[] = ob_get_clean();
89
+ }
90
+
91
+ private static function enable_all_two_factor_providers() {
92
+ if ( ! in_array( 'two-factor', self::$available_modules ) ) {
93
+ return;
94
+ }
95
+
96
+
97
+ $two_factor_providers = ITSEC_Modules::get_setting( 'two-factor', 'enabled-providers' );
98
+ $added_provider = false;
99
+
100
+ ob_start();
101
+
102
+ if ( ! in_array( 'Two_Factor_Totp', $two_factor_providers ) ) {
103
+ $two_factor_providers[] = 'Two_Factor_Totp';
104
+ $added_provider = true;
105
+
106
+ self::open_container();
107
+ echo '<p>' . __( 'Enabled the Time-Based One-Time Password (TOTP) provider for Two-Factor Authentication.', 'better-wp-security' ) . '</p>';
108
+ echo '</div>';
109
+ }
110
+
111
+ if ( ! in_array( 'Two_Factor_Email', $two_factor_providers ) ) {
112
+ $two_factor_providers[] = 'Two_Factor_Email';
113
+ $added_provider = true;
114
+
115
+ self::open_container();
116
+ echo '<p>' . __( 'Enabled the Email provider for Two-Factor Authentication.', 'better-wp-security' ) . '</p>';
117
+ echo '</div>';
118
+ }
119
+
120
+ if ( ! in_array( 'Two_Factor_Backup_Codes', $two_factor_providers ) ) {
121
+ $two_factor_providers[] = 'Two_Factor_Backup_Codes';
122
+ $added_provider = true;
123
+
124
+ self::open_container();
125
+ echo '<p>' . __( 'Enabled the Backup Verification Codes provider for Two-Factor Authentication.', 'better-wp-security' ) . '</p>';
126
+ echo '</div>';
127
+ }
128
+
129
+
130
+ if ( $added_provider ) {
131
+ self::$actions_taken[] = ob_get_clean();
132
+
133
+ ITSEC_Modules::set_setting( 'two-factor', 'enabled-providers', $two_factor_providers );
134
+
135
+ ITSEC_Response::reload_module( 'two-factor' );
136
+ }
137
+ }
138
+
139
+ private static function enforce_setting( $module, $setting_name, $setting_value, $description ) {
140
+ if ( ! in_array( $module, self::$available_modules ) ) {
141
+ return;
142
+ }
143
+
144
+ if ( ITSEC_Modules::get_setting( $module, $setting_name ) !== $setting_value ) {
145
+ ITSEC_Modules::set_setting( $module, $setting_name, $setting_value );
146
+
147
+ ob_start();
148
+
149
+ self::open_container();
150
+ echo "<p>$description</p>";
151
+ echo '</div>';
152
+
153
+ self::$actions_taken[] = ob_get_clean();
154
+
155
+ ITSEC_Response::reload_module( $module );
156
+ }
157
+ }
158
+
159
+ private static function enforce_activation( $module, $name ) {
160
+ if ( ! in_array( $module, self::$available_modules ) ) {
161
+ return;
162
+ }
163
+
164
+ if ( ITSEC_Modules::is_active( $module ) ) {
165
+ /* Translators: 1: feature name */
166
+ $text = __( '%1$s is enabled as recommended.', 'better-wp-security' );
167
+ $took_action = false;
168
+ } else {
169
+ ITSEC_Modules::activate( $module );
170
+ ITSEC_Response::add_js_function_call( 'setModuleToActive', $module );
171
+
172
+ /* Translators: 1: feature name */
173
+ $text = __( 'Enabled %1$s.', 'better-wp-security' );
174
+ $took_action = true;
175
+ }
176
+
177
+ ob_start();
178
+
179
+ self::open_container();
180
+ echo '<p>' . sprintf( $text, $name ) . '</p>';
181
+ echo '</div>';
182
+
183
+ if ( $took_action ) {
184
+ self::$actions_taken[] = ob_get_clean();
185
+ } else {
186
+ self::$confirmations[] = ob_get_clean();
187
+ }
188
+ }
189
+
190
+ public static function activate_network_brute_force() {
191
+ $settings = ITSEC_Modules::get_settings( 'network-brute-force' );
192
+
193
+ $settings['email'] = $_POST['data']['email'];
194
+ $settings['updates_optin'] = $_POST['data']['updates_optin'];
195
+ $settings['api_nag'] = false;
196
+
197
+ $results = ITSEC_Modules::set_settings( 'network-brute-force', $settings );
198
+
199
+ if ( is_wp_error( $results ) ) {
200
+ ITSEC_Response::add_error( $results );
201
+ } else if ( $results['saved'] ) {
202
+ ITSEC_Modules::activate( 'network-brute-force' );
203
+ ITSEC_Response::add_js_function_call( 'setModuleToActive', 'network-brute-force' );
204
+ ITSEC_Response::set_response( '<p>' . __( 'Your site is now using Network Brute Force Protection.', 'better-wp-security' ) . '</p>' );
205
+ }
206
+ }
207
+
208
+ private static function open_container( $status = 'complete', $id = '' ) {
209
+ echo '<div class="itsec-security-check-container itsec-security-check-container-' . $status . '"';
210
+
211
+ if ( ! empty( $id ) ) {
212
+ echo ' id="' . $id . '"';
213
+ }
214
+
215
+ echo '>';
216
+ }
217
+ }
core/modules/security-check/settings-page.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ final class ITSEC_Security_Check_Settings_Page extends ITSEC_Module_Settings_Page {
4
+ private $script_version = 1;
5
+
6
+
7
+ public function __construct() {
8
+ $this->id = 'security-check';
9
+ $this->title = __( 'Security Check', 'better-wp-security' );
10
+ $this->description = __( 'Ensure that your site is using the recommended features and settings.', 'better-wp-security' );
11
+ $this->type = 'recommended';
12
+ $this->information_only = true;
13
+ $this->can_save = false;
14
+
15
+ parent::__construct();
16
+ }
17
+
18
+ public function enqueue_scripts_and_styles() {
19
+ $vars = array(
20
+ 'securing_site' => __( 'Securing Site...', 'better-wp-security' ),
21
+ 'rerun_secure_site' => __( 'Run Secure Site Again', 'better-wp-security' ),
22
+ 'activating_network_brute_force' => __( 'Activating Network Brute Force Protection...', 'better-wp-security' ),
23
+ );
24
+
25
+ wp_enqueue_script( 'itsec-security-check-settings-script', plugins_url( 'js/settings-page.js', __FILE__ ), array( 'jquery' ), $this->script_version, true );
26
+ wp_localize_script( 'itsec-security-check-settings-script', 'itsec_security_check_settings', $vars );
27
+ }
28
+
29
+ public function handle_ajax_request( $data ) {
30
+ if ( 'secure-site' === $data['method'] ) {
31
+ require_once( dirname( __FILE__ ) . '/scanner.php' );
32
+
33
+ ITSEC_Security_Check_Scanner::run();
34
+ } else if ( 'activate-network-brute-force' === $data['method'] ) {
35
+ require_once( dirname( __FILE__ ) . '/scanner.php' );
36
+
37
+ ITSEC_Security_Check_Scanner::activate_network_brute_force();
38
+ }
39
+ }
40
+
41
+ protected function render_description( $form ) {}
42
+
43
+ protected function render_settings( $form ) {
44
+ $available_modules = ITSEC_Modules::get_available_modules();
45
+
46
+ $modules_to_activate = array(
47
+ 'ban-users' => __( 'Banned Users', 'better-wp-security' ),
48
+ 'backup' => __( 'Database Backups', 'better-wp-security' ),
49
+ 'brute-force' => __( 'Local Brute Force Protection', 'better-wp-security' ),
50
+ 'malware-scheduling' => __( 'Malware Scan Scheduling', 'better-wp-security' ),
51
+ 'network-brute-force' => __( 'Network Brute Force Protection', 'better-wp-security' ),
52
+ 'strong-passwords' => __( 'Strong Passwords', 'better-wp-security' ),
53
+ 'two-factor' => __( 'Two-Factor Authentication', 'better-wp-security' ),
54
+ 'user-logging' => __( 'User Logging', 'better-wp-security' ),
55
+ 'wordpress-tweaks' => __( 'WordPress Tweaks', 'better-wp-security' ),
56
+ );
57
+
58
+ foreach ( $modules_to_activate as $module => $val ) {
59
+ if ( ! in_array( $module, $available_modules ) ) {
60
+ unset( $modules_to_activate[$module] );
61
+ }
62
+ }
63
+
64
+ ?>
65
+ <div id="itsec-security-check-details-container">
66
+ <p><?php _e( 'Some features and settings are recommended for every site to run. This tool will ensure that your site is using these recommendations.', 'better-wp-security' ); ?></p>
67
+ <p><?php _e( 'When the button below is clicked the following modules will be enabled and configured:', 'better-wp-security' ); ?></p>
68
+ <ul class="itsec-security-check-list">
69
+ <?php foreach ( $modules_to_activate as $name ) : ?>
70
+ <li><p><?php echo $name; ?></p></li>
71
+ <?php endforeach; ?>
72
+ </ul>
73
+ </div>
74
+
75
+ <p><?php $form->add_button( 'secure_site', array( 'value' => 'Secure Site', 'class' => 'button-primary' ) ); ?></p>
76
+ <?php
77
+
78
+ }
79
+ }
80
+ new ITSEC_Security_Check_Settings_Page();
history.txt CHANGED
@@ -530,3 +530,7 @@
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.
 
 
 
 
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.
533
+ 5.6.0 - 2016-06-16 - Chris Jean & Aaron D. Campbell
534
+ New Feature: Added a new Security Check section on the settings page. This new feature adds a tool to quickly ensure that the recommended features are enabled and the recommended settings are used.
535
+ Bug Fix: Fixed the ability to remove the itsec_away.confg file in order to disable Away Mode.
536
+ Enhancement: The "Ban Lists" setting of Banned Users is now enabled by default.
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.5.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -188,6 +188,11 @@ Free support may be available with the help of the community in the <a href="htt
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.
@@ -1554,6 +1559,9 @@ This release is a complete rewrite from the ground up. Special thanks to Cory Mi
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
 
@@ -1586,78 +1594,3 @@ Version 5.3.5 contains minor bugfixes and enhancements and is recommended for al
1586
 
1587
  = 5.3.4 =
1588
  Version 5.3.4 contains minor bugfixes and enhancements and is recommended for all users.
1589
-
1590
- = 4.6.8 =
1591
- Version 4.6.8 contains minor bugfixes and enhancements and is recommended for all users.
1592
-
1593
- = 4.6.6 =
1594
- Version 4.6.6 contains minor bugfixes and is recommended for all users.
1595
-
1596
- = 4.6.2 =
1597
- Version 4.6.2 contains new features and enhancements and is recommended for all users.
1598
-
1599
- = 4.5.10 =
1600
- Version 4.5.10 contains minor bugfixes and is recommended for all users.
1601
-
1602
- = 4.5.8 =
1603
- Version 4.5.8 contains minor bugfixes and enhancements and is recommended for all users.
1604
-
1605
- = 4.5.6 =
1606
- Version 4.5.6 contains a minor bugfix and is recommended for all users.
1607
-
1608
- = 4.5.2 =
1609
- Version 4.5.2 is a feature and bug-fix release addressing numerous minor bugs affecting some users. It is recommended for all users.
1610
-
1611
- = 4.4.23 =
1612
- Version 4.4.23 contains a security update and is recommended for all users.
1613
-
1614
- = 4.4.21 =
1615
- Version 4.4.21 contains a fix to an issue that affects daylight savings time as well as other minor bug fixes. It is recommended for all users.
1616
-
1617
- = 4.4.20 =
1618
- Version 4.4.20 contains a minor bugfix and is recommended for all users.
1619
-
1620
- = 4.4.18 =
1621
- Version 4.4.18 contains a minor bugfix and is recommended for all users.
1622
-
1623
- = 4.4.16 =
1624
- Version 4.4.16 is a bug-fix release addressing numerous minor bugs affecting some users. It is recommended for all users.
1625
-
1626
- = 4.4.15 =
1627
- Version 4.4.15 is a bug-fix release addressing numerous minor bugs affecting some users. It is recommended for all users.
1628
-
1629
- = 4.4.13 =
1630
- Version 4.4.13 is a bug-fix release addressing numerous minor bugs affecting some users. It is recommended for all users.
1631
-
1632
- = 4.4.11 =
1633
- Version 4.4.11 is a bug-fix release addressing numerous minor bugs affecting some users. It is recommended for all users.
1634
-
1635
- = 4.4.9 =
1636
- Version 4.4.9 is a bugfix release for the free version and contains new features for pro users. It is a recommended update for all users.
1637
-
1638
- = 4.4.6 =
1639
- Version 4.4.6 adds new features, enhancements, bug fixes and more. It is recommended for all users.
1640
-
1641
- = 4.3.11 =
1642
- Version 4.3.11 contains a security fix and should be installed by all users.
1643
-
1644
- = 4.3.9 =
1645
- Version 4.3.9 is a bug-fix release addressing numerous minor bugs affecting some users. It is recommended for all users.
1646
-
1647
- = 4.3.7 =
1648
- Version 4.3.7 adds malware scheduling and other features as well as numerous minor bugfixes and enhancements. It is recommended for all users.
1649
-
1650
- = 4.3.3 =
1651
- Version 4.3.3 adds malware scheduling and other features as well as numerous minor bugfixes and enhancements. It is recommended for all users.
1652
-
1653
- = 4.2.15 =
1654
- Version 4.2.15 delivers fixes for minor bugs experienced by some users.
1655
-
1656
- = 4.2.13 =
1657
- Version 4.2.13 delivers fixes for minor bugs experienced by some users.
1658
-
1659
- = 4.2.8 =
1660
- Version 4.2.8 delivers fixes for minor bugs and some enhancements including the ability to whitelist file types in 404 detection.
1661
-
1662
- = 4.2.6 =
1663
- Better WP Security is now iThemes Security with new features and a greatly improved code base. We recommend disabling Better WP Security before upgrading to 4.2.6 if you are not already on 4.0 or greater.
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.6.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.6.0 =
192
+ * New Feature: Added a new Security Check section on the settings page. This new feature adds a tool to quickly ensure that the recommended features are enabled and the recommended settings are used.
193
+ * Bug Fix: Fixed the ability to remove the itsec_away.confg file in order to disable Away Mode.
194
+ * Enhancement: The "Ban Lists" setting of Banned Users is now enabled by default.
195
+
196
  = 5.5.0 =
197
  * 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.
198
  * 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.
1559
 
1560
  == Upgrade Notice ==
1561
 
1562
+ = 5.6.0 =
1563
+ Version 5.6.0 contains a new feature to quickly apply recommended settings. It is recommended for all users.
1564
+
1565
  = 5.5.0 =
1566
  Version 5.5.0 contains important bug fixes, a new File Permissions feature, and numerous enhancements. It is recommended for all users.
1567
 
1594
 
1595
  = 5.3.4 =
1596
  Version 5.3.4 contains minor bugfixes and enhancements and is recommended for all users.