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 | 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 +1 -1
- core/admin-pages/css/style.css +3 -3
- core/admin-pages/init.php +2 -4
- core/admin-pages/page-logs.php +13 -5
- core/admin-pages/page-settings.php +2 -4
- core/core.php +6 -4
- core/history.txt +10 -0
- core/lib/class-itsec-job.php +39 -0
- core/lib/class-itsec-scheduler-cron.php +19 -0
- core/lib/class-itsec-scheduler-page-load.php +14 -5
- core/lib/class-itsec-scheduler.php +51 -4
- core/lib/log.php +11 -1
- core/modules.php +0 -3
- core/modules/404-detection/logs.php +1 -1
- core/modules/file-change/scanner.php +18 -15
- core/modules/malware/class-itsec-malware-scanner.php +4 -0
- history.txt +4 -0
- readme.txt +9 -3
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.
|
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(),
|
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(),
|
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' ),
|
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(),
|
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>' .
|
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' ),
|
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(),
|
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 =
|
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 ]
|
118 |
-
|
|
|
119 |
|
120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
}
|
122 |
|
123 |
-
return
|
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
|
94 |
-
* @param array
|
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
|
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 |
-
|
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' =>
|
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 |
-
$
|
|
|
|
|
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 |
-
|
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'
|
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.
|
|
|
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.
|
409 |
-
Version 6.9.
|
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.
|