iThemes Security (formerly Better WP Security) - Version 6.1.0

Version Description

  • Enhancement: Added logging for failed two-factor, OAuth, and REST API authentications.
    • Enhancement: Added logging details about the source of login failures and the type of authentication that failed.
    • Enhancement: Due to improvements in tracking authentication failures, brute force attempts using alternate authentication methods are more reliably found and blocked.
    • Enhancement: The server's IP is treated as whitelisted and will not be considered for lockouts or bans.
    • Enhancement: Reduced memory usage when creating a backup.
    • Enhancement: Changed log entry description of "IP Flagged as bad by iThemes IPCheck" to "IP Flagged by Network Brute Force Protection". This should help clarify the meaning of the log entry.
    • Enhancement: Improved efficiency of the Network Brute Force Protection feature.
    • Bug Fix: Fixed bug that prevented Network Brute Force Protection from working properly on some sites.
Download this release

Release Info

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

Code changes from version 6.0.0 to 6.1.0

Files changed (33) hide show
  1. better-wp-security.php +1 -1
  2. core/admin-pages/css/style.css +11 -1
  3. core/class-ithemes-sync-verb-itsec-get-everything.php +0 -69
  4. core/class-itsec-core.php +23 -33
  5. core/class-itsec-lib.php +50 -0
  6. core/class-itsec-lockout.php +24 -21
  7. core/class-itsec-sync.php +0 -89
  8. core/history.txt +9 -0
  9. core/modules/away-mode/class-itsec-away-mode.php +22 -17
  10. core/modules/away-mode/sync-verbs/index.php +1 -0
  11. core/modules/away-mode/{class-ithemes-sync-verb-itsec-get-away-mode.php → sync-verbs/itsec-get-away-mode.php} +0 -0
  12. core/modules/away-mode/{class-ithemes-sync-verb-itsec-override-away-mode.php → sync-verbs/itsec-override-away-mode.php} +0 -0
  13. core/modules/backup/class-itsec-backup.php +126 -164
  14. core/modules/brute-force/class-itsec-brute-force.php +13 -77
  15. core/modules/file-change/class-ithemes-sync-verb-itsec-perform-file-scan.php +0 -53
  16. core/modules/file-change/class-itsec-file-change.php +8 -22
  17. core/modules/file-change/sync-verbs/index.php +1 -0
  18. core/modules/file-change/sync-verbs/itsec-perform-file-scan.php +12 -0
  19. core/modules/ipcheck/class-itsec-ipcheck.php +106 -241
  20. core/modules/ipcheck/setup.php +4 -0
  21. core/modules/malware/class-itsec-malware.php +24 -18
  22. core/modules/malware/sync-verbs/index.php +1 -0
  23. core/modules/malware/{class-ithemes-sync-verb-itsec-do-malware-scan.php → sync-verbs/itsec-do-malware-scan.php} +3 -8
  24. core/modules/malware/{class-ithemes-sync-verb-itsec-get-malware-scan-log.php → sync-verbs/itsec-get-malware-scan-log.php} +0 -0
  25. core/modules/security-check/scanner.php +4 -49
  26. core/sync-verbs/index.php +1 -0
  27. core/sync-verbs/itsec-get-everything.php +23 -0
  28. core/{class-ithemes-sync-verb-itsec-get-lockouts.php → sync-verbs/itsec-get-lockouts.php} +0 -0
  29. core/{class-ithemes-sync-verb-itsec-get-temp-whitelist.php → sync-verbs/itsec-get-temp-whitelist.php} +0 -0
  30. core/{class-ithemes-sync-verb-itsec-release-lockout.php → sync-verbs/itsec-release-lockout.php} +0 -0
  31. core/{class-ithemes-sync-verb-itsec-set-temp-whitelist.php → sync-verbs/itsec-set-temp-whitelist.php} +0 -0
  32. history.txt +9 -0
  33. readme.txt +14 -4
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: 6.0.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: 6.1.0
10
  * Text Domain: better-wp-security
11
  * Network: True
12
  * License: GPLv2
core/admin-pages/css/style.css CHANGED
@@ -578,6 +578,16 @@ body.itsec-modal-open {
578
  color: #9c3e3e;
579
  }
580
 
 
 
 
 
 
 
 
 
 
 
581
  /*
582
  * Security Check
583
  */
@@ -672,4 +682,4 @@ body.itsec-modal-open {
672
  .itsec-password-strength.strong {
673
  background-color: #c1e1b9;
674
  border-color: #83c373;
675
- }
578
  color: #9c3e3e;
579
  }
580
 
581
+ .itsec-notice-message {
582
+ display: block;
583
+ clear: both;
584
+ font-size: 1.125em;
585
+ margin: 1.5em 0;
586
+ padding: 1em;
587
+ border-left: 4px solid #e8e4a7;
588
+ background: #fff9ec;
589
+ }
590
+
591
  /*
592
  * Security Check
593
  */
682
  .itsec-password-strength.strong {
683
  background-color: #c1e1b9;
684
  border-color: #83c373;
685
+ }
core/class-ithemes-sync-verb-itsec-get-everything.php DELETED
@@ -1,69 +0,0 @@
1
- <?php
2
-
3
- class Ithemes_Sync_Verb_ITSEC_Get_Everything extends Ithemes_Sync_Verb {
4
-
5
- public static $name = 'itsec-get-everything';
6
- public static $description = 'Retrieve iThemes Security Status and other information.';
7
-
8
- private $default_arguments = array();
9
-
10
- public function run( $arguments ) {
11
-
12
- $itsec_sync = ITSEC_Core::get_itsec_sync();
13
-
14
- $modules = $itsec_sync->get_modules();
15
- $module_results = array();
16
-
17
- //return $modules;
18
-
19
- foreach ( $modules as $name => $module ) {
20
-
21
- if ( isset( $module['verbs'] ) && isset( $module['path'] ) && isset( $module['everything'] ) ) {
22
-
23
- $everything = array();
24
-
25
- if ( is_array( $module['everything'] ) ) {
26
-
27
- foreach ( $module['everything'] as $item ) {
28
-
29
- if ( isset( $module['verbs'][ $item ] ) ) {
30
- $everything[] = $item;
31
- }
32
-
33
- }
34
-
35
- } elseif ( isset( $module['verbs'][ $module['everything'] ] ) ) {
36
-
37
- $everything[] = $module['everything'];
38
-
39
- }
40
-
41
- foreach ( $everything as $verb ) {
42
-
43
- $class = $module['verbs'][ $verb ];
44
-
45
- if ( ! class_exists( $class ) ) {
46
-
47
- require( trailingslashit( $module['path'] ) . 'class-ithemes-sync-verb-' . $verb . '.php' );
48
-
49
- }
50
-
51
- $obj = new $class;
52
-
53
- $module_results[ $name ][ $verb ] = $obj->run( array() );
54
-
55
- }
56
-
57
- }
58
-
59
- }
60
-
61
- return array_merge( array(
62
- 'api' => '1',
63
- ),
64
- $module_results
65
- );
66
-
67
- }
68
-
69
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/class-itsec-core.php CHANGED
@@ -25,7 +25,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
25
  private
26
  $itsec_files,
27
  $itsec_notify,
28
- $itsec_sync,
29
  $plugin_build,
30
  $plugin_file,
31
  $plugin_dir,
@@ -74,7 +74,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
74
  public function init( $plugin_file, $plugin_name ) {
75
  global $itsec_globals, $itsec_logger, $itsec_lockout;
76
 
77
- $this->plugin_build = 4050; // used to trigger updates
78
  $this->plugin_file = $plugin_file;
79
  $this->plugin_dir = dirname( $plugin_file ) . '/';
80
  $this->current_time = current_time( 'timestamp' );
@@ -156,7 +156,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
156
 
157
  //Admin bar links
158
  if ( ! ITSEC_Modules::get_setting( 'global', 'hide_admin_bar' ) ) {
159
- add_action( 'admin_bar_menu', array( $this, 'admin_bar_links' ), 99 );
160
  }
161
 
162
  //See if they're upgrade from Better WP Security
@@ -179,6 +179,9 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
179
  }
180
 
181
 
 
 
 
182
  do_action( 'itsec_initialized' );
183
  }
184
 
@@ -192,20 +195,16 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
192
  return $self->itsec_notify;
193
  }
194
 
195
- public static function get_itsec_sync() {
196
  $self = self::get_instance();
197
-
198
- if ( ! isset( $self->itsec_sync ) ) {
199
- require( dirname( __FILE__ ) . '/class-itsec-sync.php' );
200
- $self->itsec_sync = new ITSEC_Sync();
201
- }
202
-
203
- return $self->itsec_sync;
204
  }
205
 
206
  public function register_sync_verbs( $sync_api ) {
207
- $itsec_sync = self::get_itsec_sync();
208
- $itsec_sync->register_verbs( $sync_api );
 
 
209
  }
210
 
211
  public function register_modules() {
@@ -257,8 +256,6 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
257
 
258
  static $this_plugin;
259
 
260
- global $itsec_globals;
261
-
262
  if ( empty( $this_plugin ) ) {
263
  $this_plugin = str_replace( WP_PLUGIN_DIR . '/', '', self::get_plugin_file() );
264
  }
@@ -283,7 +280,6 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
283
  */
284
  public function add_plugin_meta_links( $meta, $plugin_file ) {
285
 
286
- global $itsec_globals;
287
  $plugin_base = str_replace( WP_PLUGIN_DIR . '/', '', self::get_plugin_file() );
288
 
289
  if ( $plugin_base == $plugin_file ) {
@@ -302,16 +298,14 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
302
  *
303
  * @return void
304
  */
305
- public function admin_bar_links() {
306
-
307
- global $wp_admin_bar, $itsec_globals;
308
 
309
  if ( ! ITSEC_Core::current_user_can_manage() ) {
310
  return;
311
  }
312
 
313
  // Add the Parent link.
314
- $wp_admin_bar->add_menu(
315
  array(
316
  'title' => __( 'Security', 'better-wp-security' ),
317
  'href' => self::get_settings_page_url(),
@@ -319,30 +313,30 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
319
  )
320
  );
321
 
322
- $wp_admin_bar->add_menu(
323
  array(
324
- 'id' => 'itsec_admin_bar_settings',
325
  'title' => __( 'Settings', 'better-wp-security' ),
326
  'href' => self::get_settings_page_url(),
327
- 'parent' => 'itsec_admin_bar_menu',
328
  )
329
  );
330
 
331
- $wp_admin_bar->add_menu(
332
  array(
333
- 'id' => 'itsec_admin_bar_security_check',
334
  'title' => __( 'Security Check', 'better-wp-security' ),
335
  'href' => self::get_security_check_page_url(),
336
- 'parent' => 'itsec_admin_bar_menu',
337
  )
338
  );
339
 
340
- $wp_admin_bar->add_menu(
341
  array(
342
- 'id' => 'itsec_admin_bar_logs',
343
  'title' => __( 'Logs', 'better-wp-security' ),
344
  'href' => self::get_logs_page_url(),
345
- 'parent' => 'itsec_admin_bar_menu',
346
  )
347
  );
348
  }
@@ -356,8 +350,6 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
356
  */
357
  public function do_upgrade() {
358
 
359
- global $itsec_globals;
360
-
361
  //require plugin setup information
362
  if ( ! class_exists( 'ITSEC_Setup' ) ) {
363
  require( self::get_core_dir() . '/class-itsec-setup.php' );
@@ -476,8 +468,6 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
476
  */
477
  public function save_plugin_data() {
478
 
479
- global $itsec_globals;
480
-
481
  $save_data = false; //flag to avoid saving data if we don't have to
482
 
483
  $plugin_data = get_site_option( 'itsec_data' );
25
  private
26
  $itsec_files,
27
  $itsec_notify,
28
+ $sync_api,
29
  $plugin_build,
30
  $plugin_file,
31
  $plugin_dir,
74
  public function init( $plugin_file, $plugin_name ) {
75
  global $itsec_globals, $itsec_logger, $itsec_lockout;
76
 
77
+ $this->plugin_build = 4056; // used to trigger updates
78
  $this->plugin_file = $plugin_file;
79
  $this->plugin_dir = dirname( $plugin_file ) . '/';
80
  $this->current_time = current_time( 'timestamp' );
156
 
157
  //Admin bar links
158
  if ( ! ITSEC_Modules::get_setting( 'global', 'hide_admin_bar' ) ) {
159
+ add_action( 'admin_bar_menu', array( $this, 'modify_admin_bar' ), 99 );
160
  }
161
 
162
  //See if they're upgrade from Better WP Security
179
  }
180
 
181
 
182
+ add_action( 'wp_login_failed', array( 'ITSEC_Lib', 'handle_wp_login_failed' ) );
183
+
184
+
185
  do_action( 'itsec_initialized' );
186
  }
187
 
195
  return $self->itsec_notify;
196
  }
197
 
198
+ public static function get_sync_api() {
199
  $self = self::get_instance();
200
+ return $self->sync_api;
 
 
 
 
 
 
201
  }
202
 
203
  public function register_sync_verbs( $sync_api ) {
204
+ // For use by the itsec-get-everything verb as it has to run other verbs to get their details.
205
+ $this->sync_api = $sync_api;
206
+
207
+ $sync_api->register( 'itsec-get-everything', 'Ithemes_Sync_Verb_ITSEC_Get_Everything', dirname( __FILE__ ) . '/sync-verbs/itsec-get-everything.php' );
208
  }
209
 
210
  public function register_modules() {
256
 
257
  static $this_plugin;
258
 
 
 
259
  if ( empty( $this_plugin ) ) {
260
  $this_plugin = str_replace( WP_PLUGIN_DIR . '/', '', self::get_plugin_file() );
261
  }
280
  */
281
  public function add_plugin_meta_links( $meta, $plugin_file ) {
282
 
 
283
  $plugin_base = str_replace( WP_PLUGIN_DIR . '/', '', self::get_plugin_file() );
284
 
285
  if ( $plugin_base == $plugin_file ) {
298
  *
299
  * @return void
300
  */
301
+ public function modify_admin_bar( $wp_admin_bar ) {
 
 
302
 
303
  if ( ! ITSEC_Core::current_user_can_manage() ) {
304
  return;
305
  }
306
 
307
  // Add the Parent link.
308
+ $wp_admin_bar->add_node(
309
  array(
310
  'title' => __( 'Security', 'better-wp-security' ),
311
  'href' => self::get_settings_page_url(),
313
  )
314
  );
315
 
316
+ $wp_admin_bar->add_node(
317
  array(
318
+ 'parent' => 'itsec_admin_bar_menu',
319
  'title' => __( 'Settings', 'better-wp-security' ),
320
  'href' => self::get_settings_page_url(),
321
+ 'id' => 'itsec_admin_bar_settings',
322
  )
323
  );
324
 
325
+ $wp_admin_bar->add_node(
326
  array(
327
+ 'parent' => 'itsec_admin_bar_menu',
328
  'title' => __( 'Security Check', 'better-wp-security' ),
329
  'href' => self::get_security_check_page_url(),
330
+ 'id' => 'itsec_admin_bar_security_check',
331
  )
332
  );
333
 
334
+ $wp_admin_bar->add_node(
335
  array(
336
+ 'parent' => 'itsec_admin_bar_menu',
337
  'title' => __( 'Logs', 'better-wp-security' ),
338
  'href' => self::get_logs_page_url(),
339
+ 'id' => 'itsec_admin_bar_logs',
340
  )
341
  );
342
  }
350
  */
351
  public function do_upgrade() {
352
 
 
 
353
  //require plugin setup information
354
  if ( ! class_exists( 'ITSEC_Setup' ) ) {
355
  require( self::get_core_dir() . '/class-itsec-setup.php' );
468
  */
469
  public function save_plugin_data() {
470
 
 
 
471
  $save_data = false; //flag to avoid saving data if we don't have to
472
 
473
  $plugin_data = get_site_option( 'itsec_data' );
core/class-itsec-lib.php CHANGED
@@ -517,6 +517,14 @@ final class ITSEC_Lib {
517
  $whitelisted_ips[] = ITSEC_Lib::get_ip(); //add current user ip to whitelist
518
  }
519
 
 
 
 
 
 
 
 
 
520
  foreach ( $whitelisted_ips as $whitelisted_ip ) {
521
  if ( ITSEC_Lib_IP_Tools::intersect( $ip, ITSEC_Lib_IP_Tools::ip_wild_to_ip_cidr( $whitelisted_ip ) ) ) {
522
  return true;
@@ -899,4 +907,46 @@ final class ITSEC_Lib {
899
  return 'http://www.traceip.net/?query=' . urlencode( $ip );
900
  }
901
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
902
  }
517
  $whitelisted_ips[] = ITSEC_Lib::get_ip(); //add current user ip to whitelist
518
  }
519
 
520
+ if ( ! empty( $_SERVER['SERVER_ADDR'] ) ) {
521
+ $whitelisted_ips[] = $_SERVER['SERVER_ADDR'];
522
+ }
523
+
524
+ if ( ! empty( $_SERVER['LOCAL_ADDR'] ) ) {
525
+ $whitelisted_ips[] = $_SERVER['LOCAL_ADDR'];
526
+ }
527
+
528
  foreach ( $whitelisted_ips as $whitelisted_ip ) {
529
  if ( ITSEC_Lib_IP_Tools::intersect( $ip, ITSEC_Lib_IP_Tools::ip_wild_to_ip_cidr( $whitelisted_ip ) ) ) {
530
  return true;
907
  return 'http://www.traceip.net/?query=' . urlencode( $ip );
908
  }
909
  }
910
+
911
+ public static function handle_wp_login_failed( $username ) {
912
+ $authentication_types = array();
913
+
914
+ if ( isset( $_SERVER['HTTP_AUTHORIZATION'] ) ) {
915
+ $http_auth_type = substr( $_SERVER['HTTP_AUTHORIZATION'], 0, 6 );
916
+
917
+ if ( 'Basic ' === $http_auth_type ) {
918
+ $authentication_types[] = 'header_http_basic_auth';
919
+ } else if ( 'OAuth ' === $http_auth_type ) {
920
+ $authentication_types[] = 'header_http_oauth';
921
+ }
922
+ }
923
+
924
+ if ( isset( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) ) {
925
+ $authentication_types[] = 'header_http_basic_auth';
926
+ }
927
+
928
+ if ( ! empty( $_GET['oauth_consumer_key'] ) ) {
929
+ $authentication_types[] = 'query_oauth';
930
+ }
931
+
932
+ if ( ! empty( $_POST['oauth_consumer_key'] ) ) {
933
+ $authentication_types[] = 'post_oauth';
934
+ }
935
+
936
+ if ( defined('XMLRPC_REQUEST') && XMLRPC_REQUEST ) {
937
+ $source = 'xmlrpc';
938
+ $authentication_types = array( 'username_and_password' );
939
+ } else if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
940
+ $source = 'rest_api';
941
+ $authentication_types[] = 'cookie';
942
+ } else {
943
+ $source = 'wp-login.php';
944
+ $authentication_types = array( 'username_and_password' );
945
+ }
946
+
947
+ $details = compact( 'source', 'authentication_types' );
948
+ $details = apply_filters( 'itsec-filter-failed-login-details', $details );
949
+
950
+ do_action( 'itsec-handle-failed-login', $username, $details );
951
+ }
952
  }
core/class-itsec-lockout.php CHANGED
@@ -45,8 +45,8 @@ final class ITSEC_Lockout {
45
  //Register Logger
46
  add_filter( 'itsec_logger_modules', array( $this, 'register_logger' ) );
47
 
48
- //Register Sync
49
- add_filter( 'itsec_sync_modules', array( $this, 'register_sync' ) );
50
 
51
  add_action( 'itsec-settings-page-init', array( $this, 'init_settings_page' ) );
52
  add_action( 'itsec-logs-page-init', array( $this, 'init_settings_page' ) );
@@ -785,30 +785,33 @@ final class ITSEC_Lockout {
785
  }
786
 
787
  /**
788
- * Register Lockouts for Sync
789
  *
790
- * @param array $sync_modules array of logger modules
791
  *
792
- * @return array array of logger modules
793
  */
794
- public function register_sync( $sync_modules ) {
795
-
796
- $sync_modules['lockout'] = array(
797
- 'verbs' => array(
798
- 'itsec-get-lockouts' => 'Ithemes_Sync_Verb_ITSEC_Get_Lockouts',
799
- 'itsec-release-lockout' => 'Ithemes_Sync_Verb_ITSEC_Release_Lockout',
800
- 'itsec-get-temp-whitelist' => 'Ithemes_Sync_Verb_ITSEC_Get_Temp_Whitelist',
801
- 'itsec-set-temp-whitelist' => 'Ithemes_Sync_Verb_ITSEC_Set_Temp_Whitelist',
802
- ),
803
- 'everything' => array(
804
- 'itsec-get-lockouts',
805
- 'itsec-get-temp-whitelist',
806
- ),
807
- 'path' => dirname( __FILE__ ),
808
- );
809
 
810
- return $sync_modules;
 
 
 
 
 
 
 
 
 
 
 
811
 
 
812
  }
813
 
814
  /**
45
  //Register Logger
46
  add_filter( 'itsec_logger_modules', array( $this, 'register_logger' ) );
47
 
48
+ add_action( 'ithemes_sync_register_verbs', array( $this, 'register_sync_verbs' ) );
49
+ add_filter( 'itsec-filter-itsec-get-everything-verbs', array( $this, 'register_sync_get_everything_verbs' ) );
50
 
51
  add_action( 'itsec-settings-page-init', array( $this, 'init_settings_page' ) );
52
  add_action( 'itsec-logs-page-init', array( $this, 'init_settings_page' ) );
785
  }
786
 
787
  /**
788
+ * Register verbs for Sync.
789
  *
790
+ * @since 3.6.0
791
  *
792
+ * @param Ithemes_Sync_API Sync API object.
793
  */
794
+ public function register_sync_verbs( $api ) {
795
+ $api->register( 'itsec-get-lockouts', 'Ithemes_Sync_Verb_ITSEC_Get_Lockouts', dirname( __FILE__ ) . '/sync-verbs/itsec-get-lockouts.php' );
796
+ $api->register( 'itsec-release-lockout', 'Ithemes_Sync_Verb_ITSEC_Release_Lockout', dirname( __FILE__ ) . '/sync-verbs/itsec-release-lockout.php' );
797
+ $api->register( 'itsec-get-temp-whitelist', 'Ithemes_Sync_Verb_ITSEC_Get_Temp_Whitelist', dirname( __FILE__ ) . '/sync-verbs/itsec-get-temp-whitelist.php' );
798
+ $api->register( 'itsec-set-temp-whitelist', 'Ithemes_Sync_Verb_ITSEC_Set_Temp_Whitelist', dirname( __FILE__ ) . '/sync-verbs/itsec-set-temp-whitelist.php' );
799
+ }
 
 
 
 
 
 
 
 
 
800
 
801
+ /**
802
+ * Filter to add verbs to the response for the itsec-get-everything verb.
803
+ *
804
+ * @since 3.6.0
805
+ *
806
+ * @param array Array of verbs.
807
+ *
808
+ * @return array Array of verbs.
809
+ */
810
+ public function register_sync_get_everything_verbs( $verbs ) {
811
+ $verbs['lockout'][] = 'itsec-get-lockouts';
812
+ $verbs['lockout'][] = 'itsec-get-temp-whitelist';
813
 
814
+ return $verbs;
815
  }
816
 
817
  /**
core/class-itsec-sync.php DELETED
@@ -1,89 +0,0 @@
1
- <?php
2
- /**
3
- * Handles the abstraction of sync integration.
4
- *
5
- * Registers modules with sync verbs and loads appropriate verb classes where applicable.
6
- *
7
- * @package iThemes_Security
8
- *
9
- * @since 4.0.0
10
- */
11
- final class ITSEC_Sync {
12
-
13
- /**
14
- * The module's that have registered with sync
15
- *
16
- * @since 4.1.0
17
- * @access private
18
- * @var array
19
- */
20
- private $sync_modules = false;
21
-
22
- /**
23
- * Loads sync modules
24
- *
25
- * Executes primary file actions at plugins_loaded.
26
- *
27
- * @since 4.1.0
28
- *
29
- * @return ITSEC_Sync
30
- */
31
- public function __construct() {}
32
-
33
- /**
34
- * Returns all modules registered with Sync.
35
- *
36
- * Returns an array of all modules containing sync verbs.
37
- *
38
- * @since 4.1.0
39
- *
40
- * @return array sync module registrations
41
- */
42
- public function get_modules() {
43
- if ( is_array( $this->sync_modules ) ) {
44
- return $this->sync_modules;
45
- }
46
-
47
- $this->sync_modules = apply_filters( 'itsec_sync_modules', array() );
48
-
49
- if ( ! is_array( $this->sync_modules ) ) {
50
- $this->sync_modules = array();
51
- }
52
-
53
- return $this->sync_modules;
54
-
55
- }
56
-
57
- /**
58
- * Register verbs for iThemes Sync.
59
- *
60
- * Registers all verbs for a given module.
61
- *
62
- * @since 4.1.0
63
- *
64
- * @param object $api iThemes Sync Object
65
- *
66
- * @return void
67
- */
68
- public function register_verbs( $api ) {
69
- $modules = $this->get_modules();
70
-
71
- foreach ( $modules as $module ) {
72
-
73
- if ( isset( $module['verbs'] ) && isset( $module['path'] ) ) {
74
-
75
- foreach ( $module['verbs'] as $name => $class ) {
76
-
77
- $api->register( $name, $class, trailingslashit( $module['path'] ) . 'class-ithemes-sync-verb-' . $name . '.php' );
78
-
79
- }
80
-
81
- }
82
-
83
- }
84
-
85
- $api->register( 'itsec-get-everything', 'Ithemes_Sync_Verb_ITSEC_Get_Everything', dirname( __FILE__ ) . '/class-ithemes-sync-verb-itsec-get-everything.php' );
86
-
87
- }
88
-
89
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/history.txt CHANGED
@@ -481,3 +481,12 @@
481
  2.9.0 - 2016-12-28 - Chris Jean
482
  Updated Feature: Updated the "REST API" feature in the WordPress Tweaks section. The feature now has proper support for protecting privacy on your site without preventing the REST API from functioning.
483
  Enhancement: Updated Security Check to enforce setting the "REST API" setting to "Restricted Access".
 
 
 
 
 
 
 
 
 
481
  2.9.0 - 2016-12-28 - Chris Jean
482
  Updated Feature: Updated the "REST API" feature in the WordPress Tweaks section. The feature now has proper support for protecting privacy on your site without preventing the REST API from functioning.
483
  Enhancement: Updated Security Check to enforce setting the "REST API" setting to "Restricted Access".
484
+ 3.0.0 - 2017-02-07 - Chris Jean
485
+ Enhancement: Added logging for failed two-factor, OAuth, and REST API authentications.
486
+ Enhancement: Added logging details about the source of login failures and the type of authentication that failed.
487
+ Enhancement: Due to improvements in tracking authentication failures, brute force attempts using alternate authentication methods are more reliably found and blocked.
488
+ Enhancement: The server's IP is treated as whitelisted and will not be considered for lockouts or bans.
489
+ Enhancement: Reduced memory usage when creating a backup.
490
+ Enhancement: Changed log entry description of "IP Flagged as bad by iThemes IPCheck" to "IP Flagged by Network Brute Force Protection". This should help clarify the meaning of the log entry.
491
+ Enhancement: Improved efficiency of the Network Brute Force Protection feature.
492
+ Bug Fix: Fixed bug that prevented Network Brute Force Protection from working properly on some sites.
core/modules/away-mode/class-itsec-away-mode.php CHANGED
@@ -3,14 +3,15 @@
3
  final class ITSEC_Away_Mode {
4
 
5
  public function run() {
 
6
 
7
  //Execute away mode functions on admin init
8
  add_filter( 'itsec_logger_modules', array( $this, 'register_logger' ) );
9
  add_action( 'itsec_admin_init', array( $this, 'run_active_check' ) );
10
  add_action( 'login_init', array( $this, 'run_active_check' ) );
11
 
12
- //Register Sync
13
- add_filter( 'itsec_sync_modules', array( $this, 'register_sync' ) );
14
 
15
  }
16
 
@@ -122,25 +123,29 @@ final class ITSEC_Away_Mode {
122
  }
123
 
124
  /**
125
- * Register Lockouts for Sync
126
  *
127
- * @param array $sync_modules array of logger modules
128
  *
129
- * @return array array of logger modules
130
  */
131
- public function register_sync( $sync_modules ) {
132
-
133
- $sync_modules['away_mode'] = array(
134
- 'verbs' => array(
135
- 'itsec-get-away-mode' => 'Ithemes_Sync_Verb_ITSEC_Get_Away_Mode',
136
- 'itsec-override-away-mode' => 'Ithemes_Sync_Verb_ITSEC_Override_Away_Mode'
137
- ),
138
- 'everything' => 'itsec-get-away-mode',
139
- 'path' => dirname( __FILE__ ),
140
- );
141
 
142
- return $sync_modules;
 
 
 
 
 
 
 
 
 
 
143
 
 
144
  }
145
-
146
  }
3
  final class ITSEC_Away_Mode {
4
 
5
  public function run() {
6
+ return;
7
 
8
  //Execute away mode functions on admin init
9
  add_filter( 'itsec_logger_modules', array( $this, 'register_logger' ) );
10
  add_action( 'itsec_admin_init', array( $this, 'run_active_check' ) );
11
  add_action( 'login_init', array( $this, 'run_active_check' ) );
12
 
13
+ add_action( 'ithemes_sync_register_verbs', array( $this, 'register_sync_verbs' ) );
14
+ add_filter( 'itsec-filter-itsec-get-everything-verbs', array( $this, 'register_sync_get_everything_verbs' ) );
15
 
16
  }
17
 
123
  }
124
 
125
  /**
126
+ * Register verbs for Sync.
127
  *
128
+ * @since 3.6.0
129
  *
130
+ * @param Ithemes_Sync_API Sync API object.
131
  */
132
+ public function register_sync_verbs( $api ) {
133
+ $api->register( 'itsec-get-away-mode', 'Ithemes_Sync_Verb_ITSEC_Get_Away_Mode', dirname( __FILE__ ) . '/sync-verbs/itsec-get-away-mode.php' );
134
+ $api->register( 'itsec-override-away-mode', 'Ithemes_Sync_Verb_ITSEC_Override_Away_Mode', dirname( __FILE__ ) . '/sync-verbs/itsec-override-away-mode.php' );
135
+ }
 
 
 
 
 
 
136
 
137
+ /**
138
+ * Filter to add verbs to the response for the itsec-get-everything verb.
139
+ *
140
+ * @since 3.6.0
141
+ *
142
+ * @param array Array of verbs.
143
+ *
144
+ * @return array Array of verbs.
145
+ */
146
+ public function register_sync_get_everything_verbs( $verbs ) {
147
+ $verbs['away_mode'][] = 'itsec-get-away-mode';
148
 
149
+ return $verbs;
150
  }
 
151
  }
core/modules/away-mode/sync-verbs/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden.
core/modules/away-mode/{class-ithemes-sync-verb-itsec-get-away-mode.php → sync-verbs/itsec-get-away-mode.php} RENAMED
File without changes
core/modules/away-mode/{class-ithemes-sync-verb-itsec-override-away-mode.php → sync-verbs/itsec-override-away-mode.php} RENAMED
File without changes
core/modules/backup/class-itsec-backup.php CHANGED
@@ -83,28 +83,26 @@ class ITSEC_Backup {
83
  * @return mixed false on error or nothing
84
  */
85
  public function do_backup( $one_time = false ) {
86
- ITSEC_Lib::set_minimum_memory_limit( '256M' );
87
-
88
  $itsec_files = ITSEC_Core::get_itsec_files();
89
 
90
- if ( $itsec_files->get_file_lock( 'backup' ) ) {
 
 
91
 
92
- $this->execute_backup( $one_time );
93
 
94
- $itsec_files->release_file_lock( 'backup' );
 
 
95
 
96
- switch ( $this->settings['method'] ) {
97
 
98
- case 0:
99
- return __( 'Backup complete. The backup was sent to the selected email recipients and was saved locally.', 'better-wp-security' );
100
- case 1:
101
- return __( 'Backup complete. The backup was sent to the selected email recipients.', 'better-wp-security' );
102
- default:
103
- return __( 'Backup complete. The backup was saved locally.', 'better-wp-security' );
104
 
105
- }
106
- } else {
107
- return new WP_Error( 'itsec-backup-do-backup-already-running', __( 'Unable to create a backup at this time since a backup is currently being created. If you wish to create an additional backup, please wait a few minutes before trying again.', 'better-wp-security' ) );
108
  }
109
  }
110
 
@@ -120,229 +118,193 @@ class ITSEC_Backup {
120
  * @return void
121
  */
122
  private function execute_backup( $one_time = false ) {
 
123
 
124
- global $wpdb, $itsec_globals, $itsec_logger;
125
 
126
- //get all of the tables
127
- if ( isset( $this->settings['all_sites'] ) && true === $this->settings['all_sites'] ) {
128
 
129
- $tables = $wpdb->get_results( 'SHOW TABLES', ARRAY_N ); //retrieve a list of all tables in the DB
130
-
131
- } else {
132
 
133
- $tables = $wpdb->get_results( 'SHOW TABLES LIKE "' . $wpdb->base_prefix . '%"', ARRAY_N ); //retrieve a list of all tables for this WordPress installation
 
134
 
 
 
 
 
135
  }
136
 
137
- $return = '';
138
 
139
- //cycle through each table
140
- foreach ( $tables as $table ) {
 
141
 
142
- $num_fields = sizeof( $wpdb->get_results( 'DESCRIBE `' . $table[0] . '`;' ) );
143
 
144
- $return .= 'DROP TABLE IF EXISTS `' . $table[0] . '`;';
 
 
145
 
146
- $row2 = $wpdb->get_row( 'SHOW CREATE TABLE `' . $table[0] . '`;', ARRAY_N );
147
 
148
- $return .= PHP_EOL . PHP_EOL . $row2[1] . ";" . PHP_EOL . PHP_EOL;
 
 
 
 
 
 
149
 
150
- if ( ! in_array( substr( $table[0], strlen( $wpdb->prefix ) ), $this->settings['exclude'] ) ) {
 
 
 
 
 
 
 
 
 
151
 
152
- $result = $wpdb->get_results( 'SELECT * FROM `' . $table[0] . '`;', ARRAY_N );
153
 
154
- foreach ( $result as $row ) {
155
 
156
- $return .= 'INSERT INTO `' . $table[0] . '` VALUES(';
 
157
 
158
- for ( $j = 0; $j < $num_fields; $j ++ ) {
 
159
 
160
- $row[$j] = addslashes( $row[$j] );
161
- $row[$j] = preg_replace( '#' . PHP_EOL . '#', "\n", $row[$j] );
162
 
 
163
  if ( isset( $row[$j] ) ) {
 
164
 
165
- $return .= '"' . $row[$j] . '"';
 
 
166
 
 
167
  } else {
168
-
169
- $return .= '""';
170
-
171
  }
172
 
173
  if ( $j < ( $num_fields - 1 ) ) {
174
- $return .= ',';
175
  }
176
-
177
  }
178
 
179
- $return .= ");" . PHP_EOL;
180
 
 
 
 
 
 
 
 
181
  }
182
 
183
  }
184
 
185
- $return .= PHP_EOL . PHP_EOL;
186
 
187
  }
188
 
189
- $return .= PHP_EOL . PHP_EOL;
190
-
191
- //save file
192
- $file = 'backup-' . substr( sanitize_title( get_bloginfo( 'name' ) ), 0, 20 ) . '-' . current_time( 'Ymd-His' ) . '-' . wp_generate_password( 30, false );
193
-
194
- require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-directory.php' );
195
-
196
- $dir = $this->settings['location'];
197
- ITSEC_Lib_Directory::create( $dir );
198
-
199
-
200
- $fileext = '.sql';
201
-
202
- $handle = @fopen( $dir . '/' . $file . '.sql', 'w+' );
203
-
204
- @fwrite( $handle, $return );
205
- @fclose( $handle );
206
-
207
- //zip the file
208
- if ( true === $this->settings['zip'] ) {
209
 
 
210
  if ( ! class_exists( 'PclZip' ) ) {
211
  require( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
212
  }
213
 
214
- $zip = new PclZip( $dir . '/' . $file . '.zip' );
215
-
216
- if ( 0 != $zip->create( $dir . '/' . $file . '.sql', PCLZIP_OPT_REMOVE_PATH, $dir ) ) {
217
-
218
- //delete .sql and keep zip
219
- @unlink( $dir . '/' . $file . '.sql' );
220
-
221
- $fileext = '.zip';
222
 
 
 
 
223
  }
224
-
225
  }
226
 
227
  if ( 2 !== $this->settings['method'] || true === $one_time ) {
228
- require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-mail.php' );
229
- $mail = new ITSEC_Mail();
230
- $mail->add_header( esc_html__( 'Database Backup', 'better-wp-security' ), sprintf( wp_kses( __( 'Site Database Backup for <b>%s</b>', 'better-wp-security' ), array( 'b' => array() ) ), date_i18n( get_option( 'date_format' ) ) ) );
231
- $mail->add_info_box( esc_html__( 'Attached is the database backup file for your site.', 'better-wp-security' ), 'attachment' );
232
-
233
-
234
- $mail->add_section_heading( esc_html__( 'Website', 'better-wp-security' ) );
235
- $mail->add_text( esc_html( network_home_url() ) );
236
-
237
- $mail->add_section_heading( esc_html__( 'Date', 'better-wp-security' ) );
238
- $mail->add_text( esc_html( date_i18n( get_option( 'date_format' ) ) ) );
239
-
240
- $mail->add_footer();
241
-
242
-
243
- $recipients = ITSEC_Modules::get_setting( 'global', 'backup_email' );
244
- $mail->set_recipients( $recipients );
245
-
246
- $subject = sprintf( esc_html__( '[%s] Database Backup', 'better-wp-security' ), esc_url( network_home_url() ) );
247
- $subject = apply_filters( 'itsec_backup_email_subject', $subject );
248
- $mail->set_subject( $subject, false );
249
-
250
- $mail->add_attachment( "$dir/$file$fileext" );
251
-
252
- $mail_success = $mail->send();
253
  }
254
 
255
  if ( 1 === $this->settings['method'] ) {
 
 
 
256
 
257
- @unlink( $dir . '/' . $file . $fileext );
258
-
259
- } else {
260
-
261
- $retain = isset( $this->settings['retain'] ) ? absint( $this->settings['retain'] ) : 0;
262
-
263
- //delete extra files
264
- if ( 0 < $retain ) {
265
-
266
- $files = scandir( $dir, 1 );
267
-
268
  $count = 0;
269
 
270
- if ( is_array( $files ) && 0 < count( $files ) ) {
271
-
272
- foreach ( $files as $file ) {
273
-
274
- if ( strstr( $file, 'backup' ) ) {
275
-
276
- if ( $count >= $retain ) {
277
- @unlink( trailingslashit( $dir ) . $file );
278
- }
279
-
280
- $count ++;
281
- }
282
 
 
 
283
  }
284
 
 
285
  }
286
-
287
  }
288
-
289
- }
290
-
291
- if ( false === $one_time ) {
292
- ITSEC_Modules::set_setting( 'backup', 'last_run', ITSEC_Core::get_current_time_gmt() );
293
  }
294
 
295
- switch ( $this->settings['method'] ) {
296
-
297
- case 0:
298
-
299
- if ( false === $mail_success ) {
300
 
301
- $status = array(
302
- 'status' => __( 'Error', 'better-wp-security' ),
303
- 'details' => __( 'saved locally but email to backup recipients could not be sent.', 'better-wp-security' ),
304
- );
305
 
306
- } else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
 
308
- $status = array(
309
- 'status' => __( 'Success', 'better-wp-security' ),
310
- 'details' => __( 'emailed to backup recipients and saved locally', 'better-wp-security' ),
311
- );
312
 
313
- }
 
314
 
315
- break;
316
- case 1:
 
317
 
318
- if ( false === $mail_success ) {
319
 
320
- $status = array(
321
- 'status' => __( 'Error', 'better-wp-security' ),
322
- 'details' => __( 'email to backup recipients could not be sent.', 'better-wp-security' ),
323
- );
324
 
325
- } else {
 
326
 
327
- $status = array(
328
- 'status' => __( 'Success', 'better-wp-security' ),
329
- 'details' => __( 'emailed to backup recipients', 'better-wp-security' ),
330
- );
331
 
332
- }
333
 
334
- break;
335
- default:
336
- $status = array(
337
- 'status' => __( 'Success', 'better-wp-security' ),
338
- 'details' => __( 'saved locally', 'better-wp-security' ),
339
- );
340
- break;
341
 
342
- }
 
 
343
 
344
- $itsec_logger->log_event( 'backup', 3, array( $status ) );
345
 
 
346
  }
347
 
348
  /**
83
  * @return mixed false on error or nothing
84
  */
85
  public function do_backup( $one_time = false ) {
 
 
86
  $itsec_files = ITSEC_Core::get_itsec_files();
87
 
88
+ if ( ! $itsec_files->get_file_lock( 'backup' ) ) {
89
+ return new WP_Error( 'itsec-backup-do-backup-already-running', __( 'Unable to create a backup at this time since a backup is currently being created. If you wish to create an additional backup, please wait a few minutes before trying again.', 'better-wp-security' ) );
90
+ }
91
 
 
92
 
93
+ ITSEC_Lib::set_minimum_memory_limit( '256M' );
94
+ $this->execute_backup( $one_time );
95
+ $itsec_files->release_file_lock( 'backup' );
96
 
97
+ switch ( $this->settings['method'] ) {
98
 
99
+ case 0:
100
+ return __( 'Backup complete. The backup was sent to the selected email recipients and was saved locally.', 'better-wp-security' );
101
+ case 1:
102
+ return __( 'Backup complete. The backup was sent to the selected email recipients.', 'better-wp-security' );
103
+ default:
104
+ return __( 'Backup complete. The backup was saved locally.', 'better-wp-security' );
105
 
 
 
 
106
  }
107
  }
108
 
118
  * @return void
119
  */
120
  private function execute_backup( $one_time = false ) {
121
+ global $wpdb, $itsec_logger;
122
 
 
123
 
 
 
124
 
125
+ require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-directory.php' );
 
 
126
 
127
+ $dir = $this->settings['location'];
128
+ $result = ITSEC_Lib_Directory::create( $dir );
129
 
130
+ if ( is_wp_error( $result ) ) {
131
+ return $result;
132
+ } else if ( ! $result ) {
133
+ return new WP_Error( 'itsec-backup-failed-to-create-backup-dir', esc_html__( 'Unable to create the backup directory due to an unknown error.', 'better-wp-security' ) );
134
  }
135
 
136
+ $file = "$dir/backup-" . substr( sanitize_title( get_bloginfo( 'name' ) ), 0, 20 ) . '-' . current_time( 'Ymd-His' ) . '-' . wp_generate_password( 30, false ) . '.sql';
137
 
138
+ if ( false === ( $fh = @fopen( $file, 'w' ) ) ) {
139
+ return new WP_Error( 'itsec-backup-failed-to-write-backup-file', esc_html__( 'Unable to write the backup file. This may be due to a permissions or disk space issue.', 'better-wp-security' ) );
140
+ }
141
 
 
142
 
143
+ if ( false === $one_time ) {
144
+ ITSEC_Modules::set_setting( 'backup', 'last_run', ITSEC_Core::get_current_time_gmt() );
145
+ }
146
 
 
147
 
148
+ if ( $this->settings['all_sites'] ) {
149
+ $tables = $wpdb->get_col( 'SHOW TABLES' );
150
+ } else {
151
+ $tables = $wpdb->get_col( 'SHOW TABLES LIKE "' . $wpdb->base_prefix . '%"' );
152
+ }
153
+
154
+ $max_rows_per_query = 1000;
155
 
156
+ foreach ( $tables as $table ) {
157
+ $create_table = $wpdb->get_var( "SHOW CREATE TABLE `$table`;", 1 ) . ';' . PHP_EOL . PHP_EOL;
158
+ $create_table = preg_replace( '/^CREATE TABLE /', 'CREATE TABLE IF NOT EXISTS ', $create_table );
159
+ @fwrite( $fh, $create_table );
160
+
161
+ if ( in_array( substr( $table, strlen( $wpdb->prefix ) ), $this->settings['exclude'] ) ) {
162
+ // User selected to exclude the data from this table.
163
+ fwrite( $fh, PHP_EOL . PHP_EOL );
164
+ continue;
165
+ }
166
 
 
167
 
168
+ $num_fields = count( $wpdb->get_results( "DESCRIBE `$table`;" ) );
169
 
170
+ $offset = 0;
171
+ $has_more_rows = true;
172
 
173
+ while ( $has_more_rows ) {
174
+ $rows = $wpdb->get_results( "SELECT * FROM `$table` LIMIT $offset, $max_rows_per_query;", ARRAY_N );
175
 
176
+ foreach ( $rows as $row ) {
177
+ $sql = "INSERT INTO `$table` VALUES (";
178
 
179
+ for ( $j = 0; $j < $num_fields; $j ++ ) {
180
  if ( isset( $row[$j] ) ) {
181
+ $row[$j] = addslashes( $row[$j] );
182
 
183
+ if ( PHP_EOL !== "\n" ) {
184
+ $row[$j] = preg_replace( '#' . PHP_EOL . '#', "\n", $row[$j] );
185
+ }
186
 
187
+ $sql .= '"' . $row[$j] . '"';
188
  } else {
189
+ $sql .= '""';
 
 
190
  }
191
 
192
  if ( $j < ( $num_fields - 1 ) ) {
193
+ $sql .= ',';
194
  }
 
195
  }
196
 
197
+ $sql .= ");" . PHP_EOL;
198
 
199
+ @fwrite( $fh, $sql );
200
+ }
201
+
202
+ if ( count( $rows ) < $max_rows_per_query ) {
203
+ $has_more_rows = false;
204
+ } else {
205
+ $offset += $max_rows_per_query;
206
  }
207
 
208
  }
209
 
210
+ @fwrite( $fh, PHP_EOL . PHP_EOL );
211
 
212
  }
213
 
214
+ @fwrite( $fh, PHP_EOL . PHP_EOL );
215
+ @fclose( $fh );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
 
217
+ if ( $this->settings['zip'] ) {
218
  if ( ! class_exists( 'PclZip' ) ) {
219
  require( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
220
  }
221
 
222
+ $zip_file = substr( $file, 0, -4 ) . '.zip';
223
+ $pclzip = new PclZip( $zip_file );
 
 
 
 
 
 
224
 
225
+ if ( 0 != $pclzip->create( $file, PCLZIP_OPT_REMOVE_PATH, $dir ) ) {
226
+ @unlink( $file );
227
+ $file = $zip_file;
228
  }
 
229
  }
230
 
231
  if ( 2 !== $this->settings['method'] || true === $one_time ) {
232
+ $mail_success = $this->send_mail( $file );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  }
234
 
235
  if ( 1 === $this->settings['method'] ) {
236
+ @unlink( $file );
237
+ } else if ( $this->settings['retain'] > 0 ) {
238
+ $files = scandir( $dir, SCANDIR_SORT_DESCENDING );
239
 
240
+ if ( is_array( $files ) && count( $files ) > 0 ) {
 
 
 
 
 
 
 
 
 
 
241
  $count = 0;
242
 
243
+ foreach ( $files as $file ) {
244
+ if ( ! strstr( $file, 'backup' ) ) {
245
+ continue;
246
+ }
 
 
 
 
 
 
 
 
247
 
248
+ if ( $count >= $this->settings['retain'] ) {
249
+ @unlink( trailingslashit( $dir ) . $file );
250
  }
251
 
252
+ $count++;
253
  }
 
254
  }
 
 
 
 
 
255
  }
256
 
 
 
 
 
 
257
 
258
+ $status = __( 'Success', 'better-wp-security' );
259
+ $details = __( 'saved locally', 'better-wp-security' );
 
 
260
 
261
+ if ( 0 === $this->settings['method'] ) {
262
+ if ( false === $mail_success ) {
263
+ $status = __( 'Error', 'better-wp-security' );
264
+ $details = __( 'saved locally but email to backup recipients could not be sent.', 'better-wp-security' );
265
+ } else {
266
+ $details = __( 'emailed to backup recipients and saved locally', 'better-wp-security' );
267
+ }
268
+ } else if ( 1 === $this->settings['method'] ) {
269
+ if ( false === $mail_success ) {
270
+ $status = __( 'Error', 'better-wp-security' );
271
+ $details = __( 'email to backup recipients could not be sent.', 'better-wp-security' );
272
+ } else {
273
+ $details = __( 'emailed to backup recipients', 'better-wp-security' );
274
+ }
275
+ }
276
 
277
+ $data = compact( 'status', 'details' );
278
+ $itsec_logger->log_event( 'backup', 3, array( $data ) );
279
+ }
 
280
 
281
+ private function send_mail( $file ) {
282
+ require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-mail.php' );
283
 
284
+ $mail = new ITSEC_Mail();
285
+ $mail->add_header( esc_html__( 'Database Backup', 'better-wp-security' ), sprintf( wp_kses( __( 'Site Database Backup for <b>%s</b>', 'better-wp-security' ), array( 'b' => array() ) ), date_i18n( get_option( 'date_format' ) ) ) );
286
+ $mail->add_info_box( esc_html__( 'Attached is the database backup file for your site.', 'better-wp-security' ), 'attachment' );
287
 
 
288
 
289
+ $mail->add_section_heading( esc_html__( 'Website', 'better-wp-security' ) );
290
+ $mail->add_text( esc_html( network_home_url() ) );
 
 
291
 
292
+ $mail->add_section_heading( esc_html__( 'Date', 'better-wp-security' ) );
293
+ $mail->add_text( esc_html( date_i18n( get_option( 'date_format' ) ) ) );
294
 
295
+ $mail->add_footer();
 
 
 
296
 
 
297
 
298
+ $recipients = ITSEC_Modules::get_setting( 'global', 'backup_email' );
299
+ $mail->set_recipients( $recipients );
 
 
 
 
 
300
 
301
+ $subject = sprintf( esc_html__( '[%s] Database Backup', 'better-wp-security' ), esc_url( network_home_url() ) );
302
+ $subject = apply_filters( 'itsec_backup_email_subject', $subject );
303
+ $mail->set_subject( $subject, false );
304
 
305
+ $mail->add_attachment( $file );
306
 
307
+ return $mail->send();
308
  }
309
 
310
  /**
core/modules/brute-force/class-itsec-brute-force.php CHANGED
@@ -9,18 +9,15 @@ class ITSEC_Brute_Force {
9
  function run() {
10
 
11
  $this->settings = ITSEC_Modules::get_settings( 'brute-force' );
12
-
13
- $this->username = null;
14
 
15
  add_action( 'wp_login', array( $this, 'wp_login' ), 10, 2 );
16
- add_action( 'wp_login_failed', array( $this, 'wp_login_failed' ), 1, 1 );
17
 
18
  add_filter( 'itsec_logger_displays', array( $this, 'itsec_logger_displays' ) ); //adds logs metaboxes
19
 
20
  add_filter( 'authenticate', array( $this, 'authenticate' ), 10, 3 );
21
  add_filter( 'itsec_lockout_modules', array( $this, 'itsec_lockout_modules' ) );
22
  add_filter( 'itsec_logger_modules', array( $this, 'itsec_logger_modules' ) );
23
- add_filter( 'xmlrpc_login_error', array( $this, 'xmlrpc_login_error' ), 10, 2 );
24
  add_filter( 'jetpack_get_default_modules', array( $this, 'jetpack_get_default_modules' ) ); //disable jetpack protect via Geoge Stephanis
25
 
26
  }
@@ -70,13 +67,6 @@ class ITSEC_Brute_Force {
70
 
71
  }
72
 
73
- //Set username for xml_rpc block
74
- if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST === true ) {
75
-
76
- $this->username = $username;
77
-
78
- }
79
-
80
  return $user;
81
 
82
  }
@@ -186,80 +176,26 @@ class ITSEC_Brute_Force {
186
  *
187
  * @return void
188
  */
189
- public function wp_login_failed( $username ) {
190
-
191
  global $itsec_lockout, $itsec_logger;
192
 
193
- if ( isset( $this->settings['auto_ban_admin'] ) && $this->settings['auto_ban_admin'] === true && trim( sanitize_text_field( $username ) ) == 'admin' ) {
194
-
195
- $itsec_logger->log_event( 'brute_force', 5, array(), ITSEC_Lib::get_ip(), sanitize_text_field( $username ) );
196
-
197
- $itsec_lockout->do_lockout( 'brute_force_admin_user', sanitize_text_field( $username ) );
198
-
199
- }
200
-
201
- if ( isset( $_POST['log'] ) && $_POST['log'] != '' && isset( $_POST['pwd'] ) && $_POST['pwd'] != '' ) {
202
-
203
- $user_id = username_exists( sanitize_text_field( $username ) );
204
-
205
- if ( $user_id === false || $user_id === null ) {
206
-
207
- $itsec_lockout->check_lockout( false, $username );
208
-
209
- } else {
210
-
211
- $itsec_lockout->check_lockout( $user_id );
212
-
213
- };
214
-
215
- $itsec_logger->log_event( 'brute_force', 5, array(), ITSEC_Lib::get_ip(), sanitize_text_field( $username ), intval( $user_id ) );
216
 
217
- $itsec_lockout->do_lockout( 'brute_force', sanitize_text_field( $username ) );
 
 
218
 
 
219
  }
220
 
221
- }
222
-
223
- /**
224
- * Execute brute force against xml_rpc login
225
- *
226
- * @Since 4.4
227
- *
228
- * @param mixed $error WordPress error
229
- *
230
- * @return mixed WordPress error
231
- */
232
- public function xmlrpc_login_error( $error ) {
233
-
234
- global $itsec_lockout, $itsec_logger;
235
-
236
- if ( isset( $this->settings['auto_ban_admin'] ) && $this->settings['auto_ban_admin'] === true && trim( sanitize_text_field( $this->username ) ) == 'admin' ) {
237
-
238
- $itsec_logger->log_event( 'brute_force', 5, array(), ITSEC_Lib::get_ip(), $this->username );
239
-
240
- $itsec_lockout->do_lockout( 'brute_force_admin_user', $this->username );
241
-
242
  } else {
 
 
243
 
244
- $user_id = username_exists( $this->username );
245
-
246
- if ( $user_id === false || $user_id === null ) {
247
-
248
- $itsec_lockout->check_lockout( false, $this->username );
249
-
250
- } else {
251
-
252
- $itsec_lockout->check_lockout( $user_id );
253
-
254
- };
255
-
256
- $itsec_logger->log_event( 'brute_force', 5, array(), ITSEC_Lib::get_ip(), $this->username, intval( $user_id ) );
257
-
258
- $itsec_lockout->do_lockout( 'brute_force', $this->username );
259
-
260
- }
261
-
262
- return $error;
263
  }
264
 
265
  /**
9
  function run() {
10
 
11
  $this->settings = ITSEC_Modules::get_settings( 'brute-force' );
 
 
12
 
13
  add_action( 'wp_login', array( $this, 'wp_login' ), 10, 2 );
14
+ add_action( 'itsec-handle-failed-login', array( $this, 'handle_failed_login' ), 10, 2 );
15
 
16
  add_filter( 'itsec_logger_displays', array( $this, 'itsec_logger_displays' ) ); //adds logs metaboxes
17
 
18
  add_filter( 'authenticate', array( $this, 'authenticate' ), 10, 3 );
19
  add_filter( 'itsec_lockout_modules', array( $this, 'itsec_lockout_modules' ) );
20
  add_filter( 'itsec_logger_modules', array( $this, 'itsec_logger_modules' ) );
 
21
  add_filter( 'jetpack_get_default_modules', array( $this, 'jetpack_get_default_modules' ) ); //disable jetpack protect via Geoge Stephanis
22
 
23
  }
67
 
68
  }
69
 
 
 
 
 
 
 
 
70
  return $user;
71
 
72
  }
176
  *
177
  * @return void
178
  */
179
+ public function handle_failed_login( $username, $details ) {
 
180
  global $itsec_lockout, $itsec_logger;
181
 
182
+ $user_id = username_exists( $username );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
+ if ( 'admin' === $username && $this->settings['auto_ban_admin'] && empty( $user_id ) ) {
185
+ $itsec_logger->log_event( 'brute_force', 5, $details, ITSEC_Lib::get_ip(), $username );
186
+ $itsec_lockout->do_lockout( 'brute_force_admin_user', $username );
187
 
188
+ return;
189
  }
190
 
191
+ if ( empty( $user_id ) ) {
192
+ $itsec_lockout->check_lockout( false, $username );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  } else {
194
+ $itsec_lockout->check_lockout( $user_id );
195
+ };
196
 
197
+ $itsec_logger->log_event( 'brute_force', 5, $details, ITSEC_Lib::get_ip(), $username, intval( $user_id ) );
198
+ $itsec_lockout->do_lockout( 'brute_force', $username );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  }
200
 
201
  /**
core/modules/file-change/class-ithemes-sync-verb-itsec-perform-file-scan.php DELETED
@@ -1,53 +0,0 @@
1
- <?php
2
- /**
3
- * Sync verb for file change detection
4
- *
5
- * Allows for file scanning to be performed remotely via iThemes Sync.
6
- *
7
- * @since 4.0.0
8
- *
9
- * @package iThemes_Security
10
- */
11
- class Ithemes_Sync_Verb_ITSEC_Perform_File_Scan extends Ithemes_Sync_Verb {
12
- /**
13
- * The name of the verb that can be called via Sync.
14
- *
15
- * @since 4.0.0
16
- * @access public
17
- * @var string
18
- */
19
- public static $name = 'itsec-perform-file-scan';
20
-
21
- /**
22
- * A description of the verb for use in Sync.
23
- *
24
- * @since 4.0.0
25
- * @access public
26
- * @var string
27
- */
28
- public static $description = 'Perform a one-time file scan';
29
-
30
- /**
31
- * Array of default arguments to process
32
- *
33
- * @since 4.0.0
34
- * @access public
35
- * @var array
36
- */
37
- public $default_arguments = array();
38
-
39
- /**
40
- * Functionaly to execute when calling the verb
41
- *
42
- * Functionality to execute when calling this verb VIA Sync.
43
- *
44
- * @since 4.0.0
45
- *
46
- * @return array response indicating result of the file scan
47
- */
48
- public function run( $arguments ) {
49
- require_once( dirname( __FILE__ ) . '/scanner.php' );
50
-
51
- return ITSEC_File_Change_Scanner::run_scan( false, true );
52
- }
53
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/modules/file-change/class-itsec-file-change.php CHANGED
@@ -38,7 +38,7 @@ class ITSEC_File_Change {
38
 
39
  add_filter( 'itsec_logger_displays', array( $this, 'itsec_logger_displays' ) ); //adds logs metaboxes
40
  add_filter( 'itsec_logger_modules', array( $this, 'itsec_logger_modules' ) );
41
- add_filter( 'itsec_sync_modules', array( $this, 'itsec_sync_modules' ) ); //register sync modules
42
 
43
 
44
  if (
@@ -58,10 +58,10 @@ class ITSEC_File_Change {
58
  }
59
 
60
  }
61
-
62
  public function run_scan() {
63
  require_once( dirname( __FILE__ ) . '/scanner.php' );
64
-
65
  return ITSEC_File_Change_Scanner::run_scan();
66
  }
67
 
@@ -164,27 +164,13 @@ class ITSEC_File_Change {
164
  }
165
 
166
  /**
167
- * Register file change detection for Sync
168
- *
169
- * Reigsters iThemes Sync verbs for the file change detection module.
170
- *
171
- * @since 4.0.0
172
  *
173
- * @param array $sync_modules array of sync modules
174
  *
175
- * @return array array of sync modules
176
  */
177
- public function itsec_sync_modules( $sync_modules ) {
178
-
179
- $sync_modules['file-change'] = array(
180
- 'verbs' => array(
181
- 'itsec-perform-file-scan' => 'Ithemes_Sync_Verb_ITSEC_Perform_File_Scan',
182
- ),
183
- 'path' => dirname( __FILE__ ),
184
- );
185
-
186
- return $sync_modules;
187
-
188
  }
189
-
190
  }
38
 
39
  add_filter( 'itsec_logger_displays', array( $this, 'itsec_logger_displays' ) ); //adds logs metaboxes
40
  add_filter( 'itsec_logger_modules', array( $this, 'itsec_logger_modules' ) );
41
+ add_action( 'ithemes_sync_register_verbs', array( $this, 'register_sync_verbs' ) );
42
 
43
 
44
  if (
58
  }
59
 
60
  }
61
+
62
  public function run_scan() {
63
  require_once( dirname( __FILE__ ) . '/scanner.php' );
64
+
65
  return ITSEC_File_Change_Scanner::run_scan();
66
  }
67
 
164
  }
165
 
166
  /**
167
+ * Register verbs for Sync.
 
 
 
 
168
  *
169
+ * @since 3.6.0
170
  *
171
+ * @param Ithemes_Sync_API Sync API object.
172
  */
173
+ public function register_sync_verbs( $api ) {
174
+ $api->register( 'itsec-perform-file-scan', 'Ithemes_Sync_Verb_ITSEC_Perform_File_Scan', dirname( __FILE__ ) . '/sync-verbs/itsec-perform-file-scan.php' );
 
 
 
 
 
 
 
 
 
175
  }
 
176
  }
core/modules/file-change/sync-verbs/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden.
core/modules/file-change/sync-verbs/itsec-perform-file-scan.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Ithemes_Sync_Verb_ITSEC_Perform_File_Scan extends Ithemes_Sync_Verb {
4
+ public static $name = 'itsec-perform-file-scan';
5
+ public static $description = 'Perform a one-time file scan';
6
+
7
+ public function run( $arguments ) {
8
+ require_once( dirname( dirname( __FILE__ ) ) . '/scanner.php' );
9
+
10
+ return ITSEC_File_Change_Scanner::run_scan( false, true );
11
+ }
12
+ }
core/modules/ipcheck/class-itsec-ipcheck.php CHANGED
@@ -11,178 +11,168 @@
11
  *
12
  */
13
  class ITSEC_IPCheck {
14
-
15
  private $endpoint = 'http://ipcheck-api.ithemes.com/?action=';
16
  private $settings;
17
 
18
- function run() {
19
-
20
- $this->settings = get_site_option( 'itsec_ipcheck' );
21
 
22
- //Execute API Brute force protection
23
- if ( isset( $this->settings['api_ban'] ) && $this->settings['api_ban'] === true ) {
24
 
25
- add_action( 'wp_login', array( $this, 'wp_login' ), 10, 2 );
26
- add_action( 'wp_login_failed', array( $this, 'wp_login_failed' ), 1, 1 );
 
 
 
27
 
28
- add_filter( 'authenticate', array( $this, 'authenticate' ), 10, 3 );
29
- add_filter( 'itsec_logger_modules', array( $this, 'itsec_logger_modules' ) );
 
30
 
 
 
31
  }
32
 
33
- }
34
-
35
- /**
36
- * Sends to lockout class when login form isn't completely filled out and process xml_rpc username
37
- *
38
- * @since 4.5
39
- *
40
- * @param object $user user or wordpress error
41
- * @param string $username username attempted
42
- * @param string $password password attempted
43
- *
44
- * @return user object or WordPress error
45
- */
46
- public function authenticate( $user, $username = '', $password = '' ) {
47
 
48
- global $itsec_logger, $itsec_lockout;
 
 
49
 
50
- //Execute brute force if username or password are empty
51
- if ( isset( $_POST['wp-submit'] ) && ( empty( $username ) || empty( $password ) ) ) {
52
 
53
- if ( $this->report_ip() === 1 ) {
54
 
55
- $itsec_logger->log_event( 'ipcheck', 10, array(), ITSEC_Lib::get_ip() );
 
56
 
57
- $itsec_lockout->execute_lock( false, true );
 
58
 
59
- }
 
 
 
 
60
 
 
 
61
  }
62
 
63
- return $user;
64
-
65
  }
66
 
67
  /**
68
- * Set transient for caching IPs
69
- *
70
- * @since 4.5
71
  *
72
- * @param string $ip IP Address
73
- * @param bool $status if the IP is blocked or not
74
- * @param int $time length, in seconds, to cache
75
  *
76
- * @return void
77
  */
78
- private function cache_ip( $ip, $status, $time ) {
79
-
80
- //@todo one size fits all is too long. Need to adjust time
81
- set_site_transient( 'itsec_ip_cache_' . esc_sql( $ip ), $status, $time );
82
-
83
  }
84
 
85
  /**
86
- * IP to check for blacklist
87
- *
88
- * @since 4.5
89
  *
90
- * @param string|null $ip ip to report
91
  *
92
- * @return bool true if successfully reported else false
93
  */
94
- public function check_ip( $ip = null ) {
95
-
96
- global $itsec_globals, $itsec_logger;
97
-
98
- //get current IP if needed
99
- if ( $ip === null ) {
100
-
101
- $ip = ITSEC_Lib::get_ip();
102
 
103
- } else {
 
104
 
105
- $ip = trim( sanitize_text_field( $ip ) );
106
 
107
- }
108
 
109
- if ( ITSEC_Lib::is_ip_whitelisted( $ip ) ) {
110
  return false;
111
  }
112
 
113
- //See if we've checked this IP in the last hour
114
- $cache_check = get_site_transient( 'itsec_ip_cache_' . esc_sql( $ip ) );
115
 
116
- if ( is_array( $cache_check ) && isset( $cache_check['status'] ) ) {
117
- return $cache_check['status'];
118
  }
119
 
120
- $action = 'check-ip';
121
 
122
- if ( ITSEC_Lib_IP_Tools::validate( $ip ) ) { //verify IP address is valid
123
-
124
- if ( ! isset( $this->settings['api_key'] ) || ! isset( $this->settings['api_secret'] ) ) {
125
- return false; //invalid key or secret
126
- }
127
-
128
- $args = json_encode(
129
- array(
130
- 'apikey' => $this->settings['api_key'], //the api key
131
- 'behavior' => 'brute-force-login', //type of behanvior we're reporting
132
- 'ip' => $ip, //the ip to report
133
- 'site' => home_url( '', 'http' ), //the current site URL
134
- 'timestamp' => $itsec_globals['current_time_gmt'], //current time (GMT)
135
- )
136
- );
137
 
138
- //Build the request parameters
139
- $request = array(
140
- 'body' => array(
141
- 'request' => $args,
142
- 'signature' => $this->hmac_sha1( $this->settings['api_secret'], $action . $args ),
143
- ),
144
- );
145
 
146
- $response = wp_remote_post( $this->endpoint . $action, $request );
147
 
148
- //Make sure the request was valid and has a valid body
149
- if ( ! is_wp_error( $response ) && isset( $response['body'] ) ) {
 
 
 
 
 
 
 
150
 
151
- $response = json_decode( $response['body'], true );
152
 
153
- if ( is_array( $response ) && isset( $response['success'] ) && $response['success'] == true ) {
 
 
 
 
 
 
 
 
154
 
155
- $cache = isset( $response['cache_ttl'] ) ? absint( $response['cache_ttl'] ) : 3600;
 
 
 
 
 
156
 
157
- if ( isset( $response['block'] ) && $response['block'] == true ) {
158
 
159
- $expiration = date( 'Y-m-d H:i:s', $itsec_globals['current_time'] + $cache );
160
- $expiration_gmt = date( 'Y-m-d H:i:s', $itsec_globals['current_time_gmt'] + $cache );
161
 
162
- $itsec_logger->log_event( 'lockout', 10, array(
163
- 'expires' => $expiration, 'expires_gmt' => $expiration_gmt, 'type' => 'host'
164
- ), $ip );
165
 
166
- $this->cache_ip( $ip, array( 'status' => true ), $cache );
167
 
168
- return true; //API reports IP is blocked
169
 
170
- } else {
 
 
171
 
172
- $this->cache_ip( $ip, array( 'status' => false ), $cache );
173
 
174
- return false; //API reports IP is not blocked or no report (default to no block)
175
 
176
- }
177
 
178
- }
 
 
 
 
 
179
 
180
- }
181
 
 
182
  }
183
 
184
  return false;
185
-
186
  }
187
 
188
  /**
@@ -198,21 +188,16 @@ class ITSEC_IPCheck {
198
  * @return string base64 encoded hmac
199
  */
200
  private function hmac_sha1( $key, $data ) {
201
-
202
  if ( strlen( $key ) > 64 ) {
203
  $key = pack( 'H*', sha1( $key ) );
204
  }
205
 
206
  $key = str_pad( $key, 64, chr( 0x00 ) );
207
-
208
  $ipad = str_repeat( chr( 0x36 ), 64 );
209
-
210
  $opad = str_repeat( chr( 0x5c ), 64 );
211
-
212
  $hmac = pack( 'H*', sha1( ( $key ^ $opad ) . pack( 'H*', sha1( ( $key ^ $ipad ) . $data ) ) ) );
213
 
214
  return base64_encode( $hmac );
215
-
216
  }
217
 
218
  /**
@@ -225,126 +210,12 @@ class ITSEC_IPCheck {
225
  * @return array array of logger modules
226
  */
227
  public function itsec_logger_modules( $logger_modules ) {
228
-
229
  $logger_modules['ipcheck'] = array(
230
  'type' => 'ipcheck',
231
- 'function' => __( 'IP Flagged as bad by iThemes IPCheck', 'better-wp-security' ),
232
  );
233
 
234
  return $logger_modules;
235
-
236
- }
237
-
238
- /**
239
- * Send offending IP to IPCheck API
240
- *
241
- * @since 4.5
242
- *
243
- * @param string|null $ip ip to report
244
- * @param int $type type of behavior to report
245
- *
246
- * @return int -1 on failure, 0 if report successful and IP not blocked, 1 if IP successful and IP blocked
247
- */
248
- public function report_ip( $ip = null, $type = 1 ) {
249
-
250
- global $itsec_globals, $itsec_logger;
251
-
252
- $action = 'report-ip';
253
-
254
- /**
255
- * Switch types or return false if no valid type
256
- *
257
- * Valid types:
258
- * 1 = invalid/failed login
259
- *
260
- */
261
- switch ( $type ) {
262
-
263
- case 1:
264
- $behavior = 'brute-force-login';
265
- break;
266
- default:
267
- return -1;
268
-
269
- }
270
-
271
- //get current IP if needed
272
- if ( $ip === null ) {
273
-
274
- $ip = ITSEC_Lib::get_ip();
275
-
276
- } else {
277
-
278
- $ip = trim( sanitize_text_field( $ip ) );
279
-
280
- }
281
-
282
- if ( ITSEC_Lib::is_ip_whitelisted( $ip ) ) {
283
- return 0;
284
- }
285
-
286
- if ( ITSEC_Lib_IP_Tools::validate( $ip ) ) { //verify IP address is valid
287
-
288
- if ( ! isset( $this->settings['api_key'] ) || ! isset( $this->settings['api_secret'] ) ) {
289
- return -1; //invalid key or secret
290
- }
291
-
292
- $args = json_encode(
293
- array(
294
- 'apikey' => $this->settings['api_key'], //the api key
295
- 'behavior' => $behavior, //type of behanvior we're reporting
296
- 'ip' => $ip, //the ip to report
297
- 'site' => home_url( '', 'http' ), //the current site URL
298
- 'timestamp' => $itsec_globals['current_time_gmt'], //current time (GMT)
299
- )
300
- );
301
-
302
- //Build the request parameters
303
- $request = array(
304
- 'body' => array(
305
- 'request' => $args,
306
- 'signature' => $this->hmac_SHA1( $this->settings['api_secret'], $action . $args ),
307
- ),
308
- );
309
-
310
- $response = wp_remote_post( $this->endpoint . $action, $request );
311
-
312
- //Make sure the request was valid and has a valid body
313
- if ( ! is_wp_error( $response ) && isset( $response['body'] ) ) {
314
-
315
- $response = json_decode( $response['body'], true );
316
-
317
- if ( is_array( $response ) && isset( $response['success'] ) && $response['success'] == true ) {
318
-
319
- if ( isset( $response['block'] ) && $response['block'] == true ) {
320
-
321
- $cache = isset( $response['cache_ttl'] ) ? absint( $response['cache_ttl'] ) : 3600;
322
-
323
- $expiration = date( 'Y-m-d H:i:s', $itsec_globals['current_time'] + $cache );
324
- $expiration_gmt = date( 'Y-m-d H:i:s', $itsec_globals['current_time_gmt'] + $cache );
325
-
326
- $itsec_logger->log_event( 'lockout', 10, array(
327
- 'expires' => $expiration, 'expires_gmt' => $expiration_gmt, 'type' => 'host'
328
- ), $ip );
329
-
330
- $this->cache_ip( $ip, array( 'status' => true ), $cache );
331
-
332
- return 1; //ip report success. Just return true for now
333
-
334
- } else {
335
-
336
- return 0;
337
-
338
- }
339
-
340
- }
341
-
342
- }
343
-
344
- }
345
-
346
- return -1;
347
-
348
  }
349
 
350
  /**
@@ -355,17 +226,14 @@ class ITSEC_IPCheck {
355
  * @return void
356
  */
357
  public function wp_login() {
358
-
359
  global $itsec_logger, $itsec_lockout;
360
 
361
- if ( $this->check_ip() === true ) {
362
 
 
363
  $itsec_logger->log_event( 'ipcheck', 10, array(), ITSEC_Lib::get_ip() );
364
-
365
  $itsec_lockout->execute_lock( false, true );
366
-
367
  }
368
-
369
  }
370
 
371
  /**
@@ -375,18 +243,15 @@ class ITSEC_IPCheck {
375
  *
376
  * @return void
377
  */
378
- public function wp_login_failed() {
379
-
380
  global $itsec_logger, $itsec_lockout;
381
 
382
- if ( $this->report_ip() === 1 ) {
383
 
 
384
  $itsec_logger->log_event( 'ipcheck', 10, array(), ITSEC_Lib::get_ip() );
385
-
386
  $itsec_lockout->execute_lock( false, true );
387
-
388
  }
389
-
390
  }
391
 
392
  }
11
  *
12
  */
13
  class ITSEC_IPCheck {
 
14
  private $endpoint = 'http://ipcheck-api.ithemes.com/?action=';
15
  private $settings;
16
 
17
+ public function run() {
18
+ add_action( 'wp_login', array( $this, 'wp_login' ), 10, 2 );
19
+ add_action( 'itsec-handle-failed-login', array( $this, 'handle_failed_login' ), 10, 2 );
20
 
21
+ add_filter( 'itsec_logger_modules', array( $this, 'itsec_logger_modules' ) );
22
+ }
23
 
24
+ private function load_settings() {
25
+ if ( ! isset( $this->settings ) ) {
26
+ $this->settings = ITSEC_Modules::get_settings( 'network-brute-force' );
27
+ }
28
+ }
29
 
30
+ private function set_cache( $ip, $response ) {
31
+ $cache = $this->get_cache( $ip );
32
+ $time = ITSEC_Core::get_current_time_gmt();
33
 
34
+ if ( isset( $response['block'] ) ) {
35
+ $cache['block'] = (boolean) $response['block'];
36
  }
37
 
38
+ if ( isset( $response['cache_ttl'] ) ) {
39
+ $cache['cache_ttl'] = intval( $response['cache_ttl'] ) + $time;
40
+ } else if ( 0 === $cache['cache_ttl'] ) {
41
+ $cache['cache_ttl'] = $time + HOUR_IN_SECONDS;
42
+ }
 
 
 
 
 
 
 
 
 
43
 
44
+ if ( isset( $response['report_ttl'] ) ) {
45
+ $cache['report_ttl'] = intval( $response['report_ttl'] ) + $time;
46
+ }
47
 
48
+ $transient_time = max( $cache['cache_ttl'], $cache['report_ttl'] ) - $time;
 
49
 
 
50
 
51
+ set_site_transient( "itsec_ipcheck_$ip", $cache, $transient_time );
52
+ }
53
 
54
+ private function get_cache( $ip ) {
55
+ $cache = get_site_transient( "itsec_ipcheck_$ip" );
56
 
57
+ $defaults = array(
58
+ 'block' => false,
59
+ 'cache_ttl' => 0,
60
+ 'report_ttl' => 0,
61
+ );
62
 
63
+ if ( ! is_array( $cache ) ) {
64
+ return $defaults;
65
  }
66
 
67
+ return array_merge( $defaults, $cache );
 
68
  }
69
 
70
  /**
71
+ * Check visitor IP to see if it is banned by IPCheck.
 
 
72
  *
73
+ * @since 3.0.0
 
 
74
  *
75
+ * @return bool true if banned, false otherwise.
76
  */
77
+ private function is_ip_banned( $ip = false ) {
78
+ return $this->get_server_response( 'check-ip', $ip );
 
 
 
79
  }
80
 
81
  /**
82
+ * Report visitor IP for blacklistable-offense to IPCheck.
 
 
83
  *
84
+ * @since 3.0.0
85
  *
86
+ * @return bool true if banned, false otherwise.
87
  */
88
+ private function report_ip( $ip = false ) {
89
+ return $this->get_server_response( 'report-ip', $ip );
90
+ }
 
 
 
 
 
91
 
92
+ private function get_server_response( $action, $ip = false ) {
93
+ global $itsec_logger;
94
 
 
95
 
96
+ $this->load_settings();
97
 
98
+ if ( empty( $this->settings['api_key'] ) || empty( $this->settings['api_secret'] ) ) {
99
  return false;
100
  }
101
 
 
 
102
 
103
+ if ( false === $ip ) {
104
+ $ip = ITSEC_Lib::get_ip();
105
  }
106
 
107
+ require_once( ITSEC_Core::get_core_dir() . '/lib/class-itsec-lib-ip-tools.php' );
108
 
109
+ if ( ! ITSEC_Lib_IP_Tools::validate( $ip ) || ITSEC_Lib::is_ip_whitelisted( $ip ) ) {
110
+ return false;
111
+ }
 
 
 
 
 
 
 
 
 
 
 
 
112
 
 
 
 
 
 
 
 
113
 
114
+ $cache = $this->get_cache( $ip );
115
 
116
+ if ( 'check-ip' === $action ) {
117
+ if ( $cache['cache_ttl'] >= ITSEC_Core::get_current_time_gmt() ) {
118
+ return $cache['block'];
119
+ }
120
+ } else if ( 'report-ip' === $action ) {
121
+ if ( $cache['report_ttl'] >= ITSEC_Core::get_current_time_gmt() ) {
122
+ return $cache['block'];
123
+ }
124
+ }
125
 
 
126
 
127
+ $args = json_encode(
128
+ array(
129
+ 'apikey' => $this->settings['api_key'],
130
+ 'behavior' => 'brute-force-login',
131
+ 'ip' => $ip,
132
+ 'site' => home_url( '', 'http' ),
133
+ 'timestamp' => ITSEC_Core::get_current_time_gmt(),
134
+ )
135
+ );
136
 
137
+ $request = array(
138
+ 'body' => array(
139
+ 'request' => $args,
140
+ 'signature' => $this->hmac_sha1( $this->settings['api_secret'], $action . $args ),
141
+ ),
142
+ );
143
 
 
144
 
145
+ $response = wp_remote_post( $this->endpoint . $action, $request );
 
146
 
147
+ if ( is_wp_error( $response ) || ! isset( $response['body'] ) ) {
148
+ return false;
149
+ }
150
 
 
151
 
152
+ $response = json_decode( $response['body'], true );
153
 
154
+ if ( ! is_array( $response ) || ! isset( $response['success'] ) || ! $response['success'] ) {
155
+ return false;
156
+ }
157
 
 
158
 
159
+ $this->set_cache( $ip, $response );
160
 
161
+ $cache_seconds = isset( $response['cache_ttl'] ) ? absint( $response['cache_ttl'] ) : 3600;
162
 
163
+ if ( isset( $response['block'] ) && $response['block'] ) {
164
+ $data = array(
165
+ 'expires' => date( 'Y-m-d H:i:s', ITSEC_Core::get_current_time() + $cache_seconds ),
166
+ 'expires_gmt' => date( 'Y-m-d H:i:s', ITSEC_Core::get_current_time_gmt() + $cache_seconds ),
167
+ 'type' => 'host',
168
+ );
169
 
170
+ $itsec_logger->log_event( 'lockout', 10, $data, $ip );
171
 
172
+ return true;
173
  }
174
 
175
  return false;
 
176
  }
177
 
178
  /**
188
  * @return string base64 encoded hmac
189
  */
190
  private function hmac_sha1( $key, $data ) {
 
191
  if ( strlen( $key ) > 64 ) {
192
  $key = pack( 'H*', sha1( $key ) );
193
  }
194
 
195
  $key = str_pad( $key, 64, chr( 0x00 ) );
 
196
  $ipad = str_repeat( chr( 0x36 ), 64 );
 
197
  $opad = str_repeat( chr( 0x5c ), 64 );
 
198
  $hmac = pack( 'H*', sha1( ( $key ^ $opad ) . pack( 'H*', sha1( ( $key ^ $ipad ) . $data ) ) ) );
199
 
200
  return base64_encode( $hmac );
 
201
  }
202
 
203
  /**
210
  * @return array array of logger modules
211
  */
212
  public function itsec_logger_modules( $logger_modules ) {
 
213
  $logger_modules['ipcheck'] = array(
214
  'type' => 'ipcheck',
215
+ 'function' => __( 'IP Flagged by Network Brute Force Protection', 'better-wp-security' ),
216
  );
217
 
218
  return $logger_modules;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  }
220
 
221
  /**
226
  * @return void
227
  */
228
  public function wp_login() {
 
229
  global $itsec_logger, $itsec_lockout;
230
 
231
+ $this->load_settings();
232
 
233
+ if ( $this->settings['enable_ban'] && $this->is_ip_banned() ) {
234
  $itsec_logger->log_event( 'ipcheck', 10, array(), ITSEC_Lib::get_ip() );
 
235
  $itsec_lockout->execute_lock( false, true );
 
236
  }
 
237
  }
238
 
239
  /**
243
  *
244
  * @return void
245
  */
246
+ public function handle_failed_login( $username, $details ) {
 
247
  global $itsec_logger, $itsec_lockout;
248
 
249
+ $this->load_settings();
250
 
251
+ if ( $this->settings['enable_ban'] && $this->report_ip() ) {
252
  $itsec_logger->log_event( 'ipcheck', 10, array(), ITSEC_Lib::get_ip() );
 
253
  $itsec_lockout->execute_lock( false, true );
 
254
  }
 
255
  }
256
 
257
  }
core/modules/ipcheck/setup.php CHANGED
@@ -93,6 +93,10 @@ if ( ! class_exists( 'ITSEC_IPCheck_Setup' ) ) {
93
  ITSEC_Modules::set_settings( 'network-brute-force', $settings );
94
  }
95
  }
 
 
 
 
96
  }
97
 
98
  }
93
  ITSEC_Modules::set_settings( 'network-brute-force', $settings );
94
  }
95
  }
96
+
97
+ if ( $itsec_old_version < 4056 ) {
98
+ delete_site_option( 'itsec_ipcheck' );
99
+ }
100
  }
101
 
102
  }
core/modules/malware/class-itsec-malware.php CHANGED
@@ -3,7 +3,8 @@
3
  class ITSEC_Malware {
4
 
5
  function run() {
6
- add_filter( 'itsec_sync_modules', array( $this, 'itsec_sync_modules' ) );
 
7
 
8
  add_filter( 'itsec_logger_displays', array( $this, 'itsec_logger_displays' ) );
9
  add_filter( 'itsec_logger_modules', array( $this, 'itsec_logger_modules' ) );
@@ -11,25 +12,30 @@ class ITSEC_Malware {
11
  }
12
 
13
  /**
14
- * Register malware for Sync
15
  *
16
- * @param array $sync_modules array of malware modules
17
  *
18
- * @return array array of logger modules
19
  */
20
- public function itsec_sync_modules( $sync_modules ) {
21
-
22
- $sync_modules['malware'] = array(
23
- 'verbs' => array(
24
- 'itsec-do-malware-scan' => 'Ithemes_Sync_Verb_ITSEC_Malware_Do_Scan',
25
- 'itsec-get-malware-scan-log' => 'Ithemes_Sync_Verb_ITSEC_Get_Malware_Scan_Log',
26
- ),
27
- 'everything' => 'itsec-get-malware-scan-log',
28
- 'path' => dirname( __FILE__ ),
29
- );
30
 
31
- return $sync_modules;
 
 
 
 
 
 
 
 
 
 
32
 
 
33
  }
34
 
35
  /**
@@ -91,14 +97,14 @@ class ITSEC_Malware {
91
  public function filter_logger_data_column_details( $details, $data ) {
92
  if ( is_wp_error( $data ) || ( ! empty( $data ) && ! empty( $data['SCAN']['SITE'] ) ) ) {
93
  // Results for Sucuri scans.
94
-
95
  require_once( dirname( __FILE__ ) . '/class-itsec-malware-scan-results-template.php' );
96
-
97
  $details = "<div class='itsec-malware-scan-results-wrapper'>\n";
98
  $details .= ITSEC_Malware_Scan_Results_Template::get_html( $data, true );
99
  $details .= "</div>\n";
100
  }
101
-
102
  return $details;
103
  }
104
 
3
  class ITSEC_Malware {
4
 
5
  function run() {
6
+ add_action( 'ithemes_sync_register_verbs', array( $this, 'register_sync_verbs' ) );
7
+ add_filter( 'itsec-filter-itsec-get-everything-verbs', array( $this, 'register_sync_get_everything_verbs' ) );
8
 
9
  add_filter( 'itsec_logger_displays', array( $this, 'itsec_logger_displays' ) );
10
  add_filter( 'itsec_logger_modules', array( $this, 'itsec_logger_modules' ) );
12
  }
13
 
14
  /**
15
+ * Register verbs for Sync.
16
  *
17
+ * @since 3.6.0
18
  *
19
+ * @param Ithemes_Sync_API Sync API object.
20
  */
21
+ public function register_sync_verbs( $api ) {
22
+ $api->register( 'itsec-do-malware-scan', 'Ithemes_Sync_Verb_ITSEC_Malware_Do_Scan', dirname( __FILE__ ) . '/sync-verbs/itsec-do-malware-scan.php' );
23
+ $api->register( 'itsec-get-malware-scan-log', 'Ithemes_Sync_Verb_ITSEC_Get_Malware_Scan_Log', dirname( __FILE__ ) . '/sync-verbs/itsec-get-malware-scan-log.php' );
24
+ }
 
 
 
 
 
 
25
 
26
+ /**
27
+ * Filter to add verbs to the response for the itsec-get-everything verb.
28
+ *
29
+ * @since 3.6.0
30
+ *
31
+ * @param array Array of verbs.
32
+ *
33
+ * @return array Array of verbs.
34
+ */
35
+ public function register_sync_get_everything_verbs( $verbs ) {
36
+ $verbs['malware'][] = 'itsec-get-malware-scan-log';
37
 
38
+ return $verbs;
39
  }
40
 
41
  /**
97
  public function filter_logger_data_column_details( $details, $data ) {
98
  if ( is_wp_error( $data ) || ( ! empty( $data ) && ! empty( $data['SCAN']['SITE'] ) ) ) {
99
  // Results for Sucuri scans.
100
+
101
  require_once( dirname( __FILE__ ) . '/class-itsec-malware-scan-results-template.php' );
102
+
103
  $details = "<div class='itsec-malware-scan-results-wrapper'>\n";
104
  $details .= ITSEC_Malware_Scan_Results_Template::get_html( $data, true );
105
  $details .= "</div>\n";
106
  }
107
+
108
  return $details;
109
  }
110
 
core/modules/malware/sync-verbs/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden.
core/modules/malware/{class-ithemes-sync-verb-itsec-do-malware-scan.php → sync-verbs/itsec-do-malware-scan.php} RENAMED
@@ -3,15 +3,10 @@
3
  class Ithemes_Sync_Verb_ITSEC_Malware_Do_Scan extends Ithemes_Sync_Verb {
4
  public static $name = 'itsec-do-malware-scan';
5
  public static $description = '';
6
-
7
- public $default_arguments = array();
8
-
9
  public function run( $arguments ) {
10
- $arguments = Ithemes_Sync_Functions::merge_defaults( $arguments, $this->default_arguments );
11
-
12
- require_once( dirname( __FILE__ ) . '/class-itsec-malware-scanner.php' );
13
-
14
  return ITSEC_Malware_Scanner::scan();
15
  }
16
-
17
  }
3
  class Ithemes_Sync_Verb_ITSEC_Malware_Do_Scan extends Ithemes_Sync_Verb {
4
  public static $name = 'itsec-do-malware-scan';
5
  public static $description = '';
6
+
 
 
7
  public function run( $arguments ) {
8
+ require_once( dirname( dirname( __FILE__ ) ) . '/class-itsec-malware-scanner.php' );
9
+
 
 
10
  return ITSEC_Malware_Scanner::scan();
11
  }
 
12
  }
core/modules/malware/{class-ithemes-sync-verb-itsec-get-malware-scan-log.php → sync-verbs/itsec-get-malware-scan-log.php} RENAMED
File without changes
core/modules/security-check/scanner.php CHANGED
@@ -22,7 +22,10 @@ final class ITSEC_Security_Check_Scanner {
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' ) );
@@ -89,54 +92,6 @@ final class ITSEC_Security_Check_Scanner {
89
  self::$calls_to_action[] = ob_get_clean();
90
  }
91
 
92
- private static function enable_all_two_factor_providers() {
93
- if ( ! in_array( 'two-factor', self::$available_modules ) ) {
94
- return;
95
- }
96
-
97
-
98
- $two_factor_providers = ITSEC_Modules::get_setting( 'two-factor', 'enabled-providers' );
99
- $added_provider = false;
100
-
101
- ob_start();
102
-
103
- if ( ! in_array( 'Two_Factor_Totp', $two_factor_providers ) ) {
104
- $two_factor_providers[] = 'Two_Factor_Totp';
105
- $added_provider = true;
106
-
107
- self::open_container();
108
- echo '<p>' . __( 'Enabled the Time-Based One-Time Password (TOTP) provider for Two-Factor Authentication.', 'better-wp-security' ) . '</p>';
109
- echo '</div>';
110
- }
111
-
112
- if ( ! in_array( 'Two_Factor_Email', $two_factor_providers ) ) {
113
- $two_factor_providers[] = 'Two_Factor_Email';
114
- $added_provider = true;
115
-
116
- self::open_container();
117
- echo '<p>' . __( 'Enabled the Email provider for Two-Factor Authentication.', 'better-wp-security' ) . '</p>';
118
- echo '</div>';
119
- }
120
-
121
- if ( ! in_array( 'Two_Factor_Backup_Codes', $two_factor_providers ) ) {
122
- $two_factor_providers[] = 'Two_Factor_Backup_Codes';
123
- $added_provider = true;
124
-
125
- self::open_container();
126
- echo '<p>' . __( 'Enabled the Backup Verification Codes provider for Two-Factor Authentication.', 'better-wp-security' ) . '</p>';
127
- echo '</div>';
128
- }
129
-
130
-
131
- if ( $added_provider ) {
132
- self::$actions_taken[] = ob_get_clean();
133
-
134
- ITSEC_Modules::set_setting( 'two-factor', 'enabled-providers', $two_factor_providers );
135
-
136
- ITSEC_Response::reload_module( 'two-factor' );
137
- }
138
- }
139
-
140
  private static function enforce_setting( $module, $setting_name, $setting_value, $description ) {
141
  if ( ! in_array( $module, self::$available_modules ) ) {
142
  return;
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::enforce_setting( 'two-factor', 'available_methods', 'all', esc_html__( 'Changed the Authentication Methods Available to Users setting in Two-Factor Authentication to "All Methods".', 'better-wp-security' ) );
26
+ self::enforce_setting( 'two-factor', 'protect_user_type', 'privileged_users', esc_html__( 'Changed the User Type Protection setting in Two-Factor Authentication to "Privileged Users".', 'better-wp-security' ) );
27
+ self::enforce_setting( 'two-factor', 'protect_vulnerable_users', true, esc_html__( 'Enabled the Vulnerable User Protection setting in Two-Factor Authentication.', 'better-wp-security' ) );
28
+ self::enforce_setting( 'two-factor', 'protect_vulnerable_site', true, esc_html__( 'Enabled the Vulnerable Site Protection setting in Two-Factor Authentication.', 'better-wp-security' ) );
29
 
30
  self::enforce_activation( 'user-logging', __( 'User Logging', 'better-wp-security' ) );
31
  self::enforce_activation( 'wordpress-tweaks', __( 'WordPress Tweaks', 'better-wp-security' ) );
92
  self::$calls_to_action[] = ob_get_clean();
93
  }
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  private static function enforce_setting( $module, $setting_name, $setting_value, $description ) {
96
  if ( ! in_array( $module, self::$available_modules ) ) {
97
  return;
core/sync-verbs/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden.
core/sync-verbs/itsec-get-everything.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Ithemes_Sync_Verb_ITSEC_Get_Everything extends Ithemes_Sync_Verb {
4
+ public static $name = 'itsec-get-everything';
5
+ public static $description = 'Retrieve iThemes Security Status and other information.';
6
+
7
+ public function run( $arguments ) {
8
+ $api = ITSEC_Core::get_sync_api();
9
+ $modules = apply_filters( 'itsec-filter-itsec-get-everything-verbs', array() );
10
+
11
+ $results = array(
12
+ 'api' => '1',
13
+ );
14
+
15
+ foreach ( $modules as $name => $verbs ) {
16
+ foreach ( $verbs as $verb ) {
17
+ $results[$name][$verb] = $api->run( $verb );
18
+ }
19
+ }
20
+
21
+ return $results;
22
+ }
23
+ }
core/{class-ithemes-sync-verb-itsec-get-lockouts.php → sync-verbs/itsec-get-lockouts.php} RENAMED
File without changes
core/{class-ithemes-sync-verb-itsec-get-temp-whitelist.php → sync-verbs/itsec-get-temp-whitelist.php} RENAMED
File without changes
core/{class-ithemes-sync-verb-itsec-release-lockout.php → sync-verbs/itsec-release-lockout.php} RENAMED
File without changes
core/{class-ithemes-sync-verb-itsec-set-temp-whitelist.php → sync-verbs/itsec-set-temp-whitelist.php} RENAMED
File without changes
history.txt CHANGED
@@ -600,3 +600,12 @@
600
  Bug Fix: Removed "comodo" from the list of user agents blocked by the HackRepair.com blacklist. This ensures that Comodo's AutoSSL feature of cPanel/WHM is able to function.
601
  Updated Feature: Updated the "REST API" feature in the WordPress Tweaks section. The feature now has proper support for protecting privacy on your site without preventing the REST API from functioning.
602
  Enhancement: Updated Security Check to enforce setting the "REST API" setting to "Restricted Access".
 
 
 
 
 
 
 
 
 
600
  Bug Fix: Removed "comodo" from the list of user agents blocked by the HackRepair.com blacklist. This ensures that Comodo's AutoSSL feature of cPanel/WHM is able to function.
601
  Updated Feature: Updated the "REST API" feature in the WordPress Tweaks section. The feature now has proper support for protecting privacy on your site without preventing the REST API from functioning.
602
  Enhancement: Updated Security Check to enforce setting the "REST API" setting to "Restricted Access".
603
+ 6.1.0 - 2017-02-07 - Chris Jean
604
+ Enhancement: Added logging for failed two-factor, OAuth, and REST API authentications.
605
+ Enhancement: Added logging details about the source of login failures and the type of authentication that failed.
606
+ Enhancement: Due to improvements in tracking authentication failures, brute force attempts using alternate authentication methods are more reliably found and blocked.
607
+ Enhancement: The server's IP is treated as whitelisted and will not be considered for lockouts or bans.
608
+ Enhancement: Reduced memory usage when creating a backup.
609
+ Enhancement: Changed log entry description of "IP Flagged as bad by iThemes IPCheck" to "IP Flagged by Network Brute Force Protection". This should help clarify the meaning of the log entry.
610
+ Enhancement: Improved efficiency of the Network Brute Force Protection feature.
611
+ Bug Fix: Fixed bug that prevented Network Brute Force Protection from working properly on some sites.
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: ithemes, chrisjean, 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.5
5
- Tested up to: 4.7
6
- Stable tag: 6.0.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -188,6 +188,16 @@ Free support may be available with the help of the community in the <a href="htt
188
 
189
  == Changelog ==
190
 
 
 
 
 
 
 
 
 
 
 
191
  = 6.0.0 =
192
  * Bug Fix: Removed "comodo" from the list of user agents blocked by the HackRepair.com blacklist. This ensures that Comodo's AutoSSL feature of cPanel/WHM is able to function.
193
  * Updated Feature: Updated the "REST API" feature in the WordPress Tweaks section. The feature now has proper support for protecting privacy on your site without preventing the REST API from functioning.
@@ -1635,5 +1645,5 @@ This release is a complete rewrite from the ground up. Special thanks to Cory Mi
1635
 
1636
  == Upgrade Notice ==
1637
 
1638
- = 6.0.0 =
1639
- Version 6.0.0 adds privacy enhancement for the REST API. It is recommended for all users.
2
  Contributors: ithemes, chrisjean, 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.5
5
+ Tested up to: 4.7.2
6
+ Stable tag: 6.1.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
188
 
189
  == Changelog ==
190
 
191
+ = 6.1.0 =
192
+ * Enhancement: Added logging for failed two-factor, OAuth, and REST API authentications.
193
+ * Enhancement: Added logging details about the source of login failures and the type of authentication that failed.
194
+ * Enhancement: Due to improvements in tracking authentication failures, brute force attempts using alternate authentication methods are more reliably found and blocked.
195
+ * Enhancement: The server's IP is treated as whitelisted and will not be considered for lockouts or bans.
196
+ * Enhancement: Reduced memory usage when creating a backup.
197
+ * Enhancement: Changed log entry description of "IP Flagged as bad by iThemes IPCheck" to "IP Flagged by Network Brute Force Protection". This should help clarify the meaning of the log entry.
198
+ * Enhancement: Improved efficiency of the Network Brute Force Protection feature.
199
+ * Bug Fix: Fixed bug that prevented Network Brute Force Protection from working properly on some sites.
200
+
201
  = 6.0.0 =
202
  * Bug Fix: Removed "comodo" from the list of user agents blocked by the HackRepair.com blacklist. This ensures that Comodo's AutoSSL feature of cPanel/WHM is able to function.
203
  * Updated Feature: Updated the "REST API" feature in the WordPress Tweaks section. The feature now has proper support for protecting privacy on your site without preventing the REST API from functioning.
1645
 
1646
  == Upgrade Notice ==
1647
 
1648
+ = 6.1.0 =
1649
+ Version 6.1.0 adds various improvements to logging and brute force detection. It is recommended for all users.