iThemes Security (formerly Better WP Security) - Version 6.9.1

Version Description

  • Security Fix: Fixed display of unescaped data on logs page. Thanks to Pawe Kuryowicz from SecuRing for finding and reporting this issue.
  • Enhancement: The logging system now differentiates between WP-CLI commands, WP-Cron scheduled events, and normal page requests.
  • Bug Fix: Fixed the File Change scanner in that it previously could fail to exclude selected directories on some systems.
Download this release

Release Info

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

Code changes from version 6.9.0 to 6.9.1

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.9.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.9.1
10
  * Text Domain: better-wp-security
11
  * Network: True
12
  * License: GPLv2
core/admin-pages/css/style.css CHANGED
@@ -274,7 +274,6 @@ body.itsec-modal-open {
274
  .itsec-modal-content-footer .align-left{
275
  float: left;
276
  }
277
-
278
  .itsec-modal-content-footer .align-right{
279
  float: right;
280
  }
@@ -294,14 +293,15 @@ body.itsec-modal-open {
294
  .itsec-settings-section .itsec-setting-field {
295
  margin-bottom: 1.5em;
296
  }
297
-
298
  .itsec-settings-module-settings .form-table th {
299
  padding-left: 15px;
300
  }
301
-
302
  .itsec-settings-module-settings .itsec-highlighted-setting {
303
  background: #e5f5fa;
304
  }
 
 
 
305
 
306
 
307
 
274
  .itsec-modal-content-footer .align-left{
275
  float: left;
276
  }
 
277
  .itsec-modal-content-footer .align-right{
278
  float: right;
279
  }
293
  .itsec-settings-section .itsec-setting-field {
294
  margin-bottom: 1.5em;
295
  }
 
296
  .itsec-settings-module-settings .form-table th {
297
  padding-left: 15px;
298
  }
 
299
  .itsec-settings-module-settings .itsec-highlighted-setting {
300
  background: #e5f5fa;
301
  }
302
+ .itsec-settings-module-settings .form-table td select {
303
+ margin: 1em 0;
304
+ }
305
 
306
 
307
 
core/admin-pages/init.php CHANGED
@@ -2,8 +2,6 @@
2
 
3
 
4
  final class ITSEC_Admin_Page_Loader {
5
- private $version = 2.0;
6
-
7
  private $page_refs = array();
8
  private $page_id;
9
  private $translations = array();
@@ -34,12 +32,12 @@ final class ITSEC_Admin_Page_Loader {
34
  'translations' => $this->translations,
35
  );
36
 
37
- wp_enqueue_script( 'itsec-util-script', plugins_url( 'js/util.js', __FILE__ ), array(), $this->version, true );
38
  wp_localize_script( 'itsec-util-script', 'itsec_util', $vars );
39
  }
40
 
41
  public function add_styles() {
42
- wp_enqueue_style( 'itsec-settings-page-style', plugins_url( 'css/style.css', __FILE__ ), array(), $this->version );
43
  }
44
 
45
  private function set_translation_strings() {
2
 
3
 
4
  final class ITSEC_Admin_Page_Loader {
 
 
5
  private $page_refs = array();
6
  private $page_id;
7
  private $translations = array();
32
  'translations' => $this->translations,
33
  );
34
 
35
+ wp_enqueue_script( 'itsec-util-script', plugins_url( 'js/util.js', __FILE__ ), array(), ITSEC_Core::get_plugin_build(), true );
36
  wp_localize_script( 'itsec-util-script', 'itsec_util', $vars );
37
  }
38
 
39
  public function add_styles() {
40
+ wp_enqueue_style( 'itsec-settings-page-style', plugins_url( 'css/style.css', __FILE__ ), array(), ITSEC_Core::get_plugin_build() );
41
  }
42
 
43
  private function set_translation_strings() {
core/admin-pages/page-logs.php CHANGED
@@ -2,8 +2,6 @@
2
 
3
 
4
  final class ITSEC_Logs_Page {
5
- private $version = 1.8;
6
-
7
  private $self_url = '';
8
  private $modules = array();
9
  private $widgets = array();
@@ -54,12 +52,12 @@ final class ITSEC_Logs_Page {
54
  'translations' => $this->translations,
55
  );
56
 
57
- wp_enqueue_script( 'itsec-logs-page-script', plugins_url( 'js/logs.js', __FILE__ ), array( 'jquery-ui-dialog' ), $this->version, true );
58
  wp_localize_script( 'itsec-logs-page-script', 'itsec_page', $vars );
59
  }
60
 
61
  public function add_styles() {
62
- wp_enqueue_style( 'itsec-settings-page-style', plugins_url( 'css/style.css', __FILE__ ), array(), $this->version );
63
  wp_enqueue_style( 'wp-jquery-ui-dialog' );
64
  }
65
 
@@ -260,6 +258,16 @@ final class ITSEC_Logs_Page {
260
  $username = '';
261
  }
262
 
 
 
 
 
 
 
 
 
 
 
263
  $details = array(
264
  'module' => array(
265
  'header' => esc_html__( 'Module', 'better-wp-security' ),
@@ -287,7 +295,7 @@ final class ITSEC_Logs_Page {
287
  ),
288
  'url' => array(
289
  'header' => esc_html__( 'URL', 'better-wp-security' ),
290
- 'content' => '<code>' . esc_html( $entry['url'] ) . '</code>',
291
  ),
292
  'raw-details' => array(
293
  'header' => esc_html__( 'Raw Details', 'better-wp-security' ),
2
 
3
 
4
  final class ITSEC_Logs_Page {
 
 
5
  private $self_url = '';
6
  private $modules = array();
7
  private $widgets = array();
52
  'translations' => $this->translations,
53
  );
54
 
55
+ wp_enqueue_script( 'itsec-logs-page-script', plugins_url( 'js/logs.js', __FILE__ ), array( 'jquery-ui-dialog' ), ITSEC_Core::get_plugin_build(), true );
56
  wp_localize_script( 'itsec-logs-page-script', 'itsec_page', $vars );
57
  }
58
 
59
  public function add_styles() {
60
+ wp_enqueue_style( 'itsec-settings-page-style', plugins_url( 'css/style.css', __FILE__ ), array(), ITSEC_Core::get_plugin_build() );
61
  wp_enqueue_style( 'wp-jquery-ui-dialog' );
62
  }
63
 
258
  $username = '';
259
  }
260
 
261
+ if ( 'wp-cli' === $entry['url'] ) {
262
+ $url = esc_html__( 'WP-CLI Command', 'better-wp-security' );
263
+ } else if ( 'wp-cron' === $entry['url'] ) {
264
+ $url = esc_html__( 'WP-Cron Scheduled Task', 'better-wp-security' );
265
+ } else if ( 'unknown' === $entry['url'] ) {
266
+ $url = esc_html__( 'Unknown', 'better-wp-security' );
267
+ } else {
268
+ $url = esc_html( $entry['url'] );
269
+ }
270
+
271
  $details = array(
272
  'module' => array(
273
  'header' => esc_html__( 'Module', 'better-wp-security' ),
295
  ),
296
  'url' => array(
297
  'header' => esc_html__( 'URL', 'better-wp-security' ),
298
+ 'content' => '<code>' . $url . '</code>',
299
  ),
300
  'raw-details' => array(
301
  'header' => esc_html__( 'Raw Details', 'better-wp-security' ),
core/admin-pages/page-settings.php CHANGED
@@ -2,8 +2,6 @@
2
 
3
 
4
  final class ITSEC_Settings_Page {
5
- private $version = 2.0;
6
-
7
  private static $instance;
8
 
9
  private $self_url = '';
@@ -94,12 +92,12 @@ final class ITSEC_Settings_Page {
94
  }
95
 
96
  wp_enqueue_script( 'itsec-scrollTo', plugins_url( 'js/scrollTo.js', dirname( __FILE__ ) ), array( 'jquery' ) );
97
- wp_enqueue_script( 'itsec-settings-page-script', plugins_url( 'js/settings.js', __FILE__ ), array( 'underscore' ), $this->version, true );
98
  wp_localize_script( 'itsec-settings-page-script', 'itsec_page', $vars );
99
  }
100
 
101
  public function add_styles() {
102
- wp_enqueue_style( 'itsec-settings-page-style', plugins_url( 'css/style.css', __FILE__ ), array(), $this->version );
103
  }
104
 
105
  private function set_translation_strings() {
2
 
3
 
4
  final class ITSEC_Settings_Page {
 
 
5
  private static $instance;
6
 
7
  private $self_url = '';
92
  }
93
 
94
  wp_enqueue_script( 'itsec-scrollTo', plugins_url( 'js/scrollTo.js', dirname( __FILE__ ) ), array( 'jquery' ) );
95
+ wp_enqueue_script( 'itsec-settings-page-script', plugins_url( 'js/settings.js', __FILE__ ), array( 'underscore' ), ITSEC_Core::get_plugin_build(), true );
96
  wp_localize_script( 'itsec-settings-page-script', 'itsec_page', $vars );
97
  }
98
 
99
  public function add_styles() {
100
+ wp_enqueue_style( 'itsec-settings-page-style', plugins_url( 'css/style.css', __FILE__ ), array(), ITSEC_Core::get_plugin_build() );
101
  }
102
 
103
  private function set_translation_strings() {
core/core.php CHANGED
@@ -24,7 +24,7 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
24
  *
25
  * @access private
26
  */
27
- private $plugin_build = 4084;
28
 
29
  /**
30
  * Used to distinguish between a user modifying settings and the API modifying settings (such as from Sync
@@ -105,11 +105,15 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
105
  register_deactivation_hook( $this->plugin_file, array( 'ITSEC_Core', 'handle_deactivation' ) );
106
  register_uninstall_hook( $this->plugin_file, array( 'ITSEC_Core', 'handle_uninstall' ) );
107
 
 
 
108
  require( $this->plugin_dir . 'core/modules.php' );
 
 
 
109
  add_action( 'itsec-register-modules', array( $this, 'register_modules' ) );
110
  ITSEC_Modules::init_modules();
111
 
112
- require( $this->plugin_dir . 'core/lib.php' );
113
  require( $this->plugin_dir . 'core/lockout.php' );
114
  require( $this->plugin_dir . 'core/files.php' );
115
  require( $this->plugin_dir . 'core/notify.php' );
@@ -117,8 +121,6 @@ if ( ! class_exists( 'ITSEC_Core' ) ) {
117
  require( $this->plugin_dir . 'core/lib/class-itsec-lib-user-activity.php' );
118
  require( $this->plugin_dir . 'core/lib/class-itsec-lib-password-requirements.php' );
119
 
120
- require( $this->plugin_dir . 'core/lib/log.php' );
121
-
122
  require( $this->plugin_dir . 'core/lib/class-itsec-scheduler.php' );
123
  require( $this->plugin_dir . 'core/lib/class-itsec-job.php' );
124
 
24
  *
25
  * @access private
26
  */
27
+ private $plugin_build = 4085;
28
 
29
  /**
30
  * Used to distinguish between a user modifying settings and the API modifying settings (such as from Sync
105
  register_deactivation_hook( $this->plugin_file, array( 'ITSEC_Core', 'handle_deactivation' ) );
106
  register_uninstall_hook( $this->plugin_file, array( 'ITSEC_Core', 'handle_uninstall' ) );
107
 
108
+ require( $this->plugin_dir . 'core/lib/settings.php' );
109
+ require( $this->plugin_dir . 'core/lib/storage.php' );
110
  require( $this->plugin_dir . 'core/modules.php' );
111
+ require( $this->plugin_dir . 'core/lib.php' );
112
+ require( $this->plugin_dir . 'core/lib/log.php' );
113
+
114
  add_action( 'itsec-register-modules', array( $this, 'register_modules' ) );
115
  ITSEC_Modules::init_modules();
116
 
 
117
  require( $this->plugin_dir . 'core/lockout.php' );
118
  require( $this->plugin_dir . 'core/files.php' );
119
  require( $this->plugin_dir . 'core/notify.php' );
121
  require( $this->plugin_dir . 'core/lib/class-itsec-lib-user-activity.php' );
122
  require( $this->plugin_dir . 'core/lib/class-itsec-lib-password-requirements.php' );
123
 
 
 
124
  require( $this->plugin_dir . 'core/lib/class-itsec-scheduler.php' );
125
  require( $this->plugin_dir . 'core/lib/class-itsec-job.php' );
126
 
core/history.txt CHANGED
@@ -638,3 +638,13 @@
638
  Bug Fix: Fixed schema issue with new logs table.
639
  4.1.2 - 2018-02-12 - Chris Jean & Timothy Jacobs
640
  Bug Fix: Fixed "undefined offset" error when displaying specific migrated old log entries.
 
 
 
 
 
 
 
 
 
 
638
  Bug Fix: Fixed schema issue with new logs table.
639
  4.1.2 - 2018-02-12 - Chris Jean & Timothy Jacobs
640
  Bug Fix: Fixed "undefined offset" error when displaying specific migrated old log entries.
641
+ 4.1.3 - 2018-02-21 - Chris Jean & Timothy Jacobs
642
+ Enhancement: Cleaned up styling in settings to make some settings stand out better.
643
+ Minor: Use plugin build for cache busting assets.
644
+ Minor: Extract scheduling loop system to iThemes Security Core for future development.
645
+ Bug Fix: Cannot use object of type WP_Error as array in Malware Scanner.
646
+ Bug Fix: Reordered loading of logging class to allow for logging earlier.
647
+ 4.1.4 - 2018-03-01 - Chris Jean & Timothy Jacobs
648
+ Security Fix: Fixed display of unescaped data on logs page.
649
+ Enhancement: The logging system now differentiates between WP-CLI commands, WP-Cron scheduled events, and normal page requests.
650
+ Bug Fix: Fixed the File Change scanner in that it previously could fail to exclude selected directories on some systems.
core/lib/class-itsec-job.php CHANGED
@@ -48,6 +48,45 @@ class ITSEC_Job {
48
  $this->scheduler->schedule_once( ITSEC_Core::get_current_time_gmt() + $seconds, $this->id, $data );
49
  }
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  /**
52
  * Get the retry count for this job.
53
  *
48
  $this->scheduler->schedule_once( ITSEC_Core::get_current_time_gmt() + $seconds, $this->id, $data );
49
  }
50
 
51
+ /**
52
+ * Schedule the next loop item.
53
+ *
54
+ * @param array $data Data to provide to the next event.
55
+ */
56
+ public function schedule_next_in_loop( $data = array() ) {
57
+ if ( ! $config = $this->scheduler->get_loop( $this->get_id() ) ) {
58
+ return;
59
+ }
60
+
61
+ $data = array_merge( $this->get_data(), $data, array(
62
+ 'loop_item' => $this->data['loop_item'] + 1,
63
+ ) );
64
+
65
+ $this->scheduler->schedule_once( ITSEC_Core::get_current_time_gmt() + $config['wait'], $this->get_id(), $data );
66
+ }
67
+
68
+ /**
69
+ * Schedule the loop to start over again.
70
+ *
71
+ * @param array $data
72
+ */
73
+ public function schedule_new_loop( $data = array() ) {
74
+
75
+ if ( ! $config = $this->scheduler->get_loop( $this->get_id() ) ) {
76
+ return;
77
+ }
78
+
79
+ $start = $this->data['loop_start'];
80
+ $interval = $this->scheduler->get_schedule_interval( $config['schedule'] );
81
+ $now = ITSEC_Core::get_current_time_gmt();
82
+
83
+ $next = $start + $interval < $now ? $now + $config['wait'] : $start + $interval;
84
+
85
+ $this->scheduler->schedule_loop( $this->get_id(), $data, array(
86
+ 'fire_at' => $next,
87
+ ) );
88
+ }
89
+
90
  /**
91
  * Get the retry count for this job.
92
  *
core/lib/class-itsec-scheduler-cron.php CHANGED
@@ -183,6 +183,25 @@ class ITSEC_Scheduler_Cron extends ITSEC_Scheduler {
183
  }
184
 
185
  public function unschedule_single( $id, $data = array() ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  $data_hash = $this->hash_data( $data );
187
  $hash = $this->make_cron_hash( $id, $data );
188
 
183
  }
184
 
185
  public function unschedule_single( $id, $data = array() ) {
186
+
187
+ $options = $this->get_options();
188
+
189
+ if ( empty( $options['single'][ $id ] ) ) {
190
+ return false;
191
+ }
192
+
193
+ if ( null === $data ) {
194
+ $all_events = $options['single'][ $id ];
195
+
196
+ foreach ( $all_events as $data_hash => $event ) {
197
+ $cron_hash = md5( serialize( array( $id, $data_hash ) ) );
198
+ unset( $all_events[ $data_hash ] );
199
+ $this->unschedule_by_hash( $cron_hash );
200
+ }
201
+
202
+ return true;
203
+ }
204
+
205
  $data_hash = $this->hash_data( $data );
206
  $hash = $this->make_cron_hash( $id, $data );
207
 
core/lib/class-itsec-scheduler-page-load.php CHANGED
@@ -112,15 +112,24 @@ class ITSEC_Scheduler_Page_Load extends ITSEC_Scheduler {
112
  public function unschedule_single( $id, $data = array() ) {
113
 
114
  $options = $this->operating_data ? $this->operating_data : $this->get_options();
115
- $hash = $this->hash_data( $data );
116
 
117
- if ( isset( $options['single'][ $id ][ $hash ] ) ) {
118
- unset( $options['single'][ $id ][ $hash ] );
 
119
 
120
- return $this->set_options( $options );
 
 
 
 
 
 
 
 
 
121
  }
122
 
123
- return false;
124
  }
125
 
126
  public function get_recurring_events() {
112
  public function unschedule_single( $id, $data = array() ) {
113
 
114
  $options = $this->operating_data ? $this->operating_data : $this->get_options();
 
115
 
116
+ if ( ! isset( $options['single'][ $id ] ) ) {
117
+ return false;
118
+ }
119
 
120
+ if ( null === $data ) {
121
+ unset( $options['single'][ $id ] );
122
+ } else {
123
+ $hash = $this->hash_data( $data );
124
+
125
+ if ( ! isset( $options['single'][ $id ][ $hash ] ) ) {
126
+ return false;
127
+ }
128
+
129
+ unset( $options['single'][ $id ][ $hash ] );
130
  }
131
 
132
+ return $this->set_options( $options );
133
  }
134
 
135
  public function get_recurring_events() {
core/lib/class-itsec-scheduler.php CHANGED
@@ -14,6 +14,9 @@ abstract class ITSEC_Scheduler {
14
  /** @var array */
15
  protected $custom_schedules = array();
16
 
 
 
 
17
  /**
18
  * Schedule a recurring event.
19
  *
@@ -56,6 +59,23 @@ abstract class ITSEC_Scheduler {
56
  return $this->schedule_once( ITSEC_Core::get_current_time_gmt() + 60 * mt_rand( 1, 10 ), $id, $data );
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  /**
60
  * Is a recurring event scheduled.
61
  *
@@ -90,8 +110,8 @@ abstract class ITSEC_Scheduler {
90
  *
91
  * The data specified needs to be identical to the data the single event was scheduled with.
92
  *
93
- * @param string $id
94
- * @param array $data
95
  *
96
  * @return bool
97
  */
@@ -173,12 +193,39 @@ abstract class ITSEC_Scheduler {
173
  * Register a custom schedule.
174
  *
175
  * @param string $slug
176
- * @param int $interval
177
  */
178
  public function register_custom_schedule( $slug, $interval ) {
179
  $this->custom_schedules[ $slug ] = $interval;
180
  }
181
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  /**
183
  * Get a lock to be used for scheduling events.
184
  *
@@ -240,7 +287,7 @@ abstract class ITSEC_Scheduler {
240
  *
241
  * @return int
242
  */
243
- protected final function get_schedule_interval( $schedule ) {
244
  switch ( $schedule ) {
245
  case self::S_HOURLY:
246
  return HOUR_IN_SECONDS;
14
  /** @var array */
15
  protected $custom_schedules = array();
16
 
17
+ /** @var array */
18
+ protected $loops = array();
19
+
20
  /**
21
  * Schedule a recurring event.
22
  *
59
  return $this->schedule_once( ITSEC_Core::get_current_time_gmt() + 60 * mt_rand( 1, 10 ), $id, $data );
60
  }
61
 
62
+ /**
63
+ * Schedule an event loop.
64
+ *
65
+ * @param string $id The event ID.
66
+ * @param array $data Event data.
67
+ * @param array $opts
68
+ * - fire_at: Manually specify the first time the event should be fired.
69
+ */
70
+ public function schedule_loop( $id, $data = array(), $opts = array() ) {
71
+ $start = isset( $opts['fire_at'] ) ? $opts['fire_at'] : ITSEC_Core::get_current_time_gmt() + 60 * mt_rand( 1, 30 );
72
+
73
+ $this->schedule_once( $start, $id, array_merge( $data, array(
74
+ 'loop_start' => $start,
75
+ 'loop_item' => 1,
76
+ ) ) );
77
+ }
78
+
79
  /**
80
  * Is a recurring event scheduled.
81
  *
110
  *
111
  * The data specified needs to be identical to the data the single event was scheduled with.
112
  *
113
+ * @param string $id The event ID to unschedule.
114
+ * @param array|null $data Unschedules the event with the given data. Pass null to delete any and all events matching the ID.
115
  *
116
  * @return bool
117
  */
193
  * Register a custom schedule.
194
  *
195
  * @param string $slug
196
+ * @param int $interval
197
  */
198
  public function register_custom_schedule( $slug, $interval ) {
199
  $this->custom_schedules[ $slug ] = $interval;
200
  }
201
 
202
+ /**
203
+ * Register an event loop.
204
+ *
205
+ * This allows for splitting up a long running process across multiple page loads.
206
+ *
207
+ * @param string $id The event ID.
208
+ * @param string $schedule The schedule between loop starts. This is the maximum amount of time to wait.
209
+ * @param int $wait Time to wait in seconds between loop parts.
210
+ */
211
+ public function register_loop( $id, $schedule, $wait ) {
212
+ $this->loops[ $id ] = array(
213
+ 'schedule' => $schedule,
214
+ 'wait' => $wait,
215
+ );
216
+ }
217
+
218
+ /**
219
+ * Get the loop configuration.
220
+ *
221
+ * @param string $id
222
+ *
223
+ * @return array
224
+ */
225
+ public function get_loop( $id ) {
226
+ return isset( $this->loops[ $id ] ) ? $this->loops[ $id ] : array();
227
+ }
228
+
229
  /**
230
  * Get a lock to be used for scheduling events.
231
  *
287
  *
288
  * @return int
289
  */
290
+ final public function get_schedule_interval( $schedule ) {
291
  switch ( $schedule ) {
292
  case self::S_HOURLY:
293
  return HOUR_IN_SECONDS;
core/lib/log.php CHANGED
@@ -70,6 +70,16 @@ final class ITSEC_Log {
70
  }
71
 
72
  private static function add( $module, $code, $data, $type, $parent_id = 0 ) {
 
 
 
 
 
 
 
 
 
 
73
  $data = array(
74
  'parent_id' => $parent_id,
75
  'module' => $module,
@@ -80,7 +90,7 @@ final class ITSEC_Log {
80
  'init_timestamp' => gmdate( 'Y-m-d H:i:s', ITSEC_Core::get_current_time_gmt() ),
81
  'memory_current' => memory_get_usage(),
82
  'memory_peak' => memory_get_peak_usage(),
83
- 'url' => ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
84
  'blog_id' => get_current_blog_id(),
85
  'user_id' => get_current_user_id(),
86
  'remote_ip' => ITSEC_Lib::get_ip(),
70
  }
71
 
72
  private static function add( $module, $code, $data, $type, $parent_id = 0 ) {
73
+ if ( defined( 'WP_CLI' ) && WP_CLI ) {
74
+ $url = 'wp-cli';
75
+ } else if ( ( is_callable( 'wp_doing_cron' ) && wp_doing_cron() ) || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
76
+ $url = 'wp-cron';
77
+ } else if ( isset( $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'] ) ) {
78
+ $url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
79
+ } else {
80
+ $url = 'unknown';
81
+ }
82
+
83
  $data = array(
84
  'parent_id' => $parent_id,
85
  'module' => $module,
90
  'init_timestamp' => gmdate( 'Y-m-d H:i:s', ITSEC_Core::get_current_time_gmt() ),
91
  'memory_current' => memory_get_usage(),
92
  'memory_peak' => memory_get_peak_usage(),
93
+ 'url' => $url,
94
  'blog_id' => get_current_blog_id(),
95
  'user_id' => get_current_user_id(),
96
  'remote_ip' => ITSEC_Lib::get_ip(),
core/modules.php CHANGED
@@ -17,9 +17,6 @@ final class ITSEC_Modules {
17
  private $_settings_files_loaded = false;
18
 
19
  protected function __construct() {
20
- require_once( dirname( __FILE__ ) . '/lib/settings.php' );
21
- require_once( dirname( __FILE__ ) . '/lib/storage.php' );
22
-
23
  // Action triggered from another part of Security which runs when the settings page is loaded.
24
  add_action( 'itsec-settings-page-init', array( $this, 'load_settings_page' ) );
25
  add_action( 'itsec-logs-page-init', array( $this, 'load_settings_page' ) );
17
  private $_settings_files_loaded = false;
18
 
19
  protected function __construct() {
 
 
 
20
  // Action triggered from another part of Security which runs when the settings page is loaded.
21
  add_action( 'itsec-settings-page-init', array( $this, 'load_settings_page' ) );
22
  add_action( 'itsec-logs-page-init', array( $this, 'load_settings_page' ) );
core/modules/404-detection/logs.php CHANGED
@@ -10,7 +10,7 @@ final class ITSEC_Four_Oh_Four_Logs {
10
  $entry['module_display'] = esc_html__( '404 Detection', 'better-wp-security' );
11
 
12
  if ( 'found_404' === $entry['code'] ) {
13
- $entry['description'] = $entry['url'];
14
  }
15
 
16
  return $entry;
10
  $entry['module_display'] = esc_html__( '404 Detection', 'better-wp-security' );
11
 
12
  if ( 'found_404' === $entry['code'] ) {
13
+ $entry['description'] = esc_html( $entry['url'] );
14
  }
15
 
16
  return $entry;
core/modules/file-change/scanner.php CHANGED
@@ -68,7 +68,9 @@ final class ITSEC_File_Change_Scanner {
68
  }
69
 
70
  foreach ( $this->settings['file_list'] as $index => $path ) {
71
- $this->settings['file_list'][$index] = untrailingslashit( $path );
 
 
72
  }
73
 
74
  $this->excludes = array(
@@ -76,6 +78,13 @@ final class ITSEC_File_Change_Scanner {
76
  ITSEC_Modules::get_setting( 'global', 'log_location' ),
77
  );
78
 
 
 
 
 
 
 
 
79
 
80
  $send_email = true;
81
 
@@ -83,6 +92,7 @@ final class ITSEC_File_Change_Scanner {
83
 
84
  define( 'ITSEC_DOING_FILE_CHECK', true );
85
 
 
86
  //figure out what chunk we're on
87
  if ( $this->settings['split'] ) {
88
 
@@ -94,34 +104,28 @@ final class ITSEC_File_Change_Scanner {
94
 
95
  $db_field = 'itsec_local_file_list_' . $chunk;
96
 
97
-
98
- $content_dir = explode( '/', WP_CONTENT_DIR );
99
- $plugin_dir = explode( '/', WP_PLUGIN_DIR );
100
  $wp_upload_dir = ITSEC_Core::get_wp_upload_dir();
101
 
102
  $dirs = array(
103
  'wp-admin',
104
  WPINC,
105
  WP_CONTENT_DIR,
106
- ITSEC_Core::get_wp_upload_dir(),
107
  WP_CONTENT_DIR . '/themes',
108
  WP_PLUGIN_DIR,
109
  ''
110
  );
111
 
 
 
 
 
 
112
  $path = $dirs[ $chunk ];
113
 
114
  unset( $dirs[ $chunk ] );
115
-
116
  $this->excludes = array_merge( $this->excludes, $dirs );
117
 
118
- foreach ( $this->excludes as $index => $path ) {
119
- $path = untrailingslashit( $path );
120
- $path = preg_replace( '/^' . preg_quote( ABSPATH, '/' ) . '/', '', $path );
121
-
122
- $this->excludes[$index] = $path;
123
- }
124
-
125
  } else {
126
 
127
  $chunk = false;
@@ -135,7 +139,6 @@ final class ITSEC_File_Change_Scanner {
135
 
136
  $logged_files = get_site_option( $db_field );
137
 
138
- //if there are no old files old file list is an empty array
139
  if ( false === $logged_files ) {
140
 
141
  $send_email = false;
@@ -238,7 +241,7 @@ final class ITSEC_File_Change_Scanner {
238
  );
239
 
240
  $this->settings['latest_changes'] = array(
241
- 'added' => count( $files_added ),
242
  'removed' => count( $files_removed ),
243
  'changed' => count( $files_changed ),
244
  );
68
  }
69
 
70
  foreach ( $this->settings['file_list'] as $index => $path ) {
71
+ $path = untrailingslashit( $path );
72
+ $path = '/' . ltrim( $path, '/' );
73
+ $this->settings['file_list'][$index] = $path;
74
  }
75
 
76
  $this->excludes = array(
78
  ITSEC_Modules::get_setting( 'global', 'log_location' ),
79
  );
80
 
81
+ foreach ( $this->excludes as $index => $path ) {
82
+ $path = untrailingslashit( $path );
83
+ $path = preg_replace( '/^' . preg_quote( ABSPATH, '/' ) . '/', '', $path );
84
+ $path = ltrim( $path, '/' );
85
+ $this->excludes[$index] = $path;
86
+ }
87
+
88
 
89
  $send_email = true;
90
 
92
 
93
  define( 'ITSEC_DOING_FILE_CHECK', true );
94
 
95
+
96
  //figure out what chunk we're on
97
  if ( $this->settings['split'] ) {
98
 
104
 
105
  $db_field = 'itsec_local_file_list_' . $chunk;
106
 
 
 
 
107
  $wp_upload_dir = ITSEC_Core::get_wp_upload_dir();
108
 
109
  $dirs = array(
110
  'wp-admin',
111
  WPINC,
112
  WP_CONTENT_DIR,
113
+ $wp_upload_dir['basedir'],
114
  WP_CONTENT_DIR . '/themes',
115
  WP_PLUGIN_DIR,
116
  ''
117
  );
118
 
119
+ foreach ( $dirs as $index => $dir ) {
120
+ $dir = untrailingslashit( $dir );
121
+ $dirs[$index] = preg_replace( '/^' . preg_quote( ABSPATH, '/' ) . '/', '', $dir );
122
+ }
123
+
124
  $path = $dirs[ $chunk ];
125
 
126
  unset( $dirs[ $chunk ] );
 
127
  $this->excludes = array_merge( $this->excludes, $dirs );
128
 
 
 
 
 
 
 
 
129
  } else {
130
 
131
  $chunk = false;
139
 
140
  $logged_files = get_site_option( $db_field );
141
 
 
142
  if ( false === $logged_files ) {
143
 
144
  $send_email = false;
241
  );
242
 
243
  $this->settings['latest_changes'] = array(
244
+ 'added' => count( $files_added ),
245
  'removed' => count( $files_removed ),
246
  'changed' => count( $files_changed ),
247
  );
core/modules/malware/class-itsec-malware-scanner.php CHANGED
@@ -123,6 +123,10 @@ final class ITSEC_Malware_Scanner {
123
  ITSEC_Log::add_process_update( $process_id, array( 'action' => 'using-cached-response' ) );
124
  }
125
 
 
 
 
 
126
  $results = self::parse_response( $response );
127
 
128
  if ( ! is_wp_error( $results ) ) {
123
  ITSEC_Log::add_process_update( $process_id, array( 'action' => 'using-cached-response' ) );
124
  }
125
 
126
+ if ( is_wp_error( $response ) ) {
127
+ return $response;
128
+ }
129
+
130
  $results = self::parse_response( $response );
131
 
132
  if ( ! is_wp_error( $results ) ) {
history.txt CHANGED
@@ -721,3 +721,7 @@
721
  Enhancement: Updated logging system to keep track of more information and have more options to filter and sort log entries.
722
  Enhancement: Improved efficiency of File Change Detection scanning.
723
  Bug Fix: Fixed issue that could register loading the logging page as a failed login attempt on some sites.
 
 
 
 
721
  Enhancement: Updated logging system to keep track of more information and have more options to filter and sort log entries.
722
  Enhancement: Improved efficiency of File Change Detection scanning.
723
  Bug Fix: Fixed issue that could register loading the logging page as a failed login attempt on some sites.
724
+ 6.9.1 - 2018-03-01 - Chris Jean & Timothy Jacobs
725
+ Security Fix: Fixed display of unescaped data on logs page. Thanks to Paweł Kuryłowicz from SecuRing for finding and reporting this issue.
726
+ Enhancement: The logging system now differentiates between WP-CLI commands, WP-Cron scheduled events, and normal page requests.
727
+ Bug Fix: Fixed the File Change scanner in that it previously could fail to exclude selected directories on some systems.
readme.txt CHANGED
@@ -3,7 +3,8 @@ Contributors: ithemes, chrisjean, gerroald, mattdanner, timothyblynjacobs
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.7
5
  Tested up to: 4.9.4
6
- Stable tag: 6.9.0
 
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -188,6 +189,11 @@ Free support may be available with the help of the community in the <a href="htt
188
 
189
  == Changelog ==
190
 
 
 
 
 
 
191
  = 6.9.0 =
192
  * Enhancement: Updated logging system to keep track of more information and have more options to filter and sort log entries.
193
  * Enhancement: Improved efficiency of File Change Detection scanning.
@@ -405,5 +411,5 @@ Free support may be available with the help of the community in the <a href="htt
405
 
406
  == Upgrade Notice ==
407
 
408
- = 6.9.0 =
409
- Version 6.9.0 contains an improved logging system and bug fixes. It is recommended for all users.
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.7
5
  Tested up to: 4.9.4
6
+ Stable tag: 6.9.1
7
+ Requires PHP: 5.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
189
 
190
  == Changelog ==
191
 
192
+ = 6.9.1 =
193
+ * Security Fix: Fixed display of unescaped data on logs page. Thanks to Paweł Kuryłowicz from SecuRing for finding and reporting this issue.
194
+ * Enhancement: The logging system now differentiates between WP-CLI commands, WP-Cron scheduled events, and normal page requests.
195
+ * Bug Fix: Fixed the File Change scanner in that it previously could fail to exclude selected directories on some systems.
196
+
197
  = 6.9.0 =
198
  * Enhancement: Updated logging system to keep track of more information and have more options to filter and sort log entries.
199
  * Enhancement: Improved efficiency of File Change Detection scanning.
411
 
412
  == Upgrade Notice ==
413
 
414
+ = 6.9.1 =
415
+ Version 6.9.1 contains an important security bug fix. It is recommended for all users.