iThemes Security (formerly Better WP Security) - Version 5.7.0

Version Description

  • Bug Fix: Fixed data save issue that could cause multiple notification emails to be sent in a short period of time.
    • Bug Fix: Fixed issue that could cause the malware scanner to fail on sites that change the arg_separator.output php.ini value from its default value.
    • Bug Fix: Removed redundant entries in the HackRepair blacklist.
    • Bug Fix: Enabling Protect System Files in System Tweaks will now only block install.php for the current site. This fixes the issue where the setting can block installation of a site in a subdirectory.
    • Bug Fix: Fixed problem that could cause requests for iThemes Security data from iThemes Sync to fail due to large amounts of log entries.
    • Bug Fix: Scheduled backups now run if the ITSEC_BACKUP_CRON define is set with a non-boolean value.
    • Bug Fix: Replaced static references to wp-includes with the WPINC define.
    • Bug Fix: Moved blocking of query strings containing %0[0-9A-F] characters from the Non-English Characters setting to the Suspicious Query Strings setting as those characters are control code characters and are not associated with a language.
    • Bug Fix: Added escaping to some translation strings.
    • Bug Fix: Removed unused files from the WordPress Tweaks module directory.
    • Bug Fix: Fixed the Daily Digest email reversing the user and host lockout counts.
    • Bug Fix: The database backup email no longer sends from the email address configured in Settings > General. It now defaults to the same from address that the wp_mail() function uses. This will fix the mail being blocked by some mail servers due to a spoofed from address.
    • Enhancement: Updated the server config rules generated by the System Tweaks settings. They are now more consistent between Apache, LiteSpeed, and nginx. They are also more efficient and have been improved to limit accidentally blocking non-targeted requests.
    • Enhancement: Updated the database backup email to a new design.
    • Enhancement: Added a note that the Filter Request Methods setting in System Tweaks should not be enabled if the WordPress REST API is used. This is becasue the DELETE HTTP method is blocked when the setting is enabled.
    • New Feature: Added setting to block requests for PHP files in the plugins directory in System Tweaks.
    • New Feature: Added setting to block requests for PHP files in the themes directory in System Tweaks.
Download this release

Release Info

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

Code changes from version 5.6.4 to 5.7.0

better-wp-security.php CHANGED
@@ -6,7 +6,7 @@
6
  * Description: Take the guesswork out of WordPress security. iThemes Security offers 30+ ways to lock down WordPress in an easy-to-use WordPress security plugin.
7
  * Author: iThemes
8
  * Author URI: https://ithemes.com
9
- * Version: 5.6.4
10
  * Text Domain: better-wp-security
11
  * Network: True
12
  * License: GPLv2
6
  * Description: Take the guesswork out of WordPress security. iThemes Security offers 30+ ways to lock down WordPress in an easy-to-use WordPress security plugin.
7
  * Author: iThemes
8
  * Author URI: https://ithemes.com
9
+ * Version: 5.7.0
10
  * Text Domain: better-wp-security
11
  * Network: True
12
  * License: GPLv2
core/class-itsec-core.php CHANGED
@@ -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 = 4043; // used to trigger updates
78
  $this->plugin_file = $plugin_file;
79
  $this->plugin_dir = dirname( $plugin_file ) . '/';
80
  $this->current_time = current_time( 'timestamp' );
74
  public function init( $plugin_file, $plugin_name ) {
75
  global $itsec_globals, $itsec_logger, $itsec_lockout;
76
 
77
+ $this->plugin_build = 4044; // used to trigger updates
78
  $this->plugin_file = $plugin_file;
79
  $this->plugin_dir = dirname( $plugin_file ) . '/';
80
  $this->current_time = current_time( 'timestamp' );
core/class-itsec-notify.php CHANGED
@@ -67,7 +67,11 @@ class ITSEC_Notify {
67
  }
68
 
69
 
70
- return $this->send_daily_digest();
 
 
 
 
71
  }
72
 
73
  /**
@@ -92,11 +96,11 @@ class ITSEC_Notify {
92
 
93
  $mail->add_section_heading( esc_html__( 'Lockouts', 'better-wp-security' ), 'lock' );
94
 
95
- $host_count = sizeof( $itsec_lockout->get_lockouts( 'host', true ) );
96
  $user_count = sizeof( $itsec_lockout->get_lockouts( 'user', true ) );
 
97
 
98
  if ( $host_count > 0 || $user_count > 0 ) {
99
- $mail->add_lockouts_summary( $host_count, $user_count );
100
  $send_email = true;
101
  } else {
102
  $mail->add_text( esc_html__( 'No lockouts since the last email check.', 'better-wp-security' ) );
67
  }
68
 
69
 
70
+ $result = $this->send_daily_digest();
71
+
72
+ delete_site_transient( 'itsec_notification_running' );
73
+
74
+ return $result;
75
  }
76
 
77
  /**
96
 
97
  $mail->add_section_heading( esc_html__( 'Lockouts', 'better-wp-security' ), 'lock' );
98
 
 
99
  $user_count = sizeof( $itsec_lockout->get_lockouts( 'user', true ) );
100
+ $host_count = sizeof( $itsec_lockout->get_lockouts( 'host', true ) );
101
 
102
  if ( $host_count > 0 || $user_count > 0 ) {
103
+ $mail->add_lockouts_summary( $user_count, $host_count );
104
  $send_email = true;
105
  } else {
106
  $mail->add_text( esc_html__( 'No lockouts since the last email check.', 'better-wp-security' ) );
core/history.txt CHANGED
@@ -441,3 +441,21 @@
441
  Bug Fix: Fixed issue that could prevent saving of File Change settings, resulting in an error messages of "A validation function for file-change received data that did not have the required entry for latest_changes."
442
  2.5.11 - 2016-10-14 - Chris Jean
443
  Bug Fix: Fixed iThemes Security Pro logo appearing in daily digest emails for iThemes Security users.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
441
  Bug Fix: Fixed issue that could prevent saving of File Change settings, resulting in an error messages of "A validation function for file-change received data that did not have the required entry for latest_changes."
442
  2.5.11 - 2016-10-14 - Chris Jean
443
  Bug Fix: Fixed iThemes Security Pro logo appearing in daily digest emails for iThemes Security users.
444
+ 2.6.0 - 2016-10-27 - Chris Jean
445
+ Bug Fix: Fixed data save issue that could cause multiple notification emails to be sent in a short period of time.
446
+ Bug Fix: Fixed issue that could cause the malware scanner to fail on sites that change the arg_separator.output php.ini value from its default value.
447
+ Bug Fix: Removed redundant entries in the HackRepair blacklist.
448
+ Bug Fix: Enabling Protect System Files in System Tweaks will now only block install.php for the current site. This fixes the issue where the setting can block installation of a site in a subdirectory.
449
+ Bug Fix: Fixed problem that could cause requests for iThemes Security data from iThemes Sync to fail due to large amounts of log entries.
450
+ Bug Fix: Scheduled backups now run if the ITSEC_BACKUP_CRON define is set with a non-boolean value.
451
+ Bug Fix: Replaced static references to wp-includes with the WPINC define.
452
+ Bug Fix: Moved blocking of query strings containing %0[0-9A-F] characters from the Non-English Characters setting to the Suspicious Query Strings setting as those characters are control code characters and are not associated with a language.
453
+ Bug Fix: Added escaping to some translation strings.
454
+ Bug Fix: Removed unused files from the WordPress Tweaks module directory.
455
+ Bug Fix: Fixed the Daily Digest email reversing the user and host lockout counts.
456
+ Bug Fix: The database backup email no longer sends from the email address configured in Settings > General. It now defaults to the same from address that the wp_mail() function uses. This will fix the mail being blocked by some mail servers due to a spoofed from address.
457
+ Enhancement: Updated the server config rules generated by the System Tweaks settings. They are now more consistent between Apache, LiteSpeed, and nginx. They are also more efficient and have been improved to limit accidentally blocking non-targeted requests.
458
+ Enhancement: Updated the database backup email to a new design.
459
+ Enhancement: Added a note that the Filter Request Methods setting in System Tweaks should not be enabled if the WordPress REST API is used. This is becasue the DELETE HTTP method is blocked when the setting is enabled.
460
+ New Feature: Added setting to block requests for PHP files in the plugins directory in System Tweaks.
461
+ New Feature: Added setting to block requests for PHP files in the themes directory in System Tweaks.
core/lib/class-itsec-lib-utility.php CHANGED
@@ -29,30 +29,30 @@ if ( ! class_exists( 'ITSEC_Lib_Utility' ) ) {
29
  if ( ! is_callable( $function ) ) {
30
  return false;
31
  }
32
-
33
  if ( ! isset( $GLOBALS['itsec_lib_cached_values'] ) ) {
34
  $GLOBALS['itsec_lib_cached_values'] = array();
35
  }
36
-
37
  if ( ! isset( $GLOBALS['itsec_lib_cached_values']['ini_get:disable_functions'] ) ) {
38
  $GLOBALS['itsec_lib_cached_values']['ini_get:disable_functions'] = preg_split( '/\s*,\s*/', (string) ini_get( 'disable_functions' ) );
39
  }
40
-
41
  if ( in_array( $function, $GLOBALS['itsec_lib_cached_values']['ini_get:disable_functions'] ) ) {
42
  return false;
43
  }
44
-
45
  if ( ! isset( $GLOBALS['itsec_lib_cached_values']['ini_get:suhosin.executor.func.blacklist'] ) ) {
46
  $GLOBALS['itsec_lib_cached_values']['ini_get:suhosin.executor.func.blacklist'] = preg_split( '/\s*,\s*/', (string) ini_get( 'suhosin.executor.func.blacklist' ) );
47
  }
48
-
49
  if ( in_array( $function, $GLOBALS['itsec_lib_cached_values']['ini_get:suhosin.executor.func.blacklist'] ) ) {
50
  return false;
51
  }
52
-
53
  return true;
54
  }
55
-
56
  /**
57
  * Returns the type of web server.
58
  *
@@ -69,14 +69,14 @@ if ( ! class_exists( 'ITSEC_Lib_Utility' ) ) {
69
  return ITSEC_SERVER_OVERRIDE;
70
  }
71
  // @codeCoverageIgnoreEnd
72
-
73
-
74
  if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
75
  $server_software = strtolower( $_SERVER['SERVER_SOFTWARE'] );
76
  } else {
77
  $server_software = '';
78
  }
79
-
80
  if ( false !== strpos( $server_software, 'apache' ) ) {
81
  $server = 'apache';
82
  } else if ( false !== strpos( $server_software, 'nginx' ) ) {
@@ -90,10 +90,10 @@ if ( ! class_exists( 'ITSEC_Lib_Utility' ) ) {
90
  } else {
91
  $server = 'apache';
92
  }
93
-
94
  return apply_filters( 'itsec_filter_web_server', $server );
95
  }
96
-
97
  /**
98
  * Updates the supplied content to use the same line endings.
99
  *
@@ -106,7 +106,27 @@ if ( ! class_exists( 'ITSEC_Lib_Utility' ) ) {
106
  public static function normalize_line_endings( $content, $line_ending = "\n" ) {
107
  return preg_replace( '/(?<!\r)\n|\r(?!\n)|(?<!\r)\r\n|\r\r\n/', $line_ending, $content );
108
  }
109
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  /**
111
  * Returns the directory path to the uploads directory relative to the site root.
112
  *
@@ -116,18 +136,9 @@ if ( ! class_exists( 'ITSEC_Lib_Utility' ) ) {
116
  */
117
  public static function get_relative_upload_url_path() {
118
  $upload_dir_details = wp_upload_dir();
119
- $upload_baseurl = parse_url( $upload_dir_details['baseurl'], PHP_URL_PATH );
120
- $home_url = parse_url( home_url(), PHP_URL_PATH );
121
-
122
- $upload_path = preg_replace( '/^' . preg_quote( $home_url, '/' ) . '/', '', $upload_baseurl, 1, $count );
123
-
124
- if ( 1 === $count ) {
125
- return trim( $upload_path, '/' );
126
- }
127
-
128
- return false;
129
  }
130
-
131
  /**
132
  * Remove comments from a string containing PHP code.
133
  *
@@ -140,30 +151,30 @@ if ( ! class_exists( 'ITSEC_Lib_Utility' ) ) {
140
  if ( ! self::is_callable_function( 'token_get_all' ) ) {
141
  return new WP_Error( 'itsec-lib-utility-strip-php-comments-token-get-all-is-disabled', __( 'Unable to strip comments from the source code as the token_get_all() function is disabled. This is a system configuration issue.', 'better-wp-security' ) );
142
  }
143
-
144
-
145
  $tokens = token_get_all( $contents );
146
-
147
  if ( ! is_array( $tokens ) ) {
148
  return new WP_Error( 'itsec-lib-utility-strip-php-comments-token-get-all-invalid-response', sprintf( __( 'Unable to strip comments from the source code as the token_get_all() function returned an unrecognized value (type: %s)', 'better-wp-security' ), gettype( $tokens ) ) );
149
  }
150
-
151
-
152
  if ( ! defined( 'T_ML_COMMENT' ) ) {
153
  define( 'T_ML_COMMENT', T_COMMENT );
154
  }
155
  if ( ! defined( 'T_DOC_COMMENT' ) ) {
156
  define( 'T_DOC_COMMENT', T_ML_COMMENT );
157
  }
158
-
159
  $contents = '';
160
-
161
  foreach ( $tokens as $token ) {
162
  if ( is_string( $token ) ) {
163
  $contents .= $token;
164
  } else {
165
  list( $id, $text ) = $token;
166
-
167
  switch ($id) {
168
  case T_COMMENT:
169
  case T_ML_COMMENT:
@@ -175,7 +186,7 @@ if ( ! class_exists( 'ITSEC_Lib_Utility' ) ) {
175
  }
176
  }
177
  }
178
-
179
  return $contents;
180
  }
181
  }
29
  if ( ! is_callable( $function ) ) {
30
  return false;
31
  }
32
+
33
  if ( ! isset( $GLOBALS['itsec_lib_cached_values'] ) ) {
34
  $GLOBALS['itsec_lib_cached_values'] = array();
35
  }
36
+
37
  if ( ! isset( $GLOBALS['itsec_lib_cached_values']['ini_get:disable_functions'] ) ) {
38
  $GLOBALS['itsec_lib_cached_values']['ini_get:disable_functions'] = preg_split( '/\s*,\s*/', (string) ini_get( 'disable_functions' ) );
39
  }
40
+
41
  if ( in_array( $function, $GLOBALS['itsec_lib_cached_values']['ini_get:disable_functions'] ) ) {
42
  return false;
43
  }
44
+
45
  if ( ! isset( $GLOBALS['itsec_lib_cached_values']['ini_get:suhosin.executor.func.blacklist'] ) ) {
46
  $GLOBALS['itsec_lib_cached_values']['ini_get:suhosin.executor.func.blacklist'] = preg_split( '/\s*,\s*/', (string) ini_get( 'suhosin.executor.func.blacklist' ) );
47
  }
48
+
49
  if ( in_array( $function, $GLOBALS['itsec_lib_cached_values']['ini_get:suhosin.executor.func.blacklist'] ) ) {
50
  return false;
51
  }
52
+
53
  return true;
54
  }
55
+
56
  /**
57
  * Returns the type of web server.
58
  *
69
  return ITSEC_SERVER_OVERRIDE;
70
  }
71
  // @codeCoverageIgnoreEnd
72
+
73
+
74
  if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
75
  $server_software = strtolower( $_SERVER['SERVER_SOFTWARE'] );
76
  } else {
77
  $server_software = '';
78
  }
79
+
80
  if ( false !== strpos( $server_software, 'apache' ) ) {
81
  $server = 'apache';
82
  } else if ( false !== strpos( $server_software, 'nginx' ) ) {
90
  } else {
91
  $server = 'apache';
92
  }
93
+
94
  return apply_filters( 'itsec_filter_web_server', $server );
95
  }
96
+
97
  /**
98
  * Updates the supplied content to use the same line endings.
99
  *
106
  public static function normalize_line_endings( $content, $line_ending = "\n" ) {
107
  return preg_replace( '/(?<!\r)\n|\r(?!\n)|(?<!\r)\r\n|\r\r\n/', $line_ending, $content );
108
  }
109
+
110
+ /**
111
+ * Returns the path portion of a URL.
112
+ *
113
+ * @since 2.5.10
114
+ *
115
+ * @param string $url The URL to extract the path from.
116
+ * @return string|bool The relative path portion of the supplied URL or false if the path could not be determined.
117
+ */
118
+ public static function get_relative_url_path( $url ) {
119
+ $url = parse_url( $url, PHP_URL_PATH );
120
+ $home_url = parse_url( home_url(), PHP_URL_PATH );
121
+ $path = preg_replace( '/^' . preg_quote( $home_url, '/' ) . '/', '', $url, 1, $count );
122
+
123
+ if ( 1 === $count ) {
124
+ return trim( $path, '/' );
125
+ }
126
+
127
+ return false;
128
+ }
129
+
130
  /**
131
  * Returns the directory path to the uploads directory relative to the site root.
132
  *
136
  */
137
  public static function get_relative_upload_url_path() {
138
  $upload_dir_details = wp_upload_dir();
139
+ return ITSEC_Lib_Utility::get_relative_url_path( $upload_dir_details['baseurl'] );
 
 
 
 
 
 
 
 
 
140
  }
141
+
142
  /**
143
  * Remove comments from a string containing PHP code.
144
  *
151
  if ( ! self::is_callable_function( 'token_get_all' ) ) {
152
  return new WP_Error( 'itsec-lib-utility-strip-php-comments-token-get-all-is-disabled', __( 'Unable to strip comments from the source code as the token_get_all() function is disabled. This is a system configuration issue.', 'better-wp-security' ) );
153
  }
154
+
155
+
156
  $tokens = token_get_all( $contents );
157
+
158
  if ( ! is_array( $tokens ) ) {
159
  return new WP_Error( 'itsec-lib-utility-strip-php-comments-token-get-all-invalid-response', sprintf( __( 'Unable to strip comments from the source code as the token_get_all() function returned an unrecognized value (type: %s)', 'better-wp-security' ), gettype( $tokens ) ) );
160
  }
161
+
162
+
163
  if ( ! defined( 'T_ML_COMMENT' ) ) {
164
  define( 'T_ML_COMMENT', T_COMMENT );
165
  }
166
  if ( ! defined( 'T_DOC_COMMENT' ) ) {
167
  define( 'T_DOC_COMMENT', T_ML_COMMENT );
168
  }
169
+
170
  $contents = '';
171
+
172
  foreach ( $tokens as $token ) {
173
  if ( is_string( $token ) ) {
174
  $contents .= $token;
175
  } else {
176
  list( $id, $text ) = $token;
177
+
178
  switch ($id) {
179
  case T_COMMENT:
180
  case T_ML_COMMENT:
186
  }
187
  }
188
  }
189
+
190
  return $contents;
191
  }
192
  }
core/lib/class-itsec-mailer.php CHANGED
@@ -48,6 +48,8 @@ final class ITSEC_Mail {
48
  );
49
 
50
  $footer .= $this->replace_all( $callout, $replacements );
 
 
51
  }
52
 
53
  $footer .= $this->get_template( 'footer.html' );
@@ -94,9 +96,11 @@ final class ITSEC_Mail {
94
  $this->content .= $module;
95
  }
96
 
97
- public function add_info_box( $content ) {
 
 
98
  $module = $this->get_template( 'info-box.html' );
99
- $module = $this->replace( $module, 'content', $content );
100
 
101
  $this->content .= $module;
102
  }
@@ -108,11 +112,16 @@ final class ITSEC_Mail {
108
  $this->content .= $module;
109
  }
110
 
111
- public function add_section_heading( $content, $icon_type ) {
112
- $icon_url = "https://ithemes.com/email_images/itsec-icon-$icon_type.png";
 
 
 
 
113
 
114
- $heading = $this->get_template( 'section-heading.html' );
115
- $heading = $this->replace_all( $heading, compact( 'content', 'icon_url' ) );
 
116
 
117
  $this->content .= $heading;
118
  }
@@ -144,8 +153,8 @@ final class ITSEC_Mail {
144
  return $this->content;
145
  }
146
 
147
- public function send( $to, $subject ) {
148
- return wp_mail( $to, $subject, $this->content, array( 'Content-Type: text/html; charset=UTF-8' ) );
149
  }
150
 
151
  private function get_template( $template ) {
48
  );
49
 
50
  $footer .= $this->replace_all( $callout, $replacements );
51
+ } else {
52
+ $this->add_divider();
53
  }
54
 
55
  $footer .= $this->get_template( 'footer.html' );
96
  $this->content .= $module;
97
  }
98
 
99
+ public function add_info_box( $content, $icon_type = 'info' ) {
100
+ $icon_url = "http://ithemes.com/email_images/itsec-$icon_type-icon.png";
101
+
102
  $module = $this->get_template( 'info-box.html' );
103
+ $module = $this->replace_all( $module, compact( 'content', 'icon_url' ) );
104
 
105
  $this->content .= $module;
106
  }
112
  $this->content .= $module;
113
  }
114
 
115
+ public function add_section_heading( $content, $icon_type = false ) {
116
+ if ( empty( $icon_type ) ) {
117
+ $heading = $this->get_template( 'section-heading.html' );
118
+ $heading = $this->replace_all( $heading, compact( 'content' ) );
119
+ } else {
120
+ $icon_url = "https://ithemes.com/email_images/itsec-icon-$icon_type.png";
121
 
122
+ $heading = $this->get_template( 'section-heading-with-icon.html' );
123
+ $heading = $this->replace_all( $heading, compact( 'content', 'icon_url' ) );
124
+ }
125
 
126
  $this->content .= $heading;
127
  }
153
  return $this->content;
154
  }
155
 
156
+ public function send( $to, $subject, $attachments = array() ) {
157
+ return wp_mail( $to, $subject, $this->content, array( 'Content-Type: text/html; charset=UTF-8' ), $attachments );
158
  }
159
 
160
  private function get_template( $template ) {
core/lib/mail-templates/info-box.html CHANGED
@@ -9,7 +9,7 @@
9
  <table border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;">
10
  <tr>
11
  <td class="container-cell" valign="top" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;color: #404040;font-family: Helvetica;font-size: 16px;line-height: 150%;text-align: center;padding-bottom: 40px;">
12
- <img class="info-icon" src="http://ithemes.com/email_images/itsec-info-icon.png" alt="" align="center" width="33" height="23" style="border: 0;outline: none;text-decoration: none;-ms-interpolation-mode: bicubic;height: 23px;width: 33px;vertical-align: middle;">
13
  {{ $content }}
14
  </td>
15
  </tr>
9
  <table border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;">
10
  <tr>
11
  <td class="container-cell" valign="top" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;color: #404040;font-family: Helvetica;font-size: 16px;line-height: 150%;text-align: center;padding-bottom: 40px;">
12
+ <img class="info-icon" src="{{ $icon_url }}" alt="" align="center" width="33" height="23" style="border: 0;outline: none;text-decoration: none;-ms-interpolation-mode: bicubic;height: 23px;width: 33px;vertical-align: middle;">
13
  {{ $content }}
14
  </td>
15
  </tr>
core/lib/mail-templates/section-heading-with-icon.html ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <td class="section-heading" align="center" valign="top" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;">
3
+ <table border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;">
4
+ <tr>
5
+ <td align="center" valign="top" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;">
6
+ <table class="container" border="0" cellpadding="0" cellspacing="0" width="600" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;">
7
+ <tr>
8
+ <td class="section-padding" align="center" valign="top" width="600" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;padding-top: 20px;padding-right: 20px;padding-left: 20px;">
9
+ <table border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;">
10
+ <tr>
11
+ <td class="container-cell" valign="top" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;color: #404040;font-family: Helvetica;font-size: 16px;line-height: 150%;text-align: center;padding-bottom: 0;">
12
+ <h4 style="color: #0084CB;font-family: Helvetica;font-size: 16px;font-weight: bold;line-height: 150%;margin: 0;padding: 0;text-align: center;">
13
+ <img src="{{ $icon_url }}" alt="" align="center" style="border: 0;outline: none;text-decoration: none;-ms-interpolation-mode: bicubic;height: auto;padding-top: 2px;padding-right: 5px;vertical-align: top;">
14
+ {{ $content }}
15
+ </h4>
16
+ </td>
17
+ </tr>
18
+ </table>
19
+ </td>
20
+ </tr>
21
+ </table>
22
+ </td>
23
+ </tr>
24
+ </table>
25
+ </td>
26
+ </tr>
core/lib/mail-templates/section-heading.html CHANGED
@@ -10,7 +10,6 @@
10
  <tr>
11
  <td class="container-cell" valign="top" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;color: #404040;font-family: Helvetica;font-size: 16px;line-height: 150%;text-align: center;padding-bottom: 0;">
12
  <h4 style="color: #0084CB;font-family: Helvetica;font-size: 16px;font-weight: bold;line-height: 150%;margin: 0;padding: 0;text-align: center;">
13
- <img src="{{ $icon_url }}" alt="" align="center" style="border: 0;outline: none;text-decoration: none;-ms-interpolation-mode: bicubic;height: auto;padding-top: 2px;padding-right: 5px;vertical-align: top;">
14
  {{ $content }}
15
  </h4>
16
  </td>
10
  <tr>
11
  <td class="container-cell" valign="top" style="border-collapse: collapse;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;color: #404040;font-family: Helvetica;font-size: 16px;line-height: 150%;text-align: center;padding-bottom: 0;">
12
  <h4 style="color: #0084CB;font-family: Helvetica;font-size: 16px;font-weight: bold;line-height: 150%;margin: 0;padding: 0;text-align: center;">
 
13
  {{ $content }}
14
  </h4>
15
  </td>
core/lib/storage.php CHANGED
@@ -2,92 +2,94 @@
2
 
3
  final class ITSEC_Storage {
4
  private $option = 'itsec-storage';
5
-
6
  private static $instance = false;
7
  private $changed = false;
8
  private $cache;
9
  private $shutdown_done = false;
10
-
11
  private function __construct() {
12
  $this->load();
13
-
14
- add_action( 'shutdown', array( $this, 'shutdown' ) );
 
 
15
  add_action( 'itsec-lib-clear-caches', array( $this, 'save' ), -20 );
16
  add_action( 'itsec-lib-clear-caches', array( $this, 'load' ), -10 );
17
  }
18
-
19
  private static function get_instance() {
20
  if ( false === self::$instance ) {
21
  self::$instance = new self();
22
  }
23
-
24
  return self::$instance;
25
  }
26
-
27
  public static function get( $name ) {
28
  $data = self::get_instance();
29
-
30
  if ( isset( $data->cache[$name] ) ) {
31
  return $data->cache[$name];
32
  }
33
-
34
  return null;
35
  }
36
-
37
  public static function get_all() {
38
  $data = self::get_instance();
39
-
40
  return $data->cache;
41
  }
42
-
43
  public static function set( $name, $value ) {
44
  $data = self::get_instance();
45
  $data->cache[$name] = $value;
46
  $data->changed = true;
47
-
48
  if ( $data->shutdown_done ) {
49
  self::save();
50
  }
51
  }
52
-
53
  public static function set_all( $value ) {
54
  $data = self::get_instance();
55
  $data->cache = $value;
56
  $data->changed = true;
57
-
58
  if ( $data->shutdown_done ) {
59
  self::save();
60
  }
61
  }
62
-
63
  public static function save() {
64
  $data = self::get_instance();
65
-
66
  if ( ! $data->changed ) {
67
  return true;
68
  }
69
-
70
  $data->changed = false;
71
-
72
  return update_site_option( $data->option, $data->cache );
73
  }
74
-
75
  public static function reload() {
76
  $data = self::get_instance();
77
  $data->load();
78
  }
79
-
80
  public function load() {
81
  $this->cache = get_site_option( $this->option );
82
-
83
  if ( ! is_array( $this->cache ) ) {
84
  $this->cache = array();
85
  }
86
  }
87
-
88
  public function shutdown() {
89
  self::save();
90
-
91
  $this->shutdown_done = true;
92
  }
93
  }
2
 
3
  final class ITSEC_Storage {
4
  private $option = 'itsec-storage';
5
+
6
  private static $instance = false;
7
  private $changed = false;
8
  private $cache;
9
  private $shutdown_done = false;
10
+
11
  private function __construct() {
12
  $this->load();
13
+
14
+ register_shutdown_function( array( $this, 'shutdown' ) );
15
+ add_action( 'shutdown', array( $this, 'shutdown' ), -10 );
16
+
17
  add_action( 'itsec-lib-clear-caches', array( $this, 'save' ), -20 );
18
  add_action( 'itsec-lib-clear-caches', array( $this, 'load' ), -10 );
19
  }
20
+
21
  private static function get_instance() {
22
  if ( false === self::$instance ) {
23
  self::$instance = new self();
24
  }
25
+
26
  return self::$instance;
27
  }
28
+
29
  public static function get( $name ) {
30
  $data = self::get_instance();
31
+
32
  if ( isset( $data->cache[$name] ) ) {
33
  return $data->cache[$name];
34
  }
35
+
36
  return null;
37
  }
38
+
39
  public static function get_all() {
40
  $data = self::get_instance();
41
+
42
  return $data->cache;
43
  }
44
+
45
  public static function set( $name, $value ) {
46
  $data = self::get_instance();
47
  $data->cache[$name] = $value;
48
  $data->changed = true;
49
+
50
  if ( $data->shutdown_done ) {
51
  self::save();
52
  }
53
  }
54
+
55
  public static function set_all( $value ) {
56
  $data = self::get_instance();
57
  $data->cache = $value;
58
  $data->changed = true;
59
+
60
  if ( $data->shutdown_done ) {
61
  self::save();
62
  }
63
  }
64
+
65
  public static function save() {
66
  $data = self::get_instance();
67
+
68
  if ( ! $data->changed ) {
69
  return true;
70
  }
71
+
72
  $data->changed = false;
73
+
74
  return update_site_option( $data->option, $data->cache );
75
  }
76
+
77
  public static function reload() {
78
  $data = self::get_instance();
79
  $data->load();
80
  }
81
+
82
  public function load() {
83
  $this->cache = get_site_option( $this->option );
84
+
85
  if ( ! is_array( $this->cache ) ) {
86
  $this->cache = array();
87
  }
88
  }
89
+
90
  public function shutdown() {
91
  self::save();
92
+
93
  $this->shutdown_done = true;
94
  }
95
  }
core/modules/backup/class-itsec-backup.php CHANGED
@@ -36,26 +36,39 @@ class ITSEC_Backup {
36
 
37
  $this->settings = ITSEC_Modules::get_settings( 'backup' );
38
 
39
- add_action( 'itsec_execute_backup_cron', array( $this, 'do_backup' ) ); //Action to execute during a cron run.
40
-
41
  add_filter( 'itsec_logger_modules', array( $this, 'register_logger' ) );
42
 
43
- if (
44
- ( ! defined( 'DOING_AJAX' ) || false === DOING_AJAX ) &&
45
- ( ! defined( 'ITSEC_BACKUP_CRON' ) || false === ITSEC_BACKUP_CRON ) &&
46
- ! class_exists( 'pb_backupbuddy' ) &&
47
- ( $this->settings['interval'] > 0 ) &&
48
- ( $itsec_globals['current_time_gmt'] - $this->settings['interval'] * DAY_IN_SECONDS ) > $this->settings['last_run']
49
- ) {
50
 
51
- add_action( 'init', array( $this, 'do_backup' ), 10, 0 );
 
 
52
 
53
- } else if ( defined( 'ITSEC_BACKUP_CRON' ) && true === ITSEC_BACKUP_CRON && ! wp_next_scheduled( 'itsec_execute_backup_cron' ) ) { //Use cron if needed
 
 
 
54
 
55
- wp_schedule_event( time(), 'daily', 'itsec_execute_backup_cron' );
 
 
 
56
 
 
 
 
57
  }
58
 
 
 
 
 
 
 
59
  }
60
 
61
  /**
@@ -70,7 +83,6 @@ class ITSEC_Backup {
70
  * @return mixed false on error or nothing
71
  */
72
  public function do_backup( $one_time = false ) {
73
-
74
  ITSEC_Lib::set_minimum_memory_limit( '256M' );
75
 
76
  $itsec_files = ITSEC_Core::get_itsec_files();
@@ -180,7 +192,7 @@ class ITSEC_Backup {
180
  $file = 'backup-' . substr( sanitize_title( get_bloginfo( 'name' ) ), 0, 20 ) . '-' . current_time( 'Ymd-His' ) . '-' . wp_generate_password( 30, false );
181
 
182
  require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-directory.php' );
183
-
184
  $dir = $this->settings['location'];
185
  ITSEC_Lib_Directory::create( $dir );
186
 
@@ -213,38 +225,38 @@ class ITSEC_Backup {
213
  }
214
 
215
  if ( 2 !== $this->settings['method'] || true === $one_time ) {
 
 
 
 
216
 
217
- $attachment = array( $dir . '/' . $file . $fileext );
218
- $body = __( 'Attached is the backup file for the database powering', 'better-wp-security' ) . ' ' . get_option( 'siteurl' ) . __( ' taken', 'better-wp-security' ) . ' ' . date( 'l, F jS, Y \a\\t g:i a', $itsec_globals['current_time'] );
219
 
220
- //Setup the remainder of the email
221
- $recipients = ITSEC_Modules::get_setting( 'global', 'backup_email' );
222
- $subject = __( 'Site Database Backup', 'better-wp-security' ) . ' ' . date( 'l, F jS, Y \a\\t g:i a', $itsec_globals['current_time'] );
223
- $subject = apply_filters( 'itsec_backup_email_subject', $subject );
224
- $headers = 'From: ' . get_bloginfo( 'name' ) . ' <' . get_option( 'admin_email' ) . '>' . "\r\n";
225
- $mail_success = false;
226
 
227
- //Use HTML Content type
228
- add_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
229
 
230
- //Send emails to all recipients
231
- foreach ( $recipients as $recipient ) {
232
 
233
- if ( is_email( trim( $recipient ) ) ) {
234
 
235
- if ( defined( 'ITSEC_DEBUG' ) && true === ITSEC_DEBUG ) {
236
- $body .= '<p>' . __( 'Debug info (source page): ' . esc_url( $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"] ) ) . '</p>';
237
- }
238
 
239
- $mail_success = wp_mail( trim( $recipient ), $subject, '<html>' . $body . '</html>', $headers, $attachment );
 
240
 
 
 
241
  }
242
-
243
  }
244
 
245
- //Remove HTML Content type
246
- remove_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
247
 
 
 
 
248
  }
249
 
250
  if ( 1 === $this->settings['method'] ) {
@@ -284,9 +296,7 @@ class ITSEC_Backup {
284
  }
285
 
286
  if ( false === $one_time ) {
287
-
288
  ITSEC_Modules::set_setting( 'backup', 'last_run', ITSEC_Core::get_current_time_gmt() );
289
-
290
  }
291
 
292
  switch ( $this->settings['method'] ) {
@@ -364,19 +374,4 @@ class ITSEC_Backup {
364
 
365
  }
366
 
367
- /**
368
- * Set HTML content type for email.
369
- *
370
- * Sets the content type on outgoing emails to HTML.
371
- *
372
- * @since 4.0.0
373
- *
374
- * @return string html content type
375
- */
376
- public function set_html_content_type() {
377
-
378
- return 'text/html';
379
-
380
- }
381
-
382
  }
36
 
37
  $this->settings = ITSEC_Modules::get_settings( 'backup' );
38
 
39
+ add_action( 'itsec_execute_backup_cron', array( $this, 'do_backup' ) );
 
40
  add_filter( 'itsec_logger_modules', array( $this, 'register_logger' ) );
41
 
42
+ if ( defined( 'ITSEC_BACKUP_CRON' ) && true === ITSEC_BACKUP_CRON ) {
43
+ if ( ! wp_next_scheduled( 'itsec_execute_backup_cron' ) ) {
44
+ wp_schedule_event( time(), 'daily', 'itsec_execute_backup_cron' );
45
+ }
 
 
 
46
 
47
+ // When ITSEC_BACKUP_CRON is enabled, skip the regular scheduling system.
48
+ return;
49
+ }
50
 
51
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
52
+ // Don't run on AJAX requests.
53
+ return;
54
+ }
55
 
56
+ if ( class_exists( 'pb_backupbuddy' ) ) {
57
+ // Don't run when BackupBuddy is active.
58
+ return;
59
+ }
60
 
61
+ if ( $this->settings['interval'] <= 0 ) {
62
+ // Don't run when the interval is zero or less.
63
+ return;
64
  }
65
 
66
+
67
+ $next_run = $this->settings['last_run'] + $this->settings['interval'] * DAY_IN_SECONDS;
68
+
69
+ if ( $next_run <= $itsec_globals['current_time_gmt'] ) {
70
+ add_action( 'init', array( $this, 'do_backup' ), 10, 0 );
71
+ }
72
  }
73
 
74
  /**
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();
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
 
225
  }
226
 
227
  if ( 2 !== $this->settings['method'] || true === $one_time ) {
228
+ require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-mailer.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
+ $raw_recipients = ITSEC_Modules::get_setting( 'global', 'backup_email' );
244
+ $recipients = array();
 
245
 
246
+ foreach ( $raw_recipients as $recipient ) {
247
+ $recipient = trim( $recipient );
248
 
249
+ if ( is_email( $recipient ) ) {
250
+ $recipients[] = $recipient;
251
  }
 
252
  }
253
 
254
+ $subject = sprintf( esc_html__( '[%s] Database Backup', 'better-wp-security' ), esc_url( network_home_url() ) );
255
+ $subject = apply_filters( 'itsec_backup_email_subject', $subject );
256
 
257
+ $attachment = array( "$dir/$file$fileext" );
258
+
259
+ $mail_success = $mail->send( $recipients, $subject, $attachment );
260
  }
261
 
262
  if ( 1 === $this->settings['method'] ) {
296
  }
297
 
298
  if ( false === $one_time ) {
 
299
  ITSEC_Modules::set_setting( 'backup', 'last_run', ITSEC_Core::get_current_time_gmt() );
 
300
  }
301
 
302
  switch ( $this->settings['method'] ) {
374
 
375
  }
376
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377
  }
core/modules/ban-users/lists/hackrepair-apache.inc CHANGED
@@ -48,7 +48,6 @@ RewriteCond %{HTTP_USER_AGENT} "^GrabNet" [NC,OR]
48
  RewriteCond %{HTTP_USER_AGENT} "^Grafula" [NC,OR]
49
  RewriteCond %{HTTP_USER_AGENT} "^harvest" [NC,OR]
50
  RewriteCond %{HTTP_USER_AGENT} "^HMView" [NC,OR]
51
- RewriteCond %{HTTP_USER_AGENT} "^ia_archiver" [NC,OR]
52
  RewriteCond %{HTTP_USER_AGENT} "^Image Stripper" [NC,OR]
53
  RewriteCond %{HTTP_USER_AGENT} "^Image Sucker" [NC,OR]
54
  RewriteCond %{HTTP_USER_AGENT} "^InterGET" [NC,OR]
@@ -106,7 +105,6 @@ RewriteCond %{HTTP_USER_AGENT} "^turnit" [NC,OR]
106
  RewriteCond %{HTTP_USER_AGENT} "^vikspider" [NC,OR]
107
  RewriteCond %{HTTP_USER_AGENT} "^VoidEYE" [NC,OR]
108
  RewriteCond %{HTTP_USER_AGENT} "^Web Image Collector" [NC,OR]
109
- RewriteCond %{HTTP_USER_AGENT} "^Web Sucker" [NC,OR]
110
  RewriteCond %{HTTP_USER_AGENT} "^WebAuto" [NC,OR]
111
  RewriteCond %{HTTP_USER_AGENT} "^WebBandit" [NC,OR]
112
  RewriteCond %{HTTP_USER_AGENT} "^WebCopier" [NC,OR]
48
  RewriteCond %{HTTP_USER_AGENT} "^Grafula" [NC,OR]
49
  RewriteCond %{HTTP_USER_AGENT} "^harvest" [NC,OR]
50
  RewriteCond %{HTTP_USER_AGENT} "^HMView" [NC,OR]
 
51
  RewriteCond %{HTTP_USER_AGENT} "^Image Stripper" [NC,OR]
52
  RewriteCond %{HTTP_USER_AGENT} "^Image Sucker" [NC,OR]
53
  RewriteCond %{HTTP_USER_AGENT} "^InterGET" [NC,OR]
105
  RewriteCond %{HTTP_USER_AGENT} "^vikspider" [NC,OR]
106
  RewriteCond %{HTTP_USER_AGENT} "^VoidEYE" [NC,OR]
107
  RewriteCond %{HTTP_USER_AGENT} "^Web Image Collector" [NC,OR]
 
108
  RewriteCond %{HTTP_USER_AGENT} "^WebAuto" [NC,OR]
109
  RewriteCond %{HTTP_USER_AGENT} "^WebBandit" [NC,OR]
110
  RewriteCond %{HTTP_USER_AGENT} "^WebCopier" [NC,OR]
core/modules/ban-users/lists/hackrepair-litespeed.inc CHANGED
@@ -48,7 +48,6 @@ RewriteCond %{HTTP_USER_AGENT} "^GrabNet" [NC,OR]
48
  RewriteCond %{HTTP_USER_AGENT} "^Grafula" [NC,OR]
49
  RewriteCond %{HTTP_USER_AGENT} "^harvest" [NC,OR]
50
  RewriteCond %{HTTP_USER_AGENT} "^HMView" [NC,OR]
51
- RewriteCond %{HTTP_USER_AGENT} "^ia_archiver" [NC,OR]
52
  RewriteCond %{HTTP_USER_AGENT} "^Image Stripper" [NC,OR]
53
  RewriteCond %{HTTP_USER_AGENT} "^Image Sucker" [NC,OR]
54
  RewriteCond %{HTTP_USER_AGENT} "^InterGET" [NC,OR]
@@ -106,7 +105,6 @@ RewriteCond %{HTTP_USER_AGENT} "^turnit" [NC,OR]
106
  RewriteCond %{HTTP_USER_AGENT} "^vikspider" [NC,OR]
107
  RewriteCond %{HTTP_USER_AGENT} "^VoidEYE" [NC,OR]
108
  RewriteCond %{HTTP_USER_AGENT} "^Web Image Collector" [NC,OR]
109
- RewriteCond %{HTTP_USER_AGENT} "^Web Sucker" [NC,OR]
110
  RewriteCond %{HTTP_USER_AGENT} "^WebAuto" [NC,OR]
111
  RewriteCond %{HTTP_USER_AGENT} "^WebBandit" [NC,OR]
112
  RewriteCond %{HTTP_USER_AGENT} "^WebCopier" [NC,OR]
48
  RewriteCond %{HTTP_USER_AGENT} "^Grafula" [NC,OR]
49
  RewriteCond %{HTTP_USER_AGENT} "^harvest" [NC,OR]
50
  RewriteCond %{HTTP_USER_AGENT} "^HMView" [NC,OR]
 
51
  RewriteCond %{HTTP_USER_AGENT} "^Image Stripper" [NC,OR]
52
  RewriteCond %{HTTP_USER_AGENT} "^Image Sucker" [NC,OR]
53
  RewriteCond %{HTTP_USER_AGENT} "^InterGET" [NC,OR]
105
  RewriteCond %{HTTP_USER_AGENT} "^vikspider" [NC,OR]
106
  RewriteCond %{HTTP_USER_AGENT} "^VoidEYE" [NC,OR]
107
  RewriteCond %{HTTP_USER_AGENT} "^Web Image Collector" [NC,OR]
 
108
  RewriteCond %{HTTP_USER_AGENT} "^WebAuto" [NC,OR]
109
  RewriteCond %{HTTP_USER_AGENT} "^WebBandit" [NC,OR]
110
  RewriteCond %{HTTP_USER_AGENT} "^WebCopier" [NC,OR]
core/modules/ban-users/lists/hackrepair-nginx.inc CHANGED
@@ -47,7 +47,6 @@ if ($http_user_agent ~* "^GrabNet"){return 403;}
47
  if ($http_user_agent ~* "^Grafula"){return 403;}
48
  if ($http_user_agent ~* "^harvest"){return 403;}
49
  if ($http_user_agent ~* "^HMView"){return 403;}
50
- if ($http_user_agent ~* "^ia_archiver"){return 403;}
51
  if ($http_user_agent ~* "^Image Stripper"){return 403;}
52
  if ($http_user_agent ~* "^Image Sucker"){return 403;}
53
  if ($http_user_agent ~* "^InterGET"){return 403;}
@@ -105,7 +104,6 @@ if ($http_user_agent ~* "^turnit"){return 403;}
105
  if ($http_user_agent ~* "^vikspider"){return 403;}
106
  if ($http_user_agent ~* "^VoidEYE"){return 403;}
107
  if ($http_user_agent ~* "^Web Image Collector"){return 403;}
108
- if ($http_user_agent ~* "^Web Sucker"){return 403;}
109
  if ($http_user_agent ~* "^WebAuto"){return 403;}
110
  if ($http_user_agent ~* "^WebBandit"){return 403;}
111
  if ($http_user_agent ~* "^WebCopier"){return 403;}
47
  if ($http_user_agent ~* "^Grafula"){return 403;}
48
  if ($http_user_agent ~* "^harvest"){return 403;}
49
  if ($http_user_agent ~* "^HMView"){return 403;}
 
50
  if ($http_user_agent ~* "^Image Stripper"){return 403;}
51
  if ($http_user_agent ~* "^Image Sucker"){return 403;}
52
  if ($http_user_agent ~* "^InterGET"){return 403;}
104
  if ($http_user_agent ~* "^vikspider"){return 403;}
105
  if ($http_user_agent ~* "^VoidEYE"){return 403;}
106
  if ($http_user_agent ~* "^Web Image Collector"){return 403;}
 
107
  if ($http_user_agent ~* "^WebAuto"){return 403;}
108
  if ($http_user_agent ~* "^WebBandit"){return 403;}
109
  if ($http_user_agent ~* "^WebCopier"){return 403;}
core/modules/file-change/scanner.php CHANGED
@@ -497,7 +497,7 @@ final class ITSEC_File_Change_Scanner {
497
 
498
  $dirs = array(
499
  'wp-admin/',
500
- 'wp-includes/',
501
  $content_dir[ sizeof( $content_dir ) - 1 ] . '/',
502
  $content_dir[ sizeof( $content_dir ) - 1 ] . '/uploads/',
503
  $content_dir[ sizeof( $content_dir ) - 1 ] . '/themes/',
497
 
498
  $dirs = array(
499
  'wp-admin/',
500
+ WPINC . '/',
501
  $content_dir[ sizeof( $content_dir ) - 1 ] . '/',
502
  $content_dir[ sizeof( $content_dir ) - 1 ] . '/uploads/',
503
  $content_dir[ sizeof( $content_dir ) - 1 ] . '/themes/',
core/modules/malware/class-ithemes-sync-verb-itsec-get-malware-scan-log.php CHANGED
@@ -3,34 +3,30 @@
3
  class Ithemes_Sync_Verb_ITSEC_Get_Malware_Scan_Log extends Ithemes_Sync_Verb {
4
  public static $name = 'itsec-get-malware-scan-log';
5
  public static $description = '';
6
-
7
  public $default_arguments = array(
8
  'count' => 10,
9
  );
10
-
11
  public function run( $arguments ) {
12
  $arguments = Ithemes_Sync_Functions::merge_defaults( $arguments, $this->default_arguments );
13
-
14
  global $itsec_logger;
15
-
16
- $items = $itsec_logger->get_events( 'malware' );
17
  $response = array();
18
-
19
  foreach ( $items as $item ) {
20
  $item['log_data'] = maybe_unserialize( $item['log_data'] );
21
-
22
  if ( ! isset( $item['log_data']['SCAN']['SITE'] ) ) {
23
  // Don't return old scan data.
24
  continue;
25
  }
26
-
27
  $response[] = $item;
28
-
29
- if ( ( $arguments['count'] > 0 ) && ( count( $response ) == $arguments['count'] ) ) {
30
- break;
31
- }
32
  }
33
-
34
  return $response;
35
  }
36
  }
3
  class Ithemes_Sync_Verb_ITSEC_Get_Malware_Scan_Log extends Ithemes_Sync_Verb {
4
  public static $name = 'itsec-get-malware-scan-log';
5
  public static $description = '';
6
+
7
  public $default_arguments = array(
8
  'count' => 10,
9
  );
10
+
11
  public function run( $arguments ) {
12
  $arguments = Ithemes_Sync_Functions::merge_defaults( $arguments, $this->default_arguments );
13
+
14
  global $itsec_logger;
15
+
16
+ $items = $itsec_logger->get_events( 'malware', array(), $arguments['count'] );
17
  $response = array();
18
+
19
  foreach ( $items as $item ) {
20
  $item['log_data'] = maybe_unserialize( $item['log_data'] );
21
+
22
  if ( ! isset( $item['log_data']['SCAN']['SITE'] ) ) {
23
  // Don't return old scan data.
24
  continue;
25
  }
26
+
27
  $response[] = $item;
 
 
 
 
28
  }
29
+
30
  return $response;
31
  }
32
  }
core/modules/malware/class-itsec-malware-scanner.php CHANGED
@@ -2,46 +2,46 @@
2
 
3
  final class ITSEC_Malware_Scanner {
4
  protected static $transient_name = 'itsec_cached_sucuri_scan';
5
-
6
  public static function scan() {
7
  global $itsec_logger;
8
-
9
-
10
  $results = self::get_scan_results();
11
-
12
  if ( is_array( $results ) && isset( $results['cached'] ) && $results['cached'] ) {
13
  return $results;
14
  }
15
-
16
-
17
  $user = wp_get_current_user();
18
  $itsec_logger->log_event( 'malware', 3, $results, ITSEC_Lib::get_ip(), $user->user_login, $user->ID );
19
-
20
  return $results;
21
  }
22
-
23
  protected static function get_scan_results() {
24
  $response = get_site_transient( self::$transient_name );
25
  $cached = true;
26
-
27
  if ( defined( 'ITSEC_TEST_MALWARE_SCAN_SKIP_CACHE' ) && ITSEC_TEST_MALWARE_SCAN_SKIP_CACHE ) {
28
  $cached = false;
29
  $response = false;
30
  }
31
-
32
-
33
  if ( false === $response ) {
34
  $cached = false;
35
-
36
  $scanner_url = 'https://sitecheck.sucuri.net/';
37
  $site_url = apply_filters( 'itsec_test_malware_scan_site_url', get_site_url() );
38
-
39
  if ( defined( 'ITSEC_TEST_MALWARE_SCAN_SITE_URL' ) ) {
40
  $site_url = ITSEC_TEST_MALWARE_SCAN_SITE_URL;
41
  }
42
-
43
  $site_url = preg_replace( '|^https?://|i', '', $site_url );
44
-
45
  $query_args = array(
46
  'scan' => $site_url,
47
  'p' => 'ithemes',
@@ -49,38 +49,38 @@ final class ITSEC_Malware_Scanner {
49
  'json' => 1,
50
  'time' => time(),
51
  );
52
-
53
  $key = apply_filters( 'itsec_sucuri_key', '' );
54
-
55
  if ( defined( 'ITSEC_SUCURI_KEY' ) ) {
56
  $key = ITSEC_SUCURI_KEY;
57
  }
58
-
59
  if ( ! empty( $key ) ) {
60
  $query_args['k'] = $key;
61
  }
62
-
63
- $scan_url = "$scanner_url?" . http_build_query( $query_args );
64
-
65
  $req_args = array(
66
  'timeout' => 300,
67
  );
68
-
69
  if ( defined( 'ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY' ) && ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY ) {
70
  $req_args['sslverify'] = false;
71
-
72
  // Ensure that another plugin isn't preventing the disabling of sslverify from working.
73
  add_filter( 'https_local_ssl_verify', '__return_false', 999999 );
74
  add_filter( 'https_ssl_verify', '__return_false', 999999 );
75
  }
76
-
77
  $response = wp_remote_get( $scan_url, $req_args );
78
-
79
  if ( defined( 'ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY' ) && ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY ) {
80
  remove_filter( 'https_local_ssl_verify', '__return_false', 999999 );
81
  remove_filter( 'https_ssl_verify', '__return_false', 999999 );
82
  }
83
-
84
  if ( is_wp_error( $response ) ) {
85
  return $response;
86
  }
@@ -92,13 +92,13 @@ final class ITSEC_Malware_Scanner {
92
  } else {
93
  return new WP_Error( 'itsec-malware-scanner-wp-remote-get-response-missing-body', __( 'The scan failed due to an unexpected technical error. The response from the wp_remote_get function does not contain a body entry. Since the body entry contains the response for the request to Sucuri\'s servers, the response cannot be processed. This could indicate a plugin/theme compatibility issue or a problem in WordPress.', 'better-wp-security' ), $response );
94
  }
95
-
96
  if ( empty( $body ) ) {
97
  return new WP_Error( 'itsec-malware-scanner-wp-remote-get-response-empty-body', __( 'The scan failed due to an unexpected technical error. The response from the wp_remote_get function contains an empty body entry. Since the body entry contains the response for the request to Sucuri\'s servers, the response cannot be processed. This could indicate a plugin/theme compatibility issue or a problem in WordPress.', 'better-wp-security' ), $response );
98
  }
99
-
100
  $body = @json_decode( $body, true );
101
-
102
  if ( is_null( $body ) && isset( $response['headers'] ) && isset( $response['headers']['content-type'] ) ) {
103
  if ( 'application/json' === $response['headers']['content-type'] ) {
104
  return new WP_Error( 'itsec-malware-scanner-invalid-json-data-in-scan-response', __( 'The scan did not complete successfully. The Sucuri server should send its response in JSON encoding. The response indicates that the encoding is JSON, but the data could not be decoded. This problem could be due to a temporary Sucuri server issue or a compatibility issue on your server. If the problem continues, please contact iThemes Security support.', 'better-wp-security' ), $response );
@@ -109,23 +109,23 @@ final class ITSEC_Malware_Scanner {
109
  if ( 'ERROR' === substr( $response['body'], 0, 5 ) ) {
110
  return new WP_Error( 'itsec-malware-scanner-error-received', sprintf( __( 'The scan did not complete successfully. Sucuri sent the following error: %s', 'better-wp-security' ), '<code>' . $response['body'] . '</code>' ), $response );
111
  }
112
-
113
  if ( ! empty( $response['response'] ) && ! empty( $response['response']['code'] ) ) {
114
  return new WP_Error( 'itsec-malware-scanner-unknown-scan-error', sprintf( __( 'An unknown error prevented the scan from completing successfully. The Sucuri server responded with a <code>%s</code> error code.', 'better-wp-security' ), $response['response']['code'] ), $response );
115
  }
116
-
117
  return new WP_Error( 'itsec-malware-scanner-wp-remote-get-response-malformed', __( 'The scan failed due to an unexpected technical error. The response from the wp_remote_get function is missing some critical information that is needed in order to properly process the response from Sucuri\'s servers. This could indicate a plugin/theme compatibility issue or a problem in WordPress.', 'better-wp-security' ), $response );
118
  }
119
-
120
-
121
  if ( ! $cached ) {
122
  set_site_transient( self::$transient_name, $response, 10 * MINUTE_IN_SECONDS );
123
  }
124
-
125
  if ( is_array( $body ) ) {
126
  $body['cached'] = $cached;
127
  }
128
-
129
  return $body;
130
  }
131
  }
2
 
3
  final class ITSEC_Malware_Scanner {
4
  protected static $transient_name = 'itsec_cached_sucuri_scan';
5
+
6
  public static function scan() {
7
  global $itsec_logger;
8
+
9
+
10
  $results = self::get_scan_results();
11
+
12
  if ( is_array( $results ) && isset( $results['cached'] ) && $results['cached'] ) {
13
  return $results;
14
  }
15
+
16
+
17
  $user = wp_get_current_user();
18
  $itsec_logger->log_event( 'malware', 3, $results, ITSEC_Lib::get_ip(), $user->user_login, $user->ID );
19
+
20
  return $results;
21
  }
22
+
23
  protected static function get_scan_results() {
24
  $response = get_site_transient( self::$transient_name );
25
  $cached = true;
26
+
27
  if ( defined( 'ITSEC_TEST_MALWARE_SCAN_SKIP_CACHE' ) && ITSEC_TEST_MALWARE_SCAN_SKIP_CACHE ) {
28
  $cached = false;
29
  $response = false;
30
  }
31
+
32
+
33
  if ( false === $response ) {
34
  $cached = false;
35
+
36
  $scanner_url = 'https://sitecheck.sucuri.net/';
37
  $site_url = apply_filters( 'itsec_test_malware_scan_site_url', get_site_url() );
38
+
39
  if ( defined( 'ITSEC_TEST_MALWARE_SCAN_SITE_URL' ) ) {
40
  $site_url = ITSEC_TEST_MALWARE_SCAN_SITE_URL;
41
  }
42
+
43
  $site_url = preg_replace( '|^https?://|i', '', $site_url );
44
+
45
  $query_args = array(
46
  'scan' => $site_url,
47
  'p' => 'ithemes',
49
  'json' => 1,
50
  'time' => time(),
51
  );
52
+
53
  $key = apply_filters( 'itsec_sucuri_key', '' );
54
+
55
  if ( defined( 'ITSEC_SUCURI_KEY' ) ) {
56
  $key = ITSEC_SUCURI_KEY;
57
  }
58
+
59
  if ( ! empty( $key ) ) {
60
  $query_args['k'] = $key;
61
  }
62
+
63
+ $scan_url = "$scanner_url?" . http_build_query( $query_args, '', '&' );
64
+
65
  $req_args = array(
66
  'timeout' => 300,
67
  );
68
+
69
  if ( defined( 'ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY' ) && ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY ) {
70
  $req_args['sslverify'] = false;
71
+
72
  // Ensure that another plugin isn't preventing the disabling of sslverify from working.
73
  add_filter( 'https_local_ssl_verify', '__return_false', 999999 );
74
  add_filter( 'https_ssl_verify', '__return_false', 999999 );
75
  }
76
+
77
  $response = wp_remote_get( $scan_url, $req_args );
78
+
79
  if ( defined( 'ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY' ) && ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY ) {
80
  remove_filter( 'https_local_ssl_verify', '__return_false', 999999 );
81
  remove_filter( 'https_ssl_verify', '__return_false', 999999 );
82
  }
83
+
84
  if ( is_wp_error( $response ) ) {
85
  return $response;
86
  }
92
  } else {
93
  return new WP_Error( 'itsec-malware-scanner-wp-remote-get-response-missing-body', __( 'The scan failed due to an unexpected technical error. The response from the wp_remote_get function does not contain a body entry. Since the body entry contains the response for the request to Sucuri\'s servers, the response cannot be processed. This could indicate a plugin/theme compatibility issue or a problem in WordPress.', 'better-wp-security' ), $response );
94
  }
95
+
96
  if ( empty( $body ) ) {
97
  return new WP_Error( 'itsec-malware-scanner-wp-remote-get-response-empty-body', __( 'The scan failed due to an unexpected technical error. The response from the wp_remote_get function contains an empty body entry. Since the body entry contains the response for the request to Sucuri\'s servers, the response cannot be processed. This could indicate a plugin/theme compatibility issue or a problem in WordPress.', 'better-wp-security' ), $response );
98
  }
99
+
100
  $body = @json_decode( $body, true );
101
+
102
  if ( is_null( $body ) && isset( $response['headers'] ) && isset( $response['headers']['content-type'] ) ) {
103
  if ( 'application/json' === $response['headers']['content-type'] ) {
104
  return new WP_Error( 'itsec-malware-scanner-invalid-json-data-in-scan-response', __( 'The scan did not complete successfully. The Sucuri server should send its response in JSON encoding. The response indicates that the encoding is JSON, but the data could not be decoded. This problem could be due to a temporary Sucuri server issue or a compatibility issue on your server. If the problem continues, please contact iThemes Security support.', 'better-wp-security' ), $response );
109
  if ( 'ERROR' === substr( $response['body'], 0, 5 ) ) {
110
  return new WP_Error( 'itsec-malware-scanner-error-received', sprintf( __( 'The scan did not complete successfully. Sucuri sent the following error: %s', 'better-wp-security' ), '<code>' . $response['body'] . '</code>' ), $response );
111
  }
112
+
113
  if ( ! empty( $response['response'] ) && ! empty( $response['response']['code'] ) ) {
114
  return new WP_Error( 'itsec-malware-scanner-unknown-scan-error', sprintf( __( 'An unknown error prevented the scan from completing successfully. The Sucuri server responded with a <code>%s</code> error code.', 'better-wp-security' ), $response['response']['code'] ), $response );
115
  }
116
+
117
  return new WP_Error( 'itsec-malware-scanner-wp-remote-get-response-malformed', __( 'The scan failed due to an unexpected technical error. The response from the wp_remote_get function is missing some critical information that is needed in order to properly process the response from Sucuri\'s servers. This could indicate a plugin/theme compatibility issue or a problem in WordPress.', 'better-wp-security' ), $response );
118
  }
119
+
120
+
121
  if ( ! $cached ) {
122
  set_site_transient( self::$transient_name, $response, 10 * MINUTE_IN_SECONDS );
123
  }
124
+
125
  if ( is_array( $body ) ) {
126
  $body['cached'] = $cached;
127
  }
128
+
129
  return $body;
130
  }
131
  }
core/modules/system-tweaks/config-generators.php CHANGED
@@ -4,25 +4,27 @@ final class ITSEC_System_Tweaks_Config_Generators {
4
  public static function filter_litespeed_server_config_modification( $modification ) {
5
  return self::filter_apache_server_config_modification( $modification, 'litespeed' );
6
  }
7
-
8
  public static function filter_apache_server_config_modification( $modification, $server = 'apache' ) {
 
 
9
  $input = ITSEC_Modules::get_settings( 'system-tweaks' );
10
-
 
11
  if ( $input['protect_files'] ) {
12
  $files = array(
13
  '.htaccess',
14
  'readme.html',
15
  'readme.txt',
16
- 'install.php',
17
  'wp-config.php',
18
  );
19
-
20
  $modification .= "\n";
21
  $modification .= "\t# " . __( 'Protect System Files - Security > Settings > System Tweaks > System Files', 'better-wp-security' ) . "\n";
22
-
23
  foreach ( $files as $file ) {
24
  $modification .= "\t<files $file>\n";
25
-
26
  if ( 'apache' === $server ) {
27
  $modification .= "\t\t<IfModule mod_authz_core.c>\n";
28
  $modification .= "\t\t\tRequire all denied\n";
@@ -37,84 +39,111 @@ final class ITSEC_System_Tweaks_Config_Generators {
37
  $modification .= "\t\t\tDeny from all\n";
38
  $modification .= "\t\t</IfModule>\n";
39
  }
40
-
41
  $modification .= "\t</files>\n";
42
  }
43
  }
44
-
45
  if ( $input['directory_browsing'] ) {
46
  $modification .= "\n";
47
  $modification .= "\t# " . __( 'Disable Directory Browsing - Security > Settings > System Tweaks > Directory Browsing', 'better-wp-security' ) . "\n";
48
  $modification .= "\tOptions -Indexes\n";
49
  }
50
-
51
-
52
  $rewrites = '';
53
-
54
  if ( $input['protect_files'] ) {
55
  $rewrites .= "\n";
56
  $rewrites .= "\t\t# " . __( 'Protect System Files - Security > Settings > System Tweaks > System Files', 'better-wp-security' ) . "\n";
 
57
  $rewrites .= "\t\tRewriteRule ^wp-admin/includes/ - [F]\n";
58
- $rewrites .= "\t\tRewriteRule !^wp-includes/ - [S=3]\n";
59
- $rewrites .= "\t\tRewriteCond %{SCRIPT_FILENAME} !^(.*)wp-includes/ms-files.php\n";
60
- $rewrites .= "\t\tRewriteRule ^wp-includes/[^/]+\.php$ - [F]\n";
61
- $rewrites .= "\t\tRewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F]\n";
62
- $rewrites .= "\t\tRewriteRule ^wp-includes/theme-compat/ - [F]\n";
 
 
 
 
63
  }
64
-
65
  if ( $input['uploads_php'] ) {
66
- require_once( $GLOBALS['itsec_globals']['plugin_dir'] . 'core/lib/class-itsec-lib-utility.php' );
67
-
68
  $dir = ITSEC_Lib_Utility::get_relative_upload_url_path();
69
-
70
  if ( ! empty( $dir ) ) {
71
  $dir = preg_quote( $dir );
72
-
73
  $rewrites .= "\n";
74
- $rewrites .= "\t\t# " . __( 'Disable PHP in Uploads - Security > Settings > System Tweaks > Uploads', 'better-wp-security' ) . "\n";
75
- $rewrites .= "\t\tRewriteRule ^$dir/.*\.(?:php[1-6]?|pht|phtml?)$ - [NC,F]\n";
76
  }
77
  }
78
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  if ( $input['request_methods'] ) {
80
  $rewrites .= "\n";
81
  $rewrites .= "\t\t# " . __( 'Filter Request Methods - Security > Settings > System Tweaks > Request Methods', 'better-wp-security' ) . "\n";
82
  $rewrites .= "\t\tRewriteCond %{REQUEST_METHOD} ^(TRACE|DELETE|TRACK) [NC]\n";
83
  $rewrites .= "\t\tRewriteRule ^.* - [F]\n";
84
  }
85
-
86
  if ( $input['suspicious_query_strings'] ) {
87
  $rewrites .= "\n";
88
  $rewrites .= "\t\t# " . __( 'Filter Suspicious Query Strings in the URL - Security > Settings > System Tweaks > Suspicious Query Strings', 'better-wp-security' ) . "\n";
89
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} \.\.\/ [NC,OR]\n";
90
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} ^.*\.(bash|git|hg|log|svn|swp|cvs) [NC,OR]\n";
91
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} etc/passwd [NC,OR]\n";
92
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} boot\.ini [NC,OR]\n";
93
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} ftp\: [NC,OR]\n";
94
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} http\: [NC,OR]\n";
95
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} https\: [NC,OR]\n";
96
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]\n";
97
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|%3D) [NC,OR]\n";
98
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]\n";
99
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} ^.*(%24&x).* [NC,OR]\n";
100
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} ^.*(127\.0).* [NC,OR]\n";
101
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} ^.*(globals|encode|localhost|loopback).* [NC,OR]\n";
102
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} ^.*(request|concat|insert|union|declare).* [NC]\n";
 
103
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} !^loggedout=true\n";
104
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} !^action=jetpack-sso\n";
105
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} !^action=rp\n";
106
- $rewrites .= "\t\tRewriteCond %{HTTP_COOKIE} !^.*wordpress_logged_in_.*$\n";
107
- $rewrites .= "\t\tRewriteCond %{HTTP_REFERER} !^http://maps\.googleapis\.com(.*)$\n";
108
  $rewrites .= "\t\tRewriteRule ^.* - [F]\n";
109
  }
110
-
111
  if ( $input['non_english_characters'] ) {
112
  $rewrites .= "\n";
113
  $rewrites .= "\t\t# " . __( 'Filter Non-English Characters - Security > Settings > System Tweaks > Non-English Characters', 'better-wp-security' ) . "\n";
114
- $rewrites .= "\t\tRewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%E|%F).* [NC]\n";
115
  $rewrites .= "\t\tRewriteRule ^.* - [F]\n";
116
  }
117
-
118
  if ( ! empty( $rewrites ) ) {
119
  $modification .= "\n";
120
  $modification .= "\t<IfModule mod_rewrite.c>\n";
@@ -122,91 +151,136 @@ final class ITSEC_System_Tweaks_Config_Generators {
122
  $modification .= $rewrites;
123
  $modification .= "\t</IfModule>\n";
124
  }
125
-
126
-
127
  return $modification;
128
  }
129
-
130
  public static function filter_nginx_server_config_modification( $modification ) {
 
 
131
  $input = ITSEC_Modules::get_settings( 'system-tweaks' );
132
-
 
133
  if ( $input['protect_files'] ) {
 
 
 
 
 
 
 
 
134
  $modification .= "\n";
135
  $modification .= "\t# " . __( 'Protect System Files - Security > Settings > System Tweaks > System Files', 'better-wp-security' ) . "\n";
136
- $modification .= "\tlocation ~ /\.ht { deny all; }\n";
137
- $modification .= "\tlocation ~ wp-config.php { deny all; }\n";
138
- $modification .= "\tlocation ~ readme.html { deny all; }\n";
139
- $modification .= "\tlocation ~ readme.txt { deny all; }\n";
140
- $modification .= "\tlocation ~ /install.php { deny all; }\n";
141
- $modification .= "\tlocation ^wp-includes/(.*).php { deny all; }\n";
142
- $modification .= "\tlocation ^/wp-admin/includes(.*)$ { deny all; }\n";
143
- }
144
-
 
 
 
 
 
 
 
 
 
145
  // Rewrite Rules for Disable PHP in Uploads
146
  if ( $input['uploads_php'] ) {
147
- require_once( $GLOBALS['itsec_globals']['plugin_dir'] . 'core/lib/class-itsec-lib-utility.php' );
148
-
149
  $dir = ITSEC_Lib_Utility::get_relative_upload_url_path();
150
-
151
  if ( ! empty( $dir ) ) {
152
  $dir = preg_quote( $dir );
153
-
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  $modification .= "\n";
155
- $modification .= "\t# " . __( 'Disable PHP in Uploads - Security > Settings > System Tweaks > Uploads', 'better-wp-security' ) . "\n";
156
- $modification .= "\tlocation ^$dir/(.*).php(.?) { deny all; }\n";
157
  }
158
  }
159
-
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  // Apache rewrite rules for disable http methods
161
  if ( $input['request_methods'] ) {
162
  $modification .= "\n";
163
  $modification .= "\t# " . __( 'Filter Request Methods - Security > Settings > System Tweaks > Request Methods', 'better-wp-security' ) . "\n";
164
- $modification .= "\tif (\$request_method ~* \"^(TRACE|DELETE|TRACK)\") { return 403; }\n";
165
  }
166
-
167
  // Process suspicious query rules
168
  if ( $input['suspicious_query_strings'] ) {
169
  $modification .= "\n";
170
  $modification .= "\t# " . __( 'Filter Suspicious Query Strings in the URL - Security > Settings > System Tweaks > Suspicious Query Strings', 'better-wp-security' ) . "\n";
171
  $modification .= "\tset \$susquery 0;\n";
172
- $modification .= "\tif (\$args ~* \"\\.\\./\") { set \$susquery 1; }\n";
173
- $modification .= "\tif (\$args ~* \"\.(bash|git|hg|log|svn|swp|cvs)\") { set \$susquery 1; }\n";
174
- $modification .= "\tif (\$args ~* \"etc/passwd\") { set \$susquery 1; }\n";
175
- $modification .= "\tif (\$args ~* \"boot.ini\") { set \$susquery 1; }\n";
176
- $modification .= "\tif (\$args ~* \"ftp:\") { set \$susquery 1; }\n";
177
- $modification .= "\tif (\$args ~* \"http:\") { set \$susquery 1; }\n";
178
- $modification .= "\tif (\$args ~* \"https:\") { set \$susquery 1; }\n";
179
- $modification .= "\tif (\$args ~* \"(<|%3C).*script.*(>|%3E)\") { set \$susquery 1; }\n";
180
- $modification .= "\tif (\$args ~* \"mosConfig_[a-zA-Z_]{1,21}(=|%3D)\") { set \$susquery 1; }\n";
181
- $modification .= "\tif (\$args ~* \"base64_encode\") { set \$susquery 1; }\n";
182
- $modification .= "\tif (\$args ~* \"(%24&x)\") { set \$susquery 1; }\n";
183
- $modification .= "\tif (\$args ~* \"(127.0)\") { set \$susquery 1; }\n";
184
- $modification .= "\tif (\$args ~* \"(globals|encode|localhost|loopback)\") { set \$susquery 1; }\n";
185
- $modification .= "\tif (\$args ~* \"(request|insert|concat|union|declare)\") { set \$susquery 1; }\n";
186
- $modification .= "\tif (\$args !~ \"^loggedout=true\") { set \$susquery 0; }\n";
187
- $modification .= "\tif (\$args !~ \"^action=jetpack-sso\") { set \$susquery 0; }\n";
188
- $modification .= "\tif (\$args !~ \"^action=rp\") { set \$susquery 0; }\n";
189
- $modification .= "\tif (\$http_cookie !~ \"^.*wordpress_logged_in_.*\$\") { set \$susquery 0; }\n";
190
- $modification .= "\tif (\$http_referer !~ \"^http://maps.googleapis.com(.*)\$\") { set \$susquery 0; }\n";
191
- $modification .= "\tif (\$susquery = 1) { return 403; } \n";
192
- }
193
-
 
194
  // Process filtering of foreign characters
195
  if ( $input['non_english_characters'] ) {
196
  $modification .= "\n";
197
  $modification .= "\t# " . __( 'Filter Non-English Characters - Security > Settings > System Tweaks > Non-English Characters', 'better-wp-security' ) . "\n";
198
- $modification .= "\tif (\$args ~* \"(%0|%A|%B|%C|%D|%E|%F)\") { return 403; }\n";
199
  }
200
-
201
  return $modification;
202
  }
203
-
204
  protected static function get_valid_referers( $server_type ) {
205
  $valid_referers = array();
206
-
207
  if ( 'apache' === $server_type ) {
208
  $domain = ITSEC_Lib::get_domain( get_site_url() );
209
-
210
  if ( '*' == $domain ) {
211
  $valid_referers[] = $domain;
212
  } else {
@@ -217,20 +291,20 @@ final class ITSEC_System_Tweaks_Config_Generators {
217
  } else {
218
  return array();
219
  }
220
-
221
  $valid_referers[] = 'jetpack.wordpress.com/jetpack-comment/';
222
  $valid_referers = apply_filters( 'itsec_filter_valid_comment_referers', $valid_referers, $server_type );
223
-
224
  if ( is_string( $valid_referers ) ) {
225
  $valid_referers = array( $valid_referers );
226
  } else if ( ! is_array( $valid_referers ) ) {
227
  $valid_referers = array();
228
  }
229
-
230
  foreach ( $valid_referers as $index => $referer ) {
231
  $valid_referers[$index] = preg_replace( '|^https?://|', '', $referer );
232
  }
233
-
234
  return $valid_referers;
235
  }
236
  }
4
  public static function filter_litespeed_server_config_modification( $modification ) {
5
  return self::filter_apache_server_config_modification( $modification, 'litespeed' );
6
  }
7
+
8
  public static function filter_apache_server_config_modification( $modification, $server = 'apache' ) {
9
+ require_once( $GLOBALS['itsec_globals']['plugin_dir'] . 'core/lib/class-itsec-lib-utility.php' );
10
+
11
  $input = ITSEC_Modules::get_settings( 'system-tweaks' );
12
+ $wp_includes = WPINC;
13
+
14
  if ( $input['protect_files'] ) {
15
  $files = array(
16
  '.htaccess',
17
  'readme.html',
18
  'readme.txt',
 
19
  'wp-config.php',
20
  );
21
+
22
  $modification .= "\n";
23
  $modification .= "\t# " . __( 'Protect System Files - Security > Settings > System Tweaks > System Files', 'better-wp-security' ) . "\n";
24
+
25
  foreach ( $files as $file ) {
26
  $modification .= "\t<files $file>\n";
27
+
28
  if ( 'apache' === $server ) {
29
  $modification .= "\t\t<IfModule mod_authz_core.c>\n";
30
  $modification .= "\t\t\tRequire all denied\n";
39
  $modification .= "\t\t\tDeny from all\n";
40
  $modification .= "\t\t</IfModule>\n";
41
  }
42
+
43
  $modification .= "\t</files>\n";
44
  }
45
  }
46
+
47
  if ( $input['directory_browsing'] ) {
48
  $modification .= "\n";
49
  $modification .= "\t# " . __( 'Disable Directory Browsing - Security > Settings > System Tweaks > Directory Browsing', 'better-wp-security' ) . "\n";
50
  $modification .= "\tOptions -Indexes\n";
51
  }
52
+
53
+
54
  $rewrites = '';
55
+
56
  if ( $input['protect_files'] ) {
57
  $rewrites .= "\n";
58
  $rewrites .= "\t\t# " . __( 'Protect System Files - Security > Settings > System Tweaks > System Files', 'better-wp-security' ) . "\n";
59
+ $rewrites .= "\t\tRewriteRule ^wp-admin/install\.php$ - [F]\n";
60
  $rewrites .= "\t\tRewriteRule ^wp-admin/includes/ - [F]\n";
61
+
62
+ if ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) {
63
+ $rewrites .= "\t\tRewriteRule ^$wp_includes/ms-files.php$ - [S=4]\n";
64
+ }
65
+
66
+ $rewrites .= "\t\tRewriteRule !^$wp_includes/ - [S=3]\n";
67
+ $rewrites .= "\t\tRewriteRule ^$wp_includes/[^/]+\.php$ - [F]\n";
68
+ $rewrites .= "\t\tRewriteRule ^$wp_includes/js/tinymce/langs/.+\.php - [F]\n";
69
+ $rewrites .= "\t\tRewriteRule ^$wp_includes/theme-compat/ - [F]\n";
70
  }
71
+
72
  if ( $input['uploads_php'] ) {
 
 
73
  $dir = ITSEC_Lib_Utility::get_relative_upload_url_path();
74
+
75
  if ( ! empty( $dir ) ) {
76
  $dir = preg_quote( $dir );
77
+
78
  $rewrites .= "\n";
79
+ $rewrites .= "\t\t# " . __( 'Disable PHP in Uploads - Security > Settings > System Tweaks > PHP in Uploads', 'better-wp-security' ) . "\n";
80
+ $rewrites .= "\t\tRewriteRule ^$dir/.*\.(?:php[1-7]?|pht|phtml?|phps)$ - [NC,F]\n";
81
  }
82
  }
83
+
84
+ if ( $input['plugins_php'] ) {
85
+ $dir = ITSEC_Lib_Utility::get_relative_url_path( WP_PLUGIN_URL );
86
+
87
+ if ( ! empty( $dir ) ) {
88
+ $dir = preg_quote( $dir );
89
+
90
+ $rewrites .= "\n";
91
+ $rewrites .= "\t\t# " . __( 'Disable PHP in Plugins - Security > Settings > System Tweaks > PHP in Plugins', 'better-wp-security' ) . "\n";
92
+ $rewrites .= "\t\tRewriteRule ^$dir/.*\.(?:php[1-7]?|pht|phtml?|phps)$ - [NC,F]\n";
93
+ }
94
+ }
95
+
96
+ if ( $input['themes_php'] ) {
97
+ $dir = ITSEC_Lib_Utility::get_relative_url_path( get_theme_root_uri() );
98
+
99
+ if ( ! empty( $dir ) ) {
100
+ $dir = preg_quote( $dir );
101
+
102
+ $rewrites .= "\n";
103
+ $rewrites .= "\t\t# " . __( 'Disable PHP in Themes - Security > Settings > System Tweaks > PHP in Themes', 'better-wp-security' ) . "\n";
104
+ $rewrites .= "\t\tRewriteRule ^$dir/.*\.(?:php[1-7]?|pht|phtml?|phps)$ - [NC,F]\n";
105
+ }
106
+ }
107
+
108
  if ( $input['request_methods'] ) {
109
  $rewrites .= "\n";
110
  $rewrites .= "\t\t# " . __( 'Filter Request Methods - Security > Settings > System Tweaks > Request Methods', 'better-wp-security' ) . "\n";
111
  $rewrites .= "\t\tRewriteCond %{REQUEST_METHOD} ^(TRACE|DELETE|TRACK) [NC]\n";
112
  $rewrites .= "\t\tRewriteRule ^.* - [F]\n";
113
  }
114
+
115
  if ( $input['suspicious_query_strings'] ) {
116
  $rewrites .= "\n";
117
  $rewrites .= "\t\t# " . __( 'Filter Suspicious Query Strings in the URL - Security > Settings > System Tweaks > Suspicious Query Strings', 'better-wp-security' ) . "\n";
118
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} \.\.\/ [OR]\n";
119
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} \.(bash|git|hg|log|svn|swp|cvs) [NC,OR]\n";
120
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} etc/passwd [NC,OR]\n";
121
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} boot\.ini [NC,OR]\n";
122
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} ftp: [NC,OR]\n";
123
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} https?: [NC,OR]\n";
124
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} (<|%3C)script(>|%3E) [NC,OR]\n";
 
125
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|%3D) [NC,OR]\n";
126
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} base64_decode\( [NC,OR]\n";
127
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} %24&x [NC,OR]\n";
128
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} 127\.0 [NC,OR]\n";
129
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} (globals|encode|localhost|loopback) [NC,OR]\n";
130
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} (request|concat|insert|union|declare) [NC,OR]\n";
131
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} %[01][0-9A-F] [NC]\n";
132
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} !^loggedout=true\n";
133
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} !^action=jetpack-sso\n";
134
  $rewrites .= "\t\tRewriteCond %{QUERY_STRING} !^action=rp\n";
135
+ $rewrites .= "\t\tRewriteCond %{HTTP_COOKIE} !wordpress_logged_in_\n";
136
+ $rewrites .= "\t\tRewriteCond %{HTTP_REFERER} !^http://maps\.googleapis\.com\n";
137
  $rewrites .= "\t\tRewriteRule ^.* - [F]\n";
138
  }
139
+
140
  if ( $input['non_english_characters'] ) {
141
  $rewrites .= "\n";
142
  $rewrites .= "\t\t# " . __( 'Filter Non-English Characters - Security > Settings > System Tweaks > Non-English Characters', 'better-wp-security' ) . "\n";
143
+ $rewrites .= "\t\tRewriteCond %{QUERY_STRING} %[A-F][0-9A-F] [NC]\n";
144
  $rewrites .= "\t\tRewriteRule ^.* - [F]\n";
145
  }
146
+
147
  if ( ! empty( $rewrites ) ) {
148
  $modification .= "\n";
149
  $modification .= "\t<IfModule mod_rewrite.c>\n";
151
  $modification .= $rewrites;
152
  $modification .= "\t</IfModule>\n";
153
  }
154
+
155
+
156
  return $modification;
157
  }
158
+
159
  public static function filter_nginx_server_config_modification( $modification ) {
160
+ require_once( $GLOBALS['itsec_globals']['plugin_dir'] . 'core/lib/class-itsec-lib-utility.php' );
161
+
162
  $input = ITSEC_Modules::get_settings( 'system-tweaks' );
163
+ $wp_includes = WPINC;
164
+
165
  if ( $input['protect_files'] ) {
166
+ $config_file = ITSEC_Lib::get_htaccess();
167
+
168
+ if ( 0 === strpos( $config_file, ABSPATH ) ) {
169
+ $config_file = '/' . substr( $config_file, strlen( ABSPATH ) );
170
+ } else {
171
+ $config_file = '/nginx.conf';
172
+ }
173
+
174
  $modification .= "\n";
175
  $modification .= "\t# " . __( 'Protect System Files - Security > Settings > System Tweaks > System Files', 'better-wp-security' ) . "\n";
176
+ $modification .= "\tlocation = /wp-admin/install\.php { deny all; }\n";
177
+ $modification .= "\tlocation = $config_file { deny all; }\n";
178
+ $modification .= "\tlocation ~ /\.htaccess$ { deny all; }\n";
179
+ $modification .= "\tlocation ~ /readme\.html$ { deny all; }\n";
180
+ $modification .= "\tlocation ~ /readme\.txt$ { deny all; }\n";
181
+ $modification .= "\tlocation ~ /wp-config.php$ { deny all; }\n";
182
+ $modification .= "\tlocation ~ ^/wp-admin/includes/ { deny all; }\n";
183
+
184
+ if ( ! is_multisite() || ! get_site_option( 'ms_files_rewriting' ) ) {
185
+ // nginx can only reliably block PHP files in wp-includes if requests to wp-includes/ms-files.php are
186
+ // not required. This is because there is no skip directive as Apache has.
187
+ $modification .= "\tlocation ~ ^/$wp_includes/[^/]+\.php$ { deny all; }\n";
188
+ }
189
+
190
+ $modification .= "\tlocation ~ ^/$wp_includes/js/tinymce/langs/.+\.php$ { deny all; }\n";
191
+ $modification .= "\tlocation ~ ^/$wp_includes/theme-compat/ { deny all; }\n";
192
+ }
193
+
194
  // Rewrite Rules for Disable PHP in Uploads
195
  if ( $input['uploads_php'] ) {
 
 
196
  $dir = ITSEC_Lib_Utility::get_relative_upload_url_path();
197
+
198
  if ( ! empty( $dir ) ) {
199
  $dir = preg_quote( $dir );
200
+
201
+ $modification .= "\n";
202
+ $modification .= "\t# " . __( 'Disable PHP in Uploads - Security > Settings > System Tweaks > PHP in Uploads', 'better-wp-security' ) . "\n";
203
+ $modification .= "\tlocation ~ ^/$dir/.*\.(?:php[1-7]?|pht|phtml?|phps)$ { deny all; }\n";
204
+ }
205
+ }
206
+
207
+ // Rewrite Rules for Disable PHP in Plugins
208
+ if ( $input['plugins_php'] ) {
209
+ $dir = ITSEC_Lib_Utility::get_relative_url_path( WP_PLUGIN_URL );
210
+
211
+ if ( ! empty( $dir ) ) {
212
+ $dir = preg_quote( $dir );
213
+
214
  $modification .= "\n";
215
+ $modification .= "\t# " . __( 'Disable PHP in Plugins - Security > Settings > System Tweaks > PHP in Plugins', 'better-wp-security' ) . "\n";
216
+ $modification .= "\tlocation ~ ^/$dir/.*\.(?:php[1-7]?|pht|phtml?|phps)$ { deny all; }\n";
217
  }
218
  }
219
+
220
+ // Rewrite Rules for Disable PHP in Themes
221
+ if ( $input['themes_php'] ) {
222
+ $dir = ITSEC_Lib_Utility::get_relative_url_path( get_theme_root_uri() );
223
+
224
+ if ( ! empty( $dir ) ) {
225
+ $dir = preg_quote( $dir );
226
+
227
+ $modification .= "\n";
228
+ $modification .= "\t# " . __( 'Disable PHP in Themes - Security > Settings > System Tweaks > PHP in Themes', 'better-wp-security' ) . "\n";
229
+ $modification .= "\tlocation ~ ^/$dir/.*\.(?:php[1-7]?|pht|phtml?|phps)$ { deny all; }\n";
230
+ }
231
+ }
232
+
233
  // Apache rewrite rules for disable http methods
234
  if ( $input['request_methods'] ) {
235
  $modification .= "\n";
236
  $modification .= "\t# " . __( 'Filter Request Methods - Security > Settings > System Tweaks > Request Methods', 'better-wp-security' ) . "\n";
237
+ $modification .= "\tif ( \$request_method ~* ^(TRACE|DELETE|TRACK)$ ) { return 403; }\n";
238
  }
239
+
240
  // Process suspicious query rules
241
  if ( $input['suspicious_query_strings'] ) {
242
  $modification .= "\n";
243
  $modification .= "\t# " . __( 'Filter Suspicious Query Strings in the URL - Security > Settings > System Tweaks > Suspicious Query Strings', 'better-wp-security' ) . "\n";
244
  $modification .= "\tset \$susquery 0;\n";
245
+ $modification .= "\tif ( \$args ~* \"\.\./\" ) { set \$susquery 1; }\n";
246
+ $modification .= "\tif ( \$args ~* \"\.(bash|git|hg|log|svn|swp|cvs)\" ) { set \$susquery 1; }\n";
247
+ $modification .= "\tif ( \$args ~* \"etc/passwd\" ) { set \$susquery 1; }\n";
248
+ $modification .= "\tif ( \$args ~* \"boot\.ini\" ) { set \$susquery 1; }\n";
249
+ $modification .= "\tif ( \$args ~* \"ftp:\" ) { set \$susquery 1; }\n";
250
+ $modification .= "\tif ( \$args ~* \"https?:\" ) { set \$susquery 1; }\n";
251
+ $modification .= "\tif ( \$args ~* \"(<|%3C)script(>|%3E)\" ) { set \$susquery 1; }\n";
252
+ $modification .= "\tif ( \$args ~* \"mosConfig_[a-zA-Z_]{1,21}(=|%3D)\" ) { set \$susquery 1; }\n";
253
+ $modification .= "\tif ( \$args ~* \"base64_decode\(\" ) { set \$susquery 1; }\n";
254
+ $modification .= "\tif ( \$args ~* \"%24&x\" ) { set \$susquery 1; }\n";
255
+ $modification .= "\tif ( \$args ~* \"127\.0\" ) { set \$susquery 1; }\n";
256
+ $modification .= "\tif ( \$args ~* \"(globals|encode|localhost|loopback)\" ) { set \$susquery 1; }\n";
257
+ $modification .= "\tif ( \$args ~* \"(request|insert|concat|union|declare)\" ) { set \$susquery 1; }\n";
258
+ $modification .= "\tif ( \$args ~* \"%[01][0-9A-F]\" ) { set \$susquery 1; }\n";
259
+ $modification .= "\tif ( \$args ~ \"^loggedout=true\" ) { set \$susquery 0; }\n";
260
+ $modification .= "\tif ( \$args ~ \"^action=jetpack-sso\" ) { set \$susquery 0; }\n";
261
+ $modification .= "\tif ( \$args ~ \"^action=rp\" ) { set \$susquery 0; }\n";
262
+ $modification .= "\tif ( \$http_cookie ~ \"wordpress_logged_in_\" ) { set \$susquery 0; }\n";
263
+ $modification .= "\tif ( \$http_referer ~* \"^https?://maps\.googleapis\.com/\" ) { set \$susquery 0; }\n";
264
+ $modification .= "\tif ( \$susquery = 1 ) { return 403; }\n";
265
+
266
+ }
267
+
268
  // Process filtering of foreign characters
269
  if ( $input['non_english_characters'] ) {
270
  $modification .= "\n";
271
  $modification .= "\t# " . __( 'Filter Non-English Characters - Security > Settings > System Tweaks > Non-English Characters', 'better-wp-security' ) . "\n";
272
+ $modification .= "\tif (\$args ~* \"%[A-F][0-9A-F]\") { return 403; }\n";
273
  }
274
+
275
  return $modification;
276
  }
277
+
278
  protected static function get_valid_referers( $server_type ) {
279
  $valid_referers = array();
280
+
281
  if ( 'apache' === $server_type ) {
282
  $domain = ITSEC_Lib::get_domain( get_site_url() );
283
+
284
  if ( '*' == $domain ) {
285
  $valid_referers[] = $domain;
286
  } else {
291
  } else {
292
  return array();
293
  }
294
+
295
  $valid_referers[] = 'jetpack.wordpress.com/jetpack-comment/';
296
  $valid_referers = apply_filters( 'itsec_filter_valid_comment_referers', $valid_referers, $server_type );
297
+
298
  if ( is_string( $valid_referers ) ) {
299
  $valid_referers = array( $valid_referers );
300
  } else if ( ! is_array( $valid_referers ) ) {
301
  $valid_referers = array();
302
  }
303
+
304
  foreach ( $valid_referers as $index => $referer ) {
305
  $valid_referers[$index] = preg_replace( '|^https?://|', '', $referer );
306
  }
307
+
308
  return $valid_referers;
309
  }
310
  }
core/modules/system-tweaks/settings-page.php CHANGED
@@ -6,91 +6,107 @@ final class ITSEC_System_Tweaks_Settings_Page extends ITSEC_Module_Settings_Page
6
  $this->title = __( 'System Tweaks', 'better-wp-security' );
7
  $this->description = __( 'Advanced settings that improve security by changing the server config for this site.', 'better-wp-security' );
8
  $this->type = 'recommended';
9
-
10
  parent::__construct();
11
  }
12
-
13
  protected function render_description( $form ) {
14
-
15
  ?>
16
- <p><?php _e( 'These are advanced settings that may be utilized to further strengthen the security of your WordPress site.', 'better-wp-security' ); ?></p>
17
  <?php
18
-
19
  }
20
-
21
  protected function render_settings( $form ) {
22
-
23
  ?>
24
- <p><?php _e( 'Note: These settings are listed as advanced because they block common forms of attacks but they can also block legitimate plugins and themes that rely on the same techniques. When activating the settings below, we recommend enabling them one by one to test that everything on your site is still working as expected.', 'better-wp-security' ); ?></p>
25
- <p><?php _e( 'Remember, some of these settings might conflict with other plugins or themes, so test your site after enabling each setting.', 'better-wp-security' ); ?></p>
26
  <table class="form-table">
27
  <tr>
28
- <th scope="row"><label for="itsec-system-tweaks-protect_files"><?php _e( 'System Files', 'better-wp-security' ); ?></label></th>
29
  <td>
30
  <?php $form->add_checkbox( 'protect_files' ); ?>
31
- <label for="itsec-system-tweaks-protect_files"><?php _e( 'Protect System Files', 'better-wp-security' ); ?></label>
32
- <p class="description"><?php _e( 'Prevent public access to readme.html, readme.txt, wp-config.php, install.php, wp-includes, and .htaccess. These files can give away important information on your site and serve no purpose to the public once WordPress has been successfully installed.', 'better-wp-security' ); ?></p>
33
  </td>
34
  </tr>
35
  <tr>
36
- <th scope="row"><label for="itsec-system-tweaks-directory_browsing"><?php _e( 'Directory Browsing', 'better-wp-security' ); ?></label></th>
37
  <td>
38
  <?php $form->add_checkbox( 'directory_browsing' ); ?>
39
- <label for="itsec-system-tweaks-directory_browsing"><?php _e( 'Disable Directory Browsing', 'better-wp-security' ); ?></label>
40
- <p class="description"><?php _e( 'Prevents users from seeing a list of files in a directory when no index file is present.', 'better-wp-security' ); ?></p>
41
  </td>
42
  </tr>
43
  <tr>
44
- <th scope="row"><label for="itsec-system-tweaks-request_methods"><?php _e( 'Request Methods', 'better-wp-security' ); ?></label></th>
45
  <td>
46
  <?php $form->add_checkbox( 'request_methods' ); ?>
47
- <label for="itsec-system-tweaks-request_methods"><?php _e( 'Filter Request Methods', 'better-wp-security' ); ?></label>
48
- <p class="description"><?php _e( 'Filter out hits with the trace, delete, or track request methods.', 'better-wp-security' ); ?></p>
49
  </td>
50
  </tr>
51
  <tr>
52
- <th scope="row"><label for="itsec-system-tweaks-suspicious_query_strings"><?php _e( 'Suspicious Query Strings', 'better-wp-security' ); ?></label></th>
53
  <td>
54
  <?php $form->add_checkbox( 'suspicious_query_strings' ); ?>
55
- <label for="itsec-system-tweaks-suspicious_query_strings"><?php _e( 'Filter Suspicious Query Strings in the URL', 'better-wp-security' ); ?></label>
56
- <p class="description"><?php _e( 'These are very often signs of someone trying to gain access to your site but some plugins and themes can also be blocked.', 'better-wp-security' ); ?></p>
57
  </td>
58
  </tr>
59
  <tr>
60
- <th scope="row"><label for="itsec-system-tweaks-non_english_characters"><?php _e( 'Non-English Characters', 'better-wp-security' ); ?></label></th>
61
  <td>
62
  <?php $form->add_checkbox( 'non_english_characters' ); ?>
63
- <label for="itsec-system-tweaks-non_english_characters"><?php _e( 'Filter Non-English Characters', 'better-wp-security' ); ?></label>
64
- <p class="description"><?php _e( 'Filter out non-english characters from the query string. This should not be used on non-english sites and only works when "Filter Suspicious Query String" has been selected.', 'better-wp-security' ); ?></p>
65
  </td>
66
  </tr>
67
  <tr>
68
- <th scope="row"><label for="itsec-system-tweaks-long_url_strings"><?php _e( 'Long URL Strings', 'better-wp-security' ); ?></label></th>
69
  <td>
70
  <?php $form->add_checkbox( 'long_url_strings' ); ?>
71
- <label for="itsec-system-tweaks-long_url_strings"><?php _e( 'Filter Long URL Strings', 'better-wp-security' ); ?></label>
72
- <p class="description"><?php _e( 'Limits the number of characters that can be sent in the URL. Hackers often take advantage of long URLs to try to inject information into your database.', 'better-wp-security' ); ?></p>
73
  </td>
74
  </tr>
75
  <tr>
76
- <th scope="row"><label for="itsec-system-tweaks-write_permissions"><?php _e( 'File Writing Permissions', 'better-wp-security' ); ?></label></th>
77
  <td>
78
  <?php $form->add_checkbox( 'write_permissions' ); ?>
79
- <label for="itsec-system-tweaks-write_permissions"><?php _e( 'Remove File Writing Permissions', 'better-wp-security' ); ?></label>
80
- <p class="description"><?php _e( 'Prevents scripts and users from being able to write to the wp-config.php file and .htaccess file. Note that in the case of this and many plugins this can be overcome however it still does make the files more secure. Turning this on will set the UNIX file permissions to 0444 on these files and turning it off will set the permissions to 0664.', 'better-wp-security' ); ?></p>
81
  </td>
82
  </tr>
83
  <tr>
84
- <th scope="row"><label for="itsec-system-tweaks-uploads_php"><?php _e( 'Uploads', 'better-wp-security' ); ?></label></th>
85
  <td>
86
  <?php $form->add_checkbox( 'uploads_php' ); ?>
87
- <label for="itsec-system-tweaks-uploads_php"><?php _e( 'Disable PHP in Uploads', 'better-wp-security' ); ?></label>
88
- <p class="description"><?php _e( 'Disable PHP execution in the uploads directory. This will prevent uploading of malicious scripts to uploads.', 'better-wp-security' ); ?></p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  </td>
90
  </tr>
91
  </table>
92
  <?php
93
-
94
  }
95
  }
96
 
6
  $this->title = __( 'System Tweaks', 'better-wp-security' );
7
  $this->description = __( 'Advanced settings that improve security by changing the server config for this site.', 'better-wp-security' );
8
  $this->type = 'recommended';
9
+
10
  parent::__construct();
11
  }
12
+
13
  protected function render_description( $form ) {
14
+
15
  ?>
16
+ <p><?php esc_html_e( 'These are advanced settings that may be utilized to further strengthen the security of your WordPress site.', 'better-wp-security' ); ?></p>
17
  <?php
18
+
19
  }
20
+
21
  protected function render_settings( $form ) {
22
+
23
  ?>
24
+ <p><?php esc_html_e( 'Note: These settings are listed as advanced because they block common forms of attacks but they can also block legitimate plugins and themes that rely on the same techniques. When activating the settings below, we recommend enabling them one by one to test that everything on your site is still working as expected.', 'better-wp-security' ); ?></p>
25
+ <p><?php esc_html_e( 'Remember, some of these settings might conflict with other plugins or themes, so test your site after enabling each setting.', 'better-wp-security' ); ?></p>
26
  <table class="form-table">
27
  <tr>
28
+ <th scope="row"><label for="itsec-system-tweaks-protect_files"><?php esc_html_e( 'System Files', 'better-wp-security' ); ?></label></th>
29
  <td>
30
  <?php $form->add_checkbox( 'protect_files' ); ?>
31
+ <label for="itsec-system-tweaks-protect_files"><?php esc_html_e( 'Protect System Files', 'better-wp-security' ); ?></label>
32
+ <p class="description"><?php esc_html_e( 'Prevent public access to readme.html, readme.txt, wp-config.php, install.php, wp-includes, and .htaccess. These files can give away important information on your site and serve no purpose to the public once WordPress has been successfully installed.', 'better-wp-security' ); ?></p>
33
  </td>
34
  </tr>
35
  <tr>
36
+ <th scope="row"><label for="itsec-system-tweaks-directory_browsing"><?php esc_html_e( 'Directory Browsing', 'better-wp-security' ); ?></label></th>
37
  <td>
38
  <?php $form->add_checkbox( 'directory_browsing' ); ?>
39
+ <label for="itsec-system-tweaks-directory_browsing"><?php esc_html_e( 'Disable Directory Browsing', 'better-wp-security' ); ?></label>
40
+ <p class="description"><?php esc_html_e( 'Prevents users from seeing a list of files in a directory when no index file is present.', 'better-wp-security' ); ?></p>
41
  </td>
42
  </tr>
43
  <tr>
44
+ <th scope="row"><label for="itsec-system-tweaks-request_methods"><?php esc_html_e( 'Request Methods', 'better-wp-security' ); ?></label></th>
45
  <td>
46
  <?php $form->add_checkbox( 'request_methods' ); ?>
47
+ <label for="itsec-system-tweaks-request_methods"><?php esc_html_e( 'Filter Request Methods', 'better-wp-security' ); ?></label>
48
+ <p class="description"><?php printf( wp_kses( __( 'Filter out hits with the trace, delete, or track request methods. This should not be enabled if you use the <a href="%s">WordPress REST API</a>.', 'better-wp-security' ), array( 'a' => array( 'href' => array() ) ) ), esc_url( 'https://wordpress.org/plugins/rest-api/' ) ); ?></p>
49
  </td>
50
  </tr>
51
  <tr>
52
+ <th scope="row"><label for="itsec-system-tweaks-suspicious_query_strings"><?php esc_html_e( 'Suspicious Query Strings', 'better-wp-security' ); ?></label></th>
53
  <td>
54
  <?php $form->add_checkbox( 'suspicious_query_strings' ); ?>
55
+ <label for="itsec-system-tweaks-suspicious_query_strings"><?php esc_html_e( 'Filter Suspicious Query Strings in the URL', 'better-wp-security' ); ?></label>
56
+ <p class="description"><?php esc_html_e( 'These are very often signs of someone trying to gain access to your site but some plugins and themes can also be blocked.', 'better-wp-security' ); ?></p>
57
  </td>
58
  </tr>
59
  <tr>
60
+ <th scope="row"><label for="itsec-system-tweaks-non_english_characters"><?php esc_html_e( 'Non-English Characters', 'better-wp-security' ); ?></label></th>
61
  <td>
62
  <?php $form->add_checkbox( 'non_english_characters' ); ?>
63
+ <label for="itsec-system-tweaks-non_english_characters"><?php esc_html_e( 'Filter Non-English Characters', 'better-wp-security' ); ?></label>
64
+ <p class="description"><?php esc_html_e( 'Filter out non-english characters from the query string. This should not be used on non-english sites and only works when "Filter Suspicious Query String" has been selected.', 'better-wp-security' ); ?></p>
65
  </td>
66
  </tr>
67
  <tr>
68
+ <th scope="row"><label for="itsec-system-tweaks-long_url_strings"><?php esc_html_e( 'Long URL Strings', 'better-wp-security' ); ?></label></th>
69
  <td>
70
  <?php $form->add_checkbox( 'long_url_strings' ); ?>
71
+ <label for="itsec-system-tweaks-long_url_strings"><?php esc_html_e( 'Filter Long URL Strings', 'better-wp-security' ); ?></label>
72
+ <p class="description"><?php esc_html_e( 'Limits the number of characters that can be sent in the URL. Hackers often take advantage of long URLs to try to inject information into your database.', 'better-wp-security' ); ?></p>
73
  </td>
74
  </tr>
75
  <tr>
76
+ <th scope="row"><label for="itsec-system-tweaks-write_permissions"><?php esc_html_e( 'File Writing Permissions', 'better-wp-security' ); ?></label></th>
77
  <td>
78
  <?php $form->add_checkbox( 'write_permissions' ); ?>
79
+ <label for="itsec-system-tweaks-write_permissions"><?php esc_html_e( 'Remove File Writing Permissions', 'better-wp-security' ); ?></label>
80
+ <p class="description"><?php esc_html_e( 'Prevents scripts and users from being able to write to the wp-config.php file and .htaccess file. Note that in the case of this and many plugins this can be overcome however it still does make the files more secure. Turning this on will set the UNIX file permissions to 0444 on these files and turning it off will set the permissions to 0664.', 'better-wp-security' ); ?></p>
81
  </td>
82
  </tr>
83
  <tr>
84
+ <th scope="row"><label for="itsec-system-tweaks-uploads_php"><?php esc_html_e( 'PHP in Uploads', 'better-wp-security' ); ?></label></th>
85
  <td>
86
  <?php $form->add_checkbox( 'uploads_php' ); ?>
87
+ <label for="itsec-system-tweaks-uploads_php"><?php esc_html_e( 'Disable PHP in Uploads', 'better-wp-security' ); ?></label>
88
+ <p class="description"><?php esc_html_e( 'Disable PHP execution in the uploads directory. This blocks requests to maliciously uploaded PHP files in the uploads directory.', 'better-wp-security' ); ?></p>
89
+ </td>
90
+ </tr>
91
+ <tr>
92
+ <th scope="row"><label for="itsec-system-tweaks-plugins_php"><?php esc_html_e( 'PHP in Plugins', 'better-wp-security' ); ?></label></th>
93
+ <td>
94
+ <?php $form->add_checkbox( 'plugins_php' ); ?>
95
+ <label for="itsec-system-tweaks-plugins_php"><?php esc_html_e( 'Disable PHP in Plugins', 'better-wp-security' ); ?></label>
96
+ <p class="description"><?php esc_html_e( 'Disable PHP execution in the plugins directory. This blocks requests to PHP files inside plugin directories that can be exploited directly.', 'better-wp-security' ); ?></p>
97
+ </td>
98
+ </tr>
99
+ <tr>
100
+ <th scope="row"><label for="itsec-system-tweaks-themes_php"><?php esc_html_e( 'PHP in Themes', 'better-wp-security' ); ?></label></th>
101
+ <td>
102
+ <?php $form->add_checkbox( 'themes_php' ); ?>
103
+ <label for="itsec-system-tweaks-themes_php"><?php esc_html_e( 'Disable PHP in Themes', 'better-wp-security' ); ?></label>
104
+ <p class="description"><?php esc_html_e( 'Disable PHP execution in the themes directory. This blocks requests to PHP files inside theme directories that can be exploited directly.', 'better-wp-security' ); ?></p>
105
  </td>
106
  </tr>
107
  </table>
108
  <?php
109
+
110
  }
111
  }
112
 
core/modules/system-tweaks/settings.php CHANGED
@@ -4,7 +4,7 @@ final class ITSEC_System_Tweaks_Settings extends ITSEC_Settings {
4
  public function get_id() {
5
  return 'system-tweaks';
6
  }
7
-
8
  public function get_defaults() {
9
  return array(
10
  'protect_files' => false,
@@ -15,6 +15,8 @@ final class ITSEC_System_Tweaks_Settings extends ITSEC_Settings {
15
  'long_url_strings' => false,
16
  'write_permissions' => false,
17
  'uploads_php' => false,
 
 
18
  );
19
  }
20
  }
4
  public function get_id() {
5
  return 'system-tweaks';
6
  }
7
+
8
  public function get_defaults() {
9
  return array(
10
  'protect_files' => false,
15
  'long_url_strings' => false,
16
  'write_permissions' => false,
17
  'uploads_php' => false,
18
+ 'themes_php' => false,
19
+ 'plugins_php' => false,
20
  );
21
  }
22
  }
core/modules/system-tweaks/validator.php CHANGED
@@ -13,7 +13,9 @@ class ITSEC_System_Tweaks_Validator extends ITSEC_Validator {
13
  $this->sanitize_setting( 'bool', 'non_english_characters', __( 'Non-English Characters', 'better-wp-security' ) );
14
  $this->sanitize_setting( 'bool', 'long_url_strings', __( 'Long URL Strings', 'better-wp-security' ) );
15
  $this->sanitize_setting( 'bool', 'write_permissions', __( 'File Writing Permissions', 'better-wp-security' ) );
16
- $this->sanitize_setting( 'bool', 'uploads_php', __( 'Uploads', 'better-wp-security' ) );
 
 
17
  }
18
 
19
  protected function validate_settings() {
13
  $this->sanitize_setting( 'bool', 'non_english_characters', __( 'Non-English Characters', 'better-wp-security' ) );
14
  $this->sanitize_setting( 'bool', 'long_url_strings', __( 'Long URL Strings', 'better-wp-security' ) );
15
  $this->sanitize_setting( 'bool', 'write_permissions', __( 'File Writing Permissions', 'better-wp-security' ) );
16
+ $this->sanitize_setting( 'bool', 'uploads_php', __( 'PHP in Uploads', 'better-wp-security' ) );
17
+ $this->sanitize_setting( 'bool', 'plugins_php', __( 'PHP in Plugins', 'better-wp-security' ) );
18
+ $this->sanitize_setting( 'bool', 'themes_php', __( 'PHP in Themes', 'better-wp-security' ) );
19
  }
20
 
21
  protected function validate_settings() {
core/modules/wordpress-tweaks/class-itsec-wordpress-tweaks.php CHANGED
@@ -145,7 +145,7 @@ final class ITSEC_WordPress_Tweaks {
145
  wp_deregister_script( 'jquery-core' );
146
 
147
  wp_register_script( 'jquery', false, array( 'jquery-core', 'jquery-migrate' ), '1.11.0' );
148
- wp_register_script( 'jquery-core', '/wp-includes/js/jquery/jquery.js', false, '1.11.0' );
149
 
150
  wp_enqueue_script( 'jquery' );
151
  wp_enqueue_script( 'jquery-core' );
145
  wp_deregister_script( 'jquery-core' );
146
 
147
  wp_register_script( 'jquery', false, array( 'jquery-core', 'jquery-migrate' ), '1.11.0' );
148
+ wp_register_script( 'jquery-core', '/' . WPINC . '/js/jquery/jquery.js', false, '1.11.0' );
149
 
150
  wp_enqueue_script( 'jquery' );
151
  wp_enqueue_script( 'jquery-core' );
core/modules/wordpress-tweaks/config-generators.php CHANGED
@@ -3,29 +3,29 @@
3
  final class ITSEC_WordPress_Tweaks_Config_Generators {
4
  public static function filter_wp_config_modification( $modification ) {
5
  $input = ITSEC_Modules::get_settings( 'wordpress-tweaks' );
6
-
7
  if ( $input['file_editor'] ) {
8
  $modification .= "define( 'DISALLOW_FILE_EDIT', true ); // " . __( 'Disable File Editor - Security > Settings > WordPress Tweaks > File Editor', 'better-wp-security' ) . "\n";
9
  }
10
-
11
  return $modification;
12
  }
13
-
14
  public static function filter_litespeed_server_config_modification( $modification ) {
15
  return self::filter_apache_server_config_modification( $modification, 'litespeed' );
16
  }
17
-
18
  public static function filter_apache_server_config_modification( $modification, $server = 'apache' ) {
19
  $input = ITSEC_Modules::get_settings( 'wordpress-tweaks' );
20
-
21
  $rewrites = '';
22
-
23
-
24
  if ( 2 == $input['disable_xmlrpc'] ) {
25
  $modification .= "\n";
26
  $modification .= "\t# " . __( 'Disable XML-RPC - Security > Settings > WordPress Tweaks > XML-RPC', 'better-wp-security' ) . "\n";
27
  $modification .= "\t<files xmlrpc.php>\n";
28
-
29
  if ( 'apache' === $server ) {
30
  $modification .= "\t\t<IfModule mod_authz_core.c>\n";
31
  $modification .= "\t\t\tRequire all denied\n";
@@ -40,18 +40,18 @@ final class ITSEC_WordPress_Tweaks_Config_Generators {
40
  $modification .= "\t\t\tDeny from all\n";
41
  $modification .= "\t\t</IfModule>\n";
42
  }
43
-
44
  $modification .= "\t</files>\n";
45
  }
46
-
47
  if ( $input['comment_spam'] ) {
48
  $valid_referers = self::get_valid_referers( 'apache' );
49
-
50
  $rewrites .= "\n";
51
  $rewrites .= "\t\t# " . __( 'Reduce Comment Spam - Security > Settings > WordPress Tweaks > Comment Spam', 'better-wp-security' ) . "\n";
52
  $rewrites .= "\t\tRewriteCond %{REQUEST_METHOD} POST\n";
53
  $rewrites .= "\t\tRewriteCond %{REQUEST_URI} /wp-comments-post\.php\$\n";
54
-
55
  if ( empty( $valid_referers ) || in_array( '*', $valid_referers ) ) {
56
  $rewrites .= "\t\tRewriteCond %{HTTP_USER_AGENT} ^$\n";
57
  } else {
@@ -59,22 +59,22 @@ final class ITSEC_WordPress_Tweaks_Config_Generators {
59
  if ( '*.' == substr( $referer, 0, 2 ) ) {
60
  $referer = '([^/]+.)?' . substr( $referer, 2 );
61
  }
62
-
63
  $referer = str_replace( '.', '\.', $referer );
64
  $referer = rtrim( $referer, '/' );
65
-
66
  $valid_referers[$index] = $referer;
67
  }
68
  $valid_referers = implode( '|', $valid_referers );
69
-
70
  $rewrites .= "\t\tRewriteCond %{HTTP_USER_AGENT} ^$ [OR]\n";
71
  $rewrites .= "\t\tRewriteCond %{HTTP_REFERER} !^https?://($valid_referers)(/|$) [NC]\n";
72
  }
73
-
74
  $rewrites .= "\t\tRewriteRule ^.* - [F]\n";
75
  }
76
-
77
-
78
  if ( ! empty( $rewrites ) ) {
79
  $modification .= "\n";
80
  $modification .= "\t<IfModule mod_rewrite.c>\n";
@@ -82,49 +82,48 @@ final class ITSEC_WordPress_Tweaks_Config_Generators {
82
  $modification .= $rewrites;
83
  $modification .= "\t</IfModule>\n";
84
  }
85
-
86
-
87
  return $modification;
88
  }
89
-
90
  public static function filter_nginx_server_config_modification( $modification ) {
91
  $input = ITSEC_Modules::get_settings( 'wordpress-tweaks' );
92
-
93
-
94
  if ( 2 == $input['disable_xmlrpc'] ) {
95
  $modification .= "\n";
96
  $modification .= "\t# " . __( 'Disable XML-RPC - Security > Settings > WordPress Tweaks > XML-RPC', 'better-wp-security' ) . "\n";
97
  $modification .= "\tlocation ~ xmlrpc.php { deny all; }\n";
98
  }
99
-
100
  if ( $input['comment_spam'] ) {
101
  $valid_referers = self::get_valid_referers( 'nginx' );
102
 
103
  $modification .= "\n";
104
  $modification .= "\t# " . __( 'Reduce Comment Spam - Security > Settings > WordPress Tweaks > Comment Spam', 'better-wp-security' ) . "\n";
105
- $modification .= "\t# " . __( 'Help reduce spam', 'better-wp-security' ) . "\n";
106
- $modification .= "\tlocation /wp-comments-post.php {\n";
107
  $modification .= "\t\tlimit_except POST { deny all; }\n";
108
  $modification .= "\t\tif (\$http_user_agent ~ \"^$\") { return 403; }\n";
109
-
110
  if ( ! empty( $valid_referers ) && ! in_array( '*', $valid_referers ) ) {
111
  $modification .= "\t\tvalid_referers " . implode( ' ', $valid_referers ) . ";\n";
112
  $modification .= "\t\tif (\$invalid_referer) { return 403; }\n";
113
  }
114
-
115
  $modification .= "\t}\n";
116
  }
117
-
118
-
119
  return $modification;
120
  }
121
-
122
  protected static function get_valid_referers( $server_type ) {
123
  $valid_referers = array();
124
-
125
  if ( 'apache' === $server_type ) {
126
  $domain = ITSEC_Lib::get_domain( get_site_url() );
127
-
128
  if ( '*' == $domain ) {
129
  $valid_referers[] = $domain;
130
  } else {
@@ -135,20 +134,20 @@ final class ITSEC_WordPress_Tweaks_Config_Generators {
135
  } else {
136
  return array();
137
  }
138
-
139
  $valid_referers[] = 'jetpack.wordpress.com/jetpack-comment/';
140
  $valid_referers = apply_filters( 'itsec_filter_valid_comment_referers', $valid_referers, $server_type );
141
-
142
  if ( is_string( $valid_referers ) ) {
143
  $valid_referers = array( $valid_referers );
144
  } else if ( ! is_array( $valid_referers ) ) {
145
  $valid_referers = array();
146
  }
147
-
148
  foreach ( $valid_referers as $index => $referer ) {
149
  $valid_referers[$index] = preg_replace( '|^https?://|', '', $referer );
150
  }
151
-
152
  return $valid_referers;
153
  }
154
  }
3
  final class ITSEC_WordPress_Tweaks_Config_Generators {
4
  public static function filter_wp_config_modification( $modification ) {
5
  $input = ITSEC_Modules::get_settings( 'wordpress-tweaks' );
6
+
7
  if ( $input['file_editor'] ) {
8
  $modification .= "define( 'DISALLOW_FILE_EDIT', true ); // " . __( 'Disable File Editor - Security > Settings > WordPress Tweaks > File Editor', 'better-wp-security' ) . "\n";
9
  }
10
+
11
  return $modification;
12
  }
13
+
14
  public static function filter_litespeed_server_config_modification( $modification ) {
15
  return self::filter_apache_server_config_modification( $modification, 'litespeed' );
16
  }
17
+
18
  public static function filter_apache_server_config_modification( $modification, $server = 'apache' ) {
19
  $input = ITSEC_Modules::get_settings( 'wordpress-tweaks' );
20
+
21
  $rewrites = '';
22
+
23
+
24
  if ( 2 == $input['disable_xmlrpc'] ) {
25
  $modification .= "\n";
26
  $modification .= "\t# " . __( 'Disable XML-RPC - Security > Settings > WordPress Tweaks > XML-RPC', 'better-wp-security' ) . "\n";
27
  $modification .= "\t<files xmlrpc.php>\n";
28
+
29
  if ( 'apache' === $server ) {
30
  $modification .= "\t\t<IfModule mod_authz_core.c>\n";
31
  $modification .= "\t\t\tRequire all denied\n";
40
  $modification .= "\t\t\tDeny from all\n";
41
  $modification .= "\t\t</IfModule>\n";
42
  }
43
+
44
  $modification .= "\t</files>\n";
45
  }
46
+
47
  if ( $input['comment_spam'] ) {
48
  $valid_referers = self::get_valid_referers( 'apache' );
49
+
50
  $rewrites .= "\n";
51
  $rewrites .= "\t\t# " . __( 'Reduce Comment Spam - Security > Settings > WordPress Tweaks > Comment Spam', 'better-wp-security' ) . "\n";
52
  $rewrites .= "\t\tRewriteCond %{REQUEST_METHOD} POST\n";
53
  $rewrites .= "\t\tRewriteCond %{REQUEST_URI} /wp-comments-post\.php\$\n";
54
+
55
  if ( empty( $valid_referers ) || in_array( '*', $valid_referers ) ) {
56
  $rewrites .= "\t\tRewriteCond %{HTTP_USER_AGENT} ^$\n";
57
  } else {
59
  if ( '*.' == substr( $referer, 0, 2 ) ) {
60
  $referer = '([^/]+.)?' . substr( $referer, 2 );
61
  }
62
+
63
  $referer = str_replace( '.', '\.', $referer );
64
  $referer = rtrim( $referer, '/' );
65
+
66
  $valid_referers[$index] = $referer;
67
  }
68
  $valid_referers = implode( '|', $valid_referers );
69
+
70
  $rewrites .= "\t\tRewriteCond %{HTTP_USER_AGENT} ^$ [OR]\n";
71
  $rewrites .= "\t\tRewriteCond %{HTTP_REFERER} !^https?://($valid_referers)(/|$) [NC]\n";
72
  }
73
+
74
  $rewrites .= "\t\tRewriteRule ^.* - [F]\n";
75
  }
76
+
77
+
78
  if ( ! empty( $rewrites ) ) {
79
  $modification .= "\n";
80
  $modification .= "\t<IfModule mod_rewrite.c>\n";
82
  $modification .= $rewrites;
83
  $modification .= "\t</IfModule>\n";
84
  }
85
+
86
+
87
  return $modification;
88
  }
89
+
90
  public static function filter_nginx_server_config_modification( $modification ) {
91
  $input = ITSEC_Modules::get_settings( 'wordpress-tweaks' );
92
+
93
+
94
  if ( 2 == $input['disable_xmlrpc'] ) {
95
  $modification .= "\n";
96
  $modification .= "\t# " . __( 'Disable XML-RPC - Security > Settings > WordPress Tweaks > XML-RPC', 'better-wp-security' ) . "\n";
97
  $modification .= "\tlocation ~ xmlrpc.php { deny all; }\n";
98
  }
99
+
100
  if ( $input['comment_spam'] ) {
101
  $valid_referers = self::get_valid_referers( 'nginx' );
102
 
103
  $modification .= "\n";
104
  $modification .= "\t# " . __( 'Reduce Comment Spam - Security > Settings > WordPress Tweaks > Comment Spam', 'better-wp-security' ) . "\n";
105
+ $modification .= "\tlocation = /wp-comments-post.php {\n";
 
106
  $modification .= "\t\tlimit_except POST { deny all; }\n";
107
  $modification .= "\t\tif (\$http_user_agent ~ \"^$\") { return 403; }\n";
108
+
109
  if ( ! empty( $valid_referers ) && ! in_array( '*', $valid_referers ) ) {
110
  $modification .= "\t\tvalid_referers " . implode( ' ', $valid_referers ) . ";\n";
111
  $modification .= "\t\tif (\$invalid_referer) { return 403; }\n";
112
  }
113
+
114
  $modification .= "\t}\n";
115
  }
116
+
117
+
118
  return $modification;
119
  }
120
+
121
  protected static function get_valid_referers( $server_type ) {
122
  $valid_referers = array();
123
+
124
  if ( 'apache' === $server_type ) {
125
  $domain = ITSEC_Lib::get_domain( get_site_url() );
126
+
127
  if ( '*' == $domain ) {
128
  $valid_referers[] = $domain;
129
  } else {
134
  } else {
135
  return array();
136
  }
137
+
138
  $valid_referers[] = 'jetpack.wordpress.com/jetpack-comment/';
139
  $valid_referers = apply_filters( 'itsec_filter_valid_comment_referers', $valid_referers, $server_type );
140
+
141
  if ( is_string( $valid_referers ) ) {
142
  $valid_referers = array( $valid_referers );
143
  } else if ( ! is_array( $valid_referers ) ) {
144
  $valid_referers = array();
145
  }
146
+
147
  foreach ( $valid_referers as $index => $referer ) {
148
  $valid_referers[$index] = preg_replace( '|^https?://|', '', $referer );
149
  }
150
+
151
  return $valid_referers;
152
  }
153
  }
core/modules/wordpress-tweaks/settings-page-multisite-tweaks.php DELETED
@@ -1,57 +0,0 @@
1
- <?php
2
-
3
- final class ITSEC_Multisite_Tweaks_Settings_Page extends ITSEC_Module_Settings_Page {
4
- public function __construct() {
5
- $this->id = 'multisite-tweaks';
6
- $this->title = __( 'Multisite Tweaks', 'better-wp-security' );
7
- $this->description = __( 'Advanced settings that improve security by changing default WordPress Multisite behavior.', 'better-wp-security' );
8
- $this->type = 'recommended';
9
-
10
- parent::__construct();
11
- }
12
-
13
- protected function render_description( $form ) {
14
-
15
- ?>
16
- <p><?php _e( 'These are advanced settings that may be utilized to further strengthen the security of your WordPress site.', 'better-wp-security' ); ?></p>
17
- <?php
18
-
19
- }
20
-
21
- protected function render_settings( $form ) {
22
-
23
- ?>
24
- <p><?php _e( 'Note: These settings are listed as advanced because they block common forms of attacks but they can also block legitimate plugins and themes that rely on the same techniques. When activating the settings below, we recommend enabling them one by one to test that everything on your site is still working as expected.', 'better-wp-security' ); ?></p>
25
- <p><?php _e( 'Remember, some of these settings might conflict with other plugins or themes, so test your site after enabling each setting.', 'better-wp-security' ); ?></p>
26
- <table class="form-table">
27
- <tr>
28
- <th scope="row"><label for="itsec-multisite-tweaks-theme_updates"><?php _e( 'Theme Update Notifications', 'better-wp-security' ); ?></label></th>
29
- <td>
30
- <?php $form->add_checkbox( 'theme_updates' ); ?>
31
- <label for="itsec-multisite-tweaks-theme_updates"><?php _e( 'Hide Theme Update Notifications', 'better-wp-security' ); ?></label>
32
- <p class="description"><?php _e( 'Hides theme update notifications from users who cannot update themes. Please note that this only makes a difference in multi-site installations.', 'better-wp-security' ); ?></p>
33
- </td>
34
- </tr>
35
- <tr>
36
- <th scope="row"><label for="itsec-multisite-tweaks-plugin_updates"><?php _e( 'Plugin Update Notifications', 'better-wp-security' ); ?></label></th>
37
- <td>
38
- <?php $form->add_checkbox( 'plugin_updates' ); ?>
39
- <label for="itsec-multisite-tweaks-plugin_updates"><?php _e( 'Hide Plugin Update Notifications', 'better-wp-security' ); ?></label>
40
- <p class="description"><?php _e( 'Hides plugin update notifications from users who cannot update plugins. Please note that this only makes a difference in multi-site installations.', 'better-wp-security' ); ?></p>
41
- </td>
42
- </tr>
43
- <tr>
44
- <th scope="row"><label for="itsec-multisite-tweaks-core_updates"><?php _e( 'Core Update Notifications', 'better-wp-security' ); ?></label></th>
45
- <td>
46
- <?php $form->add_checkbox( 'core_updates' ); ?>
47
- <label for="itsec-multisite-tweaks-core_updates"><?php _e( 'Hide Core Update Notifications', 'better-wp-security' ); ?></label>
48
- <p class="description"><?php _e( 'Hides core update notifications from users who cannot update core. Please note that this only makes a difference in multi-site installations.', 'better-wp-security' ); ?></p>
49
- </td>
50
- </tr>
51
- </table>
52
- <?php
53
-
54
- }
55
- }
56
-
57
- new ITSEC_Multisite_Tweaks_Settings_Page();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/modules/wordpress-tweaks/settings-page-system-tweaks.php DELETED
@@ -1,97 +0,0 @@
1
- <?php
2
-
3
- final class ITSEC_System_Tweaks_Settings_Page extends ITSEC_Module_Settings_Page {
4
- public function __construct() {
5
- $this->id = 'system-tweaks';
6
- $this->title = __( 'System Tweaks', 'better-wp-security' );
7
- $this->description = __( 'Advanced settings that improve security by changing the server config for this site.', 'better-wp-security' );
8
- $this->type = 'recommended';
9
-
10
- parent::__construct();
11
- }
12
-
13
- protected function render_description( $form ) {
14
-
15
- ?>
16
- <p><?php _e( 'These are advanced settings that may be utilized to further strengthen the security of your WordPress site.', 'better-wp-security' ); ?></p>
17
- <?php
18
-
19
- }
20
-
21
- protected function render_settings( $form ) {
22
-
23
- ?>
24
- <p><?php _e( 'Note: These settings are listed as advanced because they block common forms of attacks but they can also block legitimate plugins and themes that rely on the same techniques. When activating the settings below, we recommend enabling them one by one to test that everything on your site is still working as expected.', 'better-wp-security' ); ?></p>
25
- <p><?php _e( 'Remember, some of these settings might conflict with other plugins or themes, so test your site after enabling each setting.', 'better-wp-security' ); ?></p>
26
- <table class="form-table">
27
- <tr>
28
- <th scope="row"><label for="itsec-system-tweaks-protect_files"><?php _e( 'System Files', 'better-wp-security' ); ?></label></th>
29
- <td>
30
- <?php $form->add_checkbox( 'protect_files' ); ?>
31
- <label for="itsec-system-tweaks-protect_files"><?php _e( 'Protect System Files', 'better-wp-security' ); ?></label>
32
- <p class="description"><?php _e( 'Prevent public access to readme.html, readme.txt, wp-config.php, install.php, wp-includes, and .htaccess. These files can give away important information on your site and serve no purpose to the public once WordPress has been successfully installed.', 'better-wp-security' ); ?></p>
33
- </td>
34
- </tr>
35
- <tr>
36
- <th scope="row"><label for="itsec-system-tweaks-directory_browsing"><?php _e( 'Directory Browsing', 'better-wp-security' ); ?></label></th>
37
- <td>
38
- <?php $form->add_checkbox( 'directory_browsing' ); ?>
39
- <label for="itsec-system-tweaks-directory_browsing"><?php _e( 'Disable Directory Browsing', 'better-wp-security' ); ?></label>
40
- <p class="description"><?php _e( 'Prevents users from seeing a list of files in a directory when no index file is present.', 'better-wp-security' ); ?></p>
41
- </td>
42
- </tr>
43
- <tr>
44
- <th scope="row"><label for="itsec-system-tweaks-request_methods"><?php _e( 'Request Methods', 'better-wp-security' ); ?></label></th>
45
- <td>
46
- <?php $form->add_checkbox( 'request_methods' ); ?>
47
- <label for="itsec-system-tweaks-request_methods"><?php _e( 'Filter Request Methods', 'better-wp-security' ); ?></label>
48
- <p class="description"><?php _e( 'Filter out hits with the trace, delete, or track request methods.', 'better-wp-security' ); ?></p>
49
- </td>
50
- </tr>
51
- <tr>
52
- <th scope="row"><label for="itsec-system-tweaks-suspicious_query_strings"><?php _e( 'Suspicious Query Strings', 'better-wp-security' ); ?></label></th>
53
- <td>
54
- <?php $form->add_checkbox( 'suspicious_query_strings' ); ?>
55
- <label for="itsec-system-tweaks-suspicious_query_strings"><?php _e( 'Filter Suspicious Query Strings in the URL', 'better-wp-security' ); ?></label>
56
- <p class="description"><?php _e( 'These are very often signs of someone trying to gain access to your site but some plugins and themes can also be blocked.', 'better-wp-security' ); ?></p>
57
- </td>
58
- </tr>
59
- <tr>
60
- <th scope="row"><label for="itsec-system-tweaks-non_english_characters"><?php _e( 'Non-English Characters', 'better-wp-security' ); ?></label></th>
61
- <td>
62
- <?php $form->add_checkbox( 'non_english_characters' ); ?>
63
- <label for="itsec-system-tweaks-non_english_characters"><?php _e( 'Filter Non-English Characters', 'better-wp-security' ); ?></label>
64
- <p class="description"><?php _e( 'Filter out non-english characters from the query string. This should not be used on non-english sites and only works when "Filter Suspicious Query String" has been selected.', 'better-wp-security' ); ?></p>
65
- </td>
66
- </tr>
67
- <tr>
68
- <th scope="row"><label for="itsec-system-tweaks-long_url_strings"><?php _e( 'Long URL Strings', 'better-wp-security' ); ?></label></th>
69
- <td>
70
- <?php $form->add_checkbox( 'long_url_strings' ); ?>
71
- <label for="itsec-system-tweaks-long_url_strings"><?php _e( 'Filter Long URL Strings', 'better-wp-security' ); ?></label>
72
- <p class="description"><?php _e( 'Limits the number of characters that can be sent in the URL. Hackers often take advantage of long URLs to try to inject information into your database.', 'better-wp-security' ); ?></p>
73
- </td>
74
- </tr>
75
- <tr>
76
- <th scope="row"><label for="itsec-system-tweaks-write_permissions"><?php _e( 'File Writing Permissions', 'better-wp-security' ); ?></label></th>
77
- <td>
78
- <?php $form->add_checkbox( 'write_permissions' ); ?>
79
- <label for="itsec-system-tweaks-write_permissions"><?php _e( 'Remove File Writing Permissions', 'better-wp-security' ); ?></label>
80
- <p class="description"><?php _e( 'Prevents scripts and users from being able to write to the wp-config.php file and .htaccess file. Note that in the case of this and many plugins this can be overcome however it still does make the files more secure. Turning this on will set the UNIX file permissions to 0444 on these files and turning it off will set the permissions to 0664.', 'better-wp-security' ); ?></p>
81
- </td>
82
- </tr>
83
- <tr>
84
- <th scope="row"><label for="itsec-system-tweaks-uploads_php"><?php _e( 'Uploads', 'better-wp-security' ); ?></label></th>
85
- <td>
86
- <?php $form->add_checkbox( 'uploads_php' ); ?>
87
- <label for="itsec-system-tweaks-uploads_php"><?php _e( 'Disable PHP in Uploads', 'better-wp-security' ); ?></label>
88
- <p class="description"><?php _e( 'Disable PHP execution in the uploads directory. This will prevent uploading of malicious scripts to uploads.', 'better-wp-security' ); ?></p>
89
- </td>
90
- </tr>
91
- </table>
92
- <?php
93
-
94
- }
95
- }
96
-
97
- new ITSEC_System_Tweaks_Settings_Page();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
history.txt CHANGED
@@ -561,3 +561,21 @@
561
  Bug Fix: Fixed issue that caused the daily digest email to be sent every day, even if no lockouts occurred and no file changes were found.
562
  Bug Fix: Fixed issue that could prevent saving of File Change settings, resulting in an error messages of "A validation function for file-change received data that did not have the required entry for latest_changes."
563
  Bug Fix: Fixed iThemes Security Pro logo appearing in daily digest emails.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
  Bug Fix: Fixed issue that caused the daily digest email to be sent every day, even if no lockouts occurred and no file changes were found.
562
  Bug Fix: Fixed issue that could prevent saving of File Change settings, resulting in an error messages of "A validation function for file-change received data that did not have the required entry for latest_changes."
563
  Bug Fix: Fixed iThemes Security Pro logo appearing in daily digest emails.
564
+ 5.7.0 - 2016-10-31 - Chris Jean
565
+ Bug Fix: Fixed data save issue that could cause multiple notification emails to be sent in a short period of time.
566
+ Bug Fix: Fixed issue that could cause the malware scanner to fail on sites that change the arg_separator.output php.ini value from its default value.
567
+ Bug Fix: Removed redundant entries in the HackRepair blacklist.
568
+ Bug Fix: Enabling Protect System Files in System Tweaks will now only block install.php for the current site. This fixes the issue where the setting can block installation of a site in a subdirectory.
569
+ Bug Fix: Fixed problem that could cause requests for iThemes Security data from iThemes Sync to fail due to large amounts of log entries.
570
+ Bug Fix: Scheduled backups now run if the ITSEC_BACKUP_CRON define is set with a non-boolean value.
571
+ Bug Fix: Replaced static references to wp-includes with the WPINC define.
572
+ Bug Fix: Moved blocking of query strings containing %0[0-9A-F] characters from the Non-English Characters setting to the Suspicious Query Strings setting as those characters are control code characters and are not associated with a language.
573
+ Bug Fix: Added escaping to some translation strings.
574
+ Bug Fix: Removed unused files from the WordPress Tweaks module directory.
575
+ Bug Fix: Fixed the Daily Digest email reversing the user and host lockout counts.
576
+ Bug Fix: The database backup email no longer sends from the email address configured in Settings > General. It now defaults to the same from address that the wp_mail() function uses. This will fix the mail being blocked by some mail servers due to a spoofed from address.
577
+ Enhancement: Updated the server config rules generated by the System Tweaks settings. They are now more consistent between Apache, LiteSpeed, and nginx. They are also more efficient and have been improved to limit accidentally blocking non-targeted requests.
578
+ Enhancement: Updated the database backup email to a new design.
579
+ Enhancement: Added a note that the Filter Request Methods setting in System Tweaks should not be enabled if the WordPress REST API is used. This is becasue the DELETE HTTP method is blocked when the setting is enabled.
580
+ New Feature: Added setting to block requests for PHP files in the plugins directory in System Tweaks.
581
+ New Feature: Added setting to block requests for PHP files in the themes directory in System Tweaks.
readme.txt CHANGED
@@ -3,7 +3,7 @@ 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.2
5
  Tested up to: 4.6.1
6
- Stable tag: 5.6.4
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -188,6 +188,25 @@ Free support may be available with the help of the community in the <a href="htt
188
 
189
  == Changelog ==
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  = 5.6.4 =
192
  * Bug Fix: Fixed issue that reported invalid counts for host and user lockouts in the daily digest email.
193
  * Bug Fix: Fixed issue that caused the daily digest email to be sent every day, even if no lockouts occurred and no file changes were found.
@@ -1590,5 +1609,5 @@ This release is a complete rewrite from the ground up. Special thanks to Cory Mi
1590
 
1591
  == Upgrade Notice ==
1592
 
1593
- = 5.6.4 =
1594
- Version 5.6.4 contains a number of 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.2
5
  Tested up to: 4.6.1
6
+ Stable tag: 5.7.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
188
 
189
  == Changelog ==
190
 
191
+ = 5.7.0 =
192
+ * Bug Fix: Fixed data save issue that could cause multiple notification emails to be sent in a short period of time.
193
+ * Bug Fix: Fixed issue that could cause the malware scanner to fail on sites that change the arg_separator.output php.ini value from its default value.
194
+ * Bug Fix: Removed redundant entries in the HackRepair blacklist.
195
+ * Bug Fix: Enabling Protect System Files in System Tweaks will now only block install.php for the current site. This fixes the issue where the setting can block installation of a site in a subdirectory.
196
+ * Bug Fix: Fixed problem that could cause requests for iThemes Security data from iThemes Sync to fail due to large amounts of log entries.
197
+ * Bug Fix: Scheduled backups now run if the ITSEC_BACKUP_CRON define is set with a non-boolean value.
198
+ * Bug Fix: Replaced static references to wp-includes with the WPINC define.
199
+ * Bug Fix: Moved blocking of query strings containing %0[0-9A-F] characters from the Non-English Characters setting to the Suspicious Query Strings setting as those characters are control code characters and are not associated with a language.
200
+ * Bug Fix: Added escaping to some translation strings.
201
+ * Bug Fix: Removed unused files from the WordPress Tweaks module directory.
202
+ * Bug Fix: Fixed the Daily Digest email reversing the user and host lockout counts.
203
+ * Bug Fix: The database backup email no longer sends from the email address configured in Settings > General. It now defaults to the same from address that the wp_mail() function uses. This will fix the mail being blocked by some mail servers due to a spoofed from address.
204
+ * Enhancement: Updated the server config rules generated by the System Tweaks settings. They are now more consistent between Apache, LiteSpeed, and nginx. They are also more efficient and have been improved to limit accidentally blocking non-targeted requests.
205
+ * Enhancement: Updated the database backup email to a new design.
206
+ * Enhancement: Added a note that the Filter Request Methods setting in System Tweaks should not be enabled if the WordPress REST API is used. This is becasue the DELETE HTTP method is blocked when the setting is enabled.
207
+ * New Feature: Added setting to block requests for PHP files in the plugins directory in System Tweaks.
208
+ * New Feature: Added setting to block requests for PHP files in the themes directory in System Tweaks.
209
+
210
  = 5.6.4 =
211
  * Bug Fix: Fixed issue that reported invalid counts for host and user lockouts in the daily digest email.
212
  * Bug Fix: Fixed issue that caused the daily digest email to be sent every day, even if no lockouts occurred and no file changes were found.
1609
 
1610
  == Upgrade Notice ==
1611
 
1612
+ = 5.7.0 =
1613
+ Version 5.7.0 contains many bug fixes and adds new optional features. It is recommended for all users.