All In One WP Security & Firewall - Version 4.1.7

Version Description

  • Added sanitisation for log file data in textarea.
  • Disabled autocomplete for Captcha field.
Download this release

Release Info

Developer mra13
Plugin Icon 128x128 All In One WP Security & Firewall
Version 4.1.7
Comparing to
See all releases

Code changes from version 4.1.4 to 4.1.7

admin/wp-security-dashboard-menu.php CHANGED
@@ -819,8 +819,8 @@ class AIOWPSecurity_Dashboard_Menu extends AIOWPSecurity_Admin_Menu
819
 
820
  function render_tab5()
821
  {
822
- global $wpdb;
823
- $file_selected = isset($_POST["aiowps_log_file"]) ? $_POST["aiowps_log_file"] : '';
824
  ?>
825
  <div class="postbox">
826
  <h3 class="hndle"><label
@@ -862,12 +862,25 @@ class AIOWPSecurity_Dashboard_Menu extends AIOWPSecurity_Admin_Menu
862
  if (isset($_POST['aiowps_view_logs']))//Do form submission tasks
863
  {
864
  $error = '';
 
 
865
  $nonce = $_REQUEST['_wpnonce'];
866
  if (!wp_verify_nonce($nonce, 'aiowpsec-dashboard-logs-nonce')) {
867
  $aio_wp_security->debug_logger->log_debug("Nonce check failed on dashboard view logs!", 4);
868
- die("Nonce check failed on dashboard view logs!");
869
  }
870
 
 
 
 
 
 
 
 
 
 
 
 
871
  if (!empty($file_selected)) {
872
  ?>
873
  <div class="postbox">
@@ -889,8 +902,7 @@ class AIOWPSecurity_Dashboard_Menu extends AIOWPSecurity_Admin_Menu
889
  $log_contents = $file_selected . ': ' . __('Log file is empty!', 'all-in-one-wp-security-and-firewall');
890
  }
891
  ?>
892
- <textarea class="aio_text_area_file_output aio_half_width aio_spacer_10_tb" rows="15"
893
- readonly><?php echo $log_contents; ?></textarea>
894
 
895
  </div>
896
  </div>
819
 
820
  function render_tab5()
821
  {
822
+ $file_selected = '';
823
+
824
  ?>
825
  <div class="postbox">
826
  <h3 class="hndle"><label
862
  if (isset($_POST['aiowps_view_logs']))//Do form submission tasks
863
  {
864
  $error = '';
865
+
866
+ //Check nonce before doing anything
867
  $nonce = $_REQUEST['_wpnonce'];
868
  if (!wp_verify_nonce($nonce, 'aiowpsec-dashboard-logs-nonce')) {
869
  $aio_wp_security->debug_logger->log_debug("Nonce check failed on dashboard view logs!", 4);
870
+ wp_die("Error! Nonce check failed on dashboard view logs!");
871
  }
872
 
873
+ //Get the selected file
874
+ $file_selected = isset($_POST["aiowps_log_file"]) ? sanitize_text_field($_POST["aiowps_log_file"]) : '';
875
+
876
+ //Let's make sure that the file selected can only ever be the correct log file of this plugin.
877
+ $valid_aiowps_log_files = array('wp-security-log.txt', 'wp-security-log-cron-job.txt');
878
+ if(!in_array($file_selected, $valid_aiowps_log_files)){
879
+ $file_selected = '';
880
+ unset($_POST['aiowps_view_logs']);
881
+ wp_die(__('Error! The file you selected is not a permitted file. You can only view log files created by this plugin.','all-in-one-wp-security-and-firewall'));
882
+ }
883
+
884
  if (!empty($file_selected)) {
885
  ?>
886
  <div class="postbox">
902
  $log_contents = $file_selected . ': ' . __('Log file is empty!', 'all-in-one-wp-security-and-firewall');
903
  }
904
  ?>
905
+ <textarea class="aio_text_area_file_output aio_half_width aio_spacer_10_tb" rows="15" readonly><?php echo esc_textarea($log_contents); ?></textarea>
 
906
 
907
  </div>
908
  </div>
classes/wp-security-backup.php CHANGED
@@ -10,83 +10,118 @@ class AIOWPSecurity_Backup
10
  add_action('aiowps_perform_scheduled_backup_tasks', array(&$this, 'aiowps_scheduled_backup_handler'));
11
  add_action('aiowps_perform_db_cleanup_tasks', array(&$this, 'aiowps_scheduled_db_cleanup_handler'));
12
  }
13
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  /**
15
  * This function will perform a database backup
16
  */
17
  function execute_backup()
18
  {
19
  global $wpdb, $aio_wp_security;
20
- $is_multi_site = false;
21
-
22
  @ini_set( 'auto_detect_line_endings', true );
23
- if (function_exists('is_multisite') && is_multisite())
 
24
  {
25
  //Let's get the current site's table prefix
26
  $site_pref = esc_sql($wpdb->prefix);
27
  $db_query = "SHOW TABLES LIKE '".$site_pref."%'";
28
  $tables = $wpdb->get_results( $db_query, ARRAY_N );
29
- $is_multi_site = true;
30
  }
31
  else
32
  {
33
  //get all of the tables
34
  $tables = $wpdb->get_results( 'SHOW TABLES', ARRAY_N );
35
- if(empty($tables)){
36
- $aio_wp_security->debug_logger->log_debug("execute_backup() - no tables found!",4);
37
- return FALSE;
38
- }
39
  }
40
 
41
- $return = '';
42
-
43
- //cycle through each table
44
- foreach($tables as $table)
45
- {
46
- $result = $wpdb->get_results( 'SELECT * FROM `' . $table[0] . '`;', ARRAY_N );
47
- $num_fields = sizeof( $wpdb->get_results( 'DESCRIBE `' . $table[0] . '`;' ) );
48
-
49
- $return.= 'DROP TABLE IF EXISTS `' . $table[0] . '`;';
50
- $row2 = $wpdb->get_row( 'SHOW CREATE TABLE `' . $table[0] . '`;', ARRAY_N );
51
- if(empty($row2)){
52
- $aio_wp_security->debug_logger->log_debug("execute_backup() - get_row returned NULL for table: ".$table[0],4);
53
- }
54
- $return.= PHP_EOL . PHP_EOL . $row2[1] . ";" . PHP_EOL . PHP_EOL;
55
-
56
- foreach( $result as $row )
57
- {
58
- $return .= 'INSERT INTO `' . $table[0] . '` VALUES(';
59
-
60
- for( $j=0; $j < $num_fields; $j++ ) {
61
-
62
- $row[$j] = addslashes( $row[$j] );
63
- //$row[$j] = ereg_replace( PHP_EOL, "\n", $row[$j] ); //deprecated!
64
- $row[$j] = preg_replace( "/".PHP_EOL."/", "\n", $row[$j] );
65
-
66
- if ( isset( $row[$j] ) ) {
67
- $return .= '"' . $row[$j] . '"' ;
68
- } else {
69
- $return.= '""';
70
- }
71
-
72
- if ( $j < ( $num_fields - 1 ) ) {
73
- $return .= ',';
74
- }
75
-
76
- }
77
- $return .= ");" . PHP_EOL;
78
- }
79
- $return .= PHP_EOL . PHP_EOL;
80
  }
81
- $return .= PHP_EOL . PHP_EOL;
82
 
83
  //Check to see if the main "backups" directory exists - create it otherwise
84
 
85
  $aiowps_backup_dir = WP_CONTENT_DIR.'/'.AIO_WP_SECURITY_BACKUPS_DIR_NAME;
86
- $aiowps_backup_url = content_url().'/'.AIO_WP_SECURITY_BACKUPS_DIR_NAME;
87
  if (!AIOWPSecurity_Utility_File::create_dir($aiowps_backup_dir))
88
  {
89
- $aio_wp_security->debug_logger->log_debug("Creation of DB backup directory failed!",4);
90
  return false;
91
  }
92
 
@@ -102,7 +137,7 @@ class AIOWPSecurity_Backup
102
 
103
  $site_name = strtolower($site_name);
104
 
105
- //make alphaunermic
106
  $site_name = preg_replace("/[^a-z0-9_\s-]/", "", $site_name);
107
 
108
  //Cleanup multiple instances of dashes or whitespaces
@@ -131,13 +166,20 @@ class AIOWPSecurity_Backup
131
 
132
  $handle = @fopen( $dirpath . '/' . $file . '.sql', 'w+' );
133
 
134
- $fw_res = @fwrite( $handle, $return );
 
 
 
 
 
 
 
135
  if (!$fw_res)
136
  {
137
- $aio_wp_security->debug_logger->log_debug("execute_backup() - Write to DB backup file failed",4);
 
138
  return false;
139
  }
140
- @fclose( $handle );
141
 
142
  //zip the file
143
  if ( class_exists( 'ZipArchive' ) )
@@ -272,7 +314,7 @@ class AIOWPSecurity_Backup
272
  }
273
  }
274
  }
275
-
276
 
277
  function aiowps_scheduled_db_cleanup_handler()
278
  {
@@ -303,6 +345,8 @@ class AIOWPSecurity_Backup
303
  $max_rows_global_meta_table = apply_filters( 'aiowps_max_rows_global_meta_table', $max_rows_global_meta_table );
304
  AIOWPSecurity_Utility::cleanup_table($global_meta_table_name, $max_rows_global_meta_table);
305
 
 
 
306
 
307
  //Keep adding other DB cleanup tasks as they arise...
308
  }
10
  add_action('aiowps_perform_scheduled_backup_tasks', array(&$this, 'aiowps_scheduled_backup_handler'));
11
  add_action('aiowps_perform_db_cleanup_tasks', array(&$this, 'aiowps_scheduled_db_cleanup_handler'));
12
  }
13
+
14
+ /**
15
+ * Add slashes, sanitize end-of-line characters (?), wrap $value in quotation marks.
16
+ * @param string $value
17
+ * @return string
18
+ */
19
+ function sanitize_db_field($value) {
20
+ return '"' . preg_replace( "/".PHP_EOL."/", "\n", addslashes($value) ) . '"';
21
+ }
22
+
23
+ /**
24
+ * Write sql dump of $tables to backup file identified by $handle.
25
+ * @global wpdb $wpdb WordPress database abstraction object.
26
+ * @global AIO_WP_Security $aio_wp_security
27
+ * @param resource $handle
28
+ * @param array $tables
29
+ * @return boolean True, if database tables dump have been successfully written to the backup file, false otherwise.
30
+ */
31
+ function write_db_backup_file($handle, $tables)
32
+ {
33
+ global $wpdb, $aio_wp_security;
34
+
35
+ $preamble
36
+ = "-- All In One WP Security & Firewall {$aio_wp_security->version}" . PHP_EOL
37
+ . '-- MySQL dump' . PHP_EOL
38
+ . '-- ' . date('Y-m-d H:i:s') . PHP_EOL . PHP_EOL
39
+ // When importing the backup, tell database server that our data is in UTF-8...
40
+ . "SET NAMES utf8;" . PHP_EOL
41
+ // ...and that foreign key checks should be ignored.
42
+ . "SET foreign_key_checks = 0;" . PHP_EOL . PHP_EOL
43
+ ;
44
+ if ( !@fwrite( $handle, $preamble ) ) { return false; }
45
+
46
+ // Loop through each table
47
+ foreach ( $tables as $table )
48
+ {
49
+ $table_name = $table[0];
50
+
51
+ $result_create_table = $wpdb->get_row( 'SHOW CREATE TABLE `' . $table_name . '`;', ARRAY_N );
52
+ if ( empty($result_create_table) ) {
53
+ $aio_wp_security->debug_logger->log_debug(__METHOD__ . " - get_row returned NULL for table: ".$table_name, 4);
54
+ return false; // Avoid incomplete backups
55
+ }
56
+
57
+ // Drop/create table preamble
58
+ $drop_and_create = 'DROP TABLE IF EXISTS `' . $table_name . '`;' . PHP_EOL . PHP_EOL
59
+ . $result_create_table[1] . ";" . PHP_EOL . PHP_EOL
60
+ ;
61
+ if ( !@fwrite( $handle, $drop_and_create ) ) { return false; }
62
+
63
+ // Dump table contents
64
+ // Fetch results as row of objects to spare memory.
65
+ $result = $wpdb->get_results( 'SELECT * FROM `' . $table_name . '`;', OBJECT );
66
+ foreach ( $result as $object_row )
67
+ {
68
+ // Convert object row to array row: this is what $wpdb->get_results()
69
+ // internally does when invoked with ARRAY_N param, but in the process
70
+ // it creates new copy of entire results array that eats a lot of memory.
71
+ $row = array_values(get_object_vars($object_row));
72
+ // Start INSERT statement
73
+ if ( !@fwrite( $handle, 'INSERT INTO `' . $table_name . '` VALUES(' ) ) { return false; }
74
+ // Loop through all fields and echo them out
75
+ foreach ( $row as $idx => $field ) {
76
+ // Echo fields separator (except for first loop)
77
+ if ( ($idx > 0) && !@fwrite( $handle, ',' ) ) { return false; }
78
+ // Echo field content (sanitized)
79
+ if ( !@fwrite( $handle, $this->sanitize_db_field($field) ) ) { return false; }
80
+ }
81
+ // Finish INSERT statement
82
+ if ( !@fwrite( $handle, ");" . PHP_EOL ) ) { return false; }
83
+ }
84
+ // Place two-empty lines after table data
85
+ if ( !@fwrite( $handle, PHP_EOL . PHP_EOL ) ) { return false; }
86
+ }
87
+
88
+ return true;
89
+ }
90
+
91
  /**
92
  * This function will perform a database backup
93
  */
94
  function execute_backup()
95
  {
96
  global $wpdb, $aio_wp_security;
97
+ $is_multi_site = function_exists('is_multisite') && is_multisite();
98
+
99
  @ini_set( 'auto_detect_line_endings', true );
100
+ @ini_set( 'memory_limit', '512M' );
101
+ if ( $is_multi_site )
102
  {
103
  //Let's get the current site's table prefix
104
  $site_pref = esc_sql($wpdb->prefix);
105
  $db_query = "SHOW TABLES LIKE '".$site_pref."%'";
106
  $tables = $wpdb->get_results( $db_query, ARRAY_N );
 
107
  }
108
  else
109
  {
110
  //get all of the tables
111
  $tables = $wpdb->get_results( 'SHOW TABLES', ARRAY_N );
 
 
 
 
112
  }
113
 
114
+ if ( empty($tables) ) {
115
+ $aio_wp_security->debug_logger->log_debug(__METHOD__ . " - no tables found!",4);
116
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  }
 
118
 
119
  //Check to see if the main "backups" directory exists - create it otherwise
120
 
121
  $aiowps_backup_dir = WP_CONTENT_DIR.'/'.AIO_WP_SECURITY_BACKUPS_DIR_NAME;
 
122
  if (!AIOWPSecurity_Utility_File::create_dir($aiowps_backup_dir))
123
  {
124
+ $aio_wp_security->debug_logger->log_debug(__METHOD__ . " - Creation of DB backup directory failed!",4);
125
  return false;
126
  }
127
 
137
 
138
  $site_name = strtolower($site_name);
139
 
140
+ //make alphanumeric
141
  $site_name = preg_replace("/[^a-z0-9_\s-]/", "", $site_name);
142
 
143
  //Cleanup multiple instances of dashes or whitespaces
166
 
167
  $handle = @fopen( $dirpath . '/' . $file . '.sql', 'w+' );
168
 
169
+ if ( $handle === false ) {
170
+ $aio_wp_security->debug_logger->log_debug("Cannot create DB backup file: {$dirpath}/{$file}.sql", 4);
171
+ return false;
172
+ }
173
+
174
+ $fw_res = $this->write_db_backup_file($handle, $tables);
175
+ @fclose( $handle );
176
+
177
  if (!$fw_res)
178
  {
179
+ @unlink( $dirpath . '/' . $file . '.sql' );
180
+ $aio_wp_security->debug_logger->log_debug(__METHOD__ . " - Write to DB backup file failed",4);
181
  return false;
182
  }
 
183
 
184
  //zip the file
185
  if ( class_exists( 'ZipArchive' ) )
314
  }
315
  }
316
  }
317
+
318
 
319
  function aiowps_scheduled_db_cleanup_handler()
320
  {
345
  $max_rows_global_meta_table = apply_filters( 'aiowps_max_rows_global_meta_table', $max_rows_global_meta_table );
346
  AIOWPSecurity_Utility::cleanup_table($global_meta_table_name, $max_rows_global_meta_table);
347
 
348
+ //Delete any expired _aiowps_captcha_string_info_xxxx transients
349
+ AIOWPSecurity_Utility::delete_expired_captcha_transients();
350
 
351
  //Keep adding other DB cleanup tasks as they arise...
352
  }
classes/wp-security-captcha.php CHANGED
@@ -88,7 +88,7 @@ class AIOWPSecurity_Captcha
88
  AIOWPSecurity_Utility::is_multisite_install() ? set_site_transient('aiowps_captcha_string_info_'.$random_str, $enc_result, 30 * 60) : set_transient('aiowps_captcha_string_info_'.$random_str, $enc_result, 30 * 60);
89
  $equation_string .= '<input type="hidden" name="aiowps-captcha-string-info" id="aiowps-captcha-string-info" value="'.$random_str.'" />';
90
  $equation_string .= '<input type="hidden" name="aiowps-captcha-temp-string" id="aiowps-captcha-temp-string" value="'.$current_time.'" />';
91
- $equation_string .= '<input type="text" size="2" id="aiowps-captcha-answer" name="aiowps-captcha-answer" value="" />';
92
  return $equation_string;
93
  }
94
 
88
  AIOWPSecurity_Utility::is_multisite_install() ? set_site_transient('aiowps_captcha_string_info_'.$random_str, $enc_result, 30 * 60) : set_transient('aiowps_captcha_string_info_'.$random_str, $enc_result, 30 * 60);
89
  $equation_string .= '<input type="hidden" name="aiowps-captcha-string-info" id="aiowps-captcha-string-info" value="'.$random_str.'" />';
90
  $equation_string .= '<input type="hidden" name="aiowps-captcha-temp-string" id="aiowps-captcha-temp-string" value="'.$current_time.'" />';
91
+ $equation_string .= '<input type="text" size="2" id="aiowps-captcha-answer" name="aiowps-captcha-answer" value="" autocomplete="off" />';
92
  return $equation_string;
93
  }
94
 
classes/wp-security-general-init-tasks.php CHANGED
@@ -48,8 +48,8 @@ class AIOWPSecurity_General_Init_Tasks
48
 
49
  if($aio_wp_security->configs->get_value('aiowps_remove_wp_generator_meta_info') == '1'){
50
  add_filter('the_generator', array(&$this,'remove_wp_generator_meta_info'));
51
- add_filter( 'style_loader_src', array(&$this,'remove_wp_css_js_meta_info'));
52
- add_filter( 'script_loader_src', array(&$this,'remove_wp_css_js_meta_info'));
53
  }
54
 
55
  //For the cookie based brute force prevention feature
@@ -276,8 +276,16 @@ class AIOWPSecurity_General_Init_Tasks
276
  }
277
 
278
  function remove_wp_css_js_meta_info($src) {
279
- if (strpos($src, 'ver=')) {
280
- $src = remove_query_arg('ver', $src);
 
 
 
 
 
 
 
 
281
  }
282
  return $src;
283
  }
48
 
49
  if($aio_wp_security->configs->get_value('aiowps_remove_wp_generator_meta_info') == '1'){
50
  add_filter('the_generator', array(&$this,'remove_wp_generator_meta_info'));
51
+ add_filter('style_loader_src', array(&$this,'remove_wp_css_js_meta_info'));
52
+ add_filter('script_loader_src', array(&$this,'remove_wp_css_js_meta_info'));
53
  }
54
 
55
  //For the cookie based brute force prevention feature
276
  }
277
 
278
  function remove_wp_css_js_meta_info($src) {
279
+ global $wp_version;
280
+ static $wp_version_hash = null; // Cache hash value for all function calls
281
+
282
+ // Replace only version number of assets with WP version
283
+ if ( strpos($src, 'ver=' . $wp_version) !== false ) {
284
+ if ( !$wp_version_hash ) {
285
+ $wp_version_hash = wp_hash($wp_version);
286
+ }
287
+ // Replace version number with computed hash
288
+ $src = add_query_arg('ver', $wp_version_hash, $src);
289
  }
290
  return $src;
291
  }
classes/wp-security-user-login.php CHANGED
@@ -365,18 +365,18 @@ class AIOWPSecurity_User_Login
365
  static function send_unlock_request_email($email, $unlock_link)
366
  {
367
  global $aio_wp_security;
368
- $to_email_address = $email;
369
- $email_msg = '';
370
  $subject = '['.get_option('siteurl').'] '. __('Unlock Request Notification','all-in-one-wp-security-and-firewall');
371
- $email_msg .= __('You have requested for the account with email address '.$email.' to be unlocked. Please click the link below to unlock your account:','all-in-one-wp-security-and-firewall')."\n";
372
- $email_msg .= __('Unlock link: '.$unlock_link,'all-in-one-wp-security-and-firewall')."\n\n";
373
- $email_msg .= __('After clicking the above link you will be able to login to the WordPress administration panel.','all-in-one-wp-security-and-firewall')."\n";
 
 
374
  $site_title = get_bloginfo( 'name' );
375
  $from_name = empty($site_title)?'WordPress':$site_title;
376
  $email_header = 'From: '.$from_name.' <'.get_bloginfo('admin_email').'>' . "\r\n\\";
377
- $sendMail = wp_mail($to_email_address, $subject, $email_msg, $email_header);
378
- if(FALSE === $sendMail){
379
- $aio_wp_security->debug_logger->log_debug("Unlock Request Notification email failed to send to ".$email,4);
380
  }
381
  }
382
 
365
  static function send_unlock_request_email($email, $unlock_link)
366
  {
367
  global $aio_wp_security;
 
 
368
  $subject = '['.get_option('siteurl').'] '. __('Unlock Request Notification','all-in-one-wp-security-and-firewall');
369
+ $email_msg
370
+ = sprintf(__('You have requested for the account with email address %s to be unlocked. Please click the link below to unlock your account:','all-in-one-wp-security-and-firewall'), $email) . "\n"
371
+ . sprintf(__('Unlock link: %s', 'all-in-one-wp-security-and-firewall'), $unlock_link) . "\n\n"
372
+ . __('After clicking the above link you will be able to login to the WordPress administration panel.', 'all-in-one-wp-security-and-firewall') . "\n"
373
+ ;
374
  $site_title = get_bloginfo( 'name' );
375
  $from_name = empty($site_title)?'WordPress':$site_title;
376
  $email_header = 'From: '.$from_name.' <'.get_bloginfo('admin_email').'>' . "\r\n\\";
377
+ $sendMail = wp_mail($email, $subject, $email_msg, $email_header);
378
+ if ( false === $sendMail ) {
379
+ $aio_wp_security->debug_logger->log_debug("Unlock Request Notification email failed to send to " . $email, 4);
380
  }
381
  }
382
 
classes/wp-security-utility-htaccess.php CHANGED
@@ -212,18 +212,9 @@ class AIOWPSecurity_Utility_Htaccess
212
  $rules = '';
213
  if ($aio_wp_security->configs->get_value('aiowps_prevent_default_wp_file_access') == '1') {
214
  $rules .= AIOWPSecurity_Utility_Htaccess::$prevent_wp_file_access_marker_start . PHP_EOL; //Add feature marker start
215
- $rules .= '<Files license.txt>
216
- order allow,deny
217
- deny from all
218
- </files>
219
- <Files wp-config-sample.php>
220
- order allow,deny
221
- deny from all
222
- </Files>
223
- <Files readme.html>
224
- order allow,deny
225
- deny from all
226
- </Files>' . PHP_EOL;
227
  $rules .= AIOWPSecurity_Utility_Htaccess::$prevent_wp_file_access_marker_end . PHP_EOL; //Add feature marker end
228
  }
229
 
@@ -233,60 +224,54 @@ class AIOWPSecurity_Utility_Htaccess
233
  static function getrules_blacklist()
234
  {
235
  global $aio_wp_security;
 
236
  $aiowps_server = AIOWPSecurity_Utility::get_server_type();
 
 
237
  $rules = '';
238
  if ($aio_wp_security->configs->get_value('aiowps_enable_blacklisting') == '1') {
239
- //Let's do the list of blacklisted IPs first
240
- $hosts = explode(PHP_EOL, $aio_wp_security->configs->get_value('aiowps_banned_ip_addresses'));
241
- if (!empty($hosts) && !(sizeof($hosts) == 1 && trim($hosts[0]) == '')) {
242
- if ($aiowps_server == 'apache' || $aiowps_server == 'litespeed') {
243
- $rules .= AIOWPSecurity_Utility_Htaccess::$ip_blacklist_marker_start . PHP_EOL; //Add feature marker start
244
- $rules .= "Order allow,deny" . PHP_EOL .
245
- "Allow from all" . PHP_EOL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  }
247
- $phosts = array();
248
- foreach ($hosts as $host) {
249
- $host = trim($host);
250
- if (!in_array($host, $phosts)) {
251
- if (strstr($host, '*')) {
252
- $parts = array_reverse(explode('.', $host));
253
- $netmask = 32;
254
- foreach ($parts as $part) {
255
- if (strstr(trim($part), '*')) {
256
- $netmask = $netmask - 8;
257
-
258
- }
259
- }
260
- $dhost = trim(str_replace('*', '0', implode('.', array_reverse($parts))) . '/' . $netmask);
261
- if (strlen($dhost) > 4) {
262
- if ($aiowps_server == 'apache' || $aiowps_server == 'litespeed') {
263
- $trule = "Deny from " . $dhost . PHP_EOL;
264
- if (trim($trule) != 'Deny From') {
265
- $rules .= $trule;
266
- }
267
- } else {
268
- $rules .= "\tdeny " . $dhost . ';' . PHP_EOL;
269
- }
270
- }
271
- } else {
272
- $dhost = trim($host);
273
- if (strlen($dhost) > 4) {
274
- if ($aiowps_server == 'apache' || $aiowps_server == 'litespeed') {
275
- $rules .= "Deny from " . $dhost . PHP_EOL;
276
- } else {
277
- $rules .= "\tdeny " . $dhost . ";" . PHP_EOL;
278
- }
279
- }
280
- }
281
  }
282
- $phosts[] = $host;
283
  }
 
284
  $rules .= AIOWPSecurity_Utility_Htaccess::$ip_blacklist_marker_end . PHP_EOL; //Add feature marker end
285
  }
 
286
  //Now let's do the user agent list
287
  $user_agents = explode(PHP_EOL, $aio_wp_security->configs->get_value('aiowps_banned_user_agents'));
288
  if (!empty($user_agents) && !(sizeof($user_agents) == 1 && trim($user_agents[0]) == '')) {
289
- if ($aiowps_server == 'apache' || $aiowps_server == 'litespeed') {
290
  $rules .= AIOWPSecurity_Utility_Htaccess::$user_agent_blacklist_marker_start . PHP_EOL; //Add feature marker start
291
  //Start mod_rewrite rules
292
  $rules .= "<IfModule mod_rewrite.c>" . PHP_EOL . "RewriteEngine On" . PHP_EOL . PHP_EOL;
@@ -307,6 +292,9 @@ class AIOWPSecurity_Utility_Htaccess
307
 
308
  }
309
  $rules .= "RewriteRule ^(.*)$ - [F,L]" . PHP_EOL . PHP_EOL;
 
 
 
310
  } else {
311
  $count = 1;
312
  $alist = '';
@@ -320,14 +308,6 @@ class AIOWPSecurity_Utility_Htaccess
320
  $rules .= "\tif (\$http_user_agent ~* " . $alist . ") { return 403; }" . PHP_EOL;
321
  }
322
  }
323
-
324
- //close mod_rewrite
325
- if (strlen($aio_wp_security->configs->get_value('aiowps_banned_user_agents')) > 0) {
326
- if (($aiowps_server == 'apache' || $aiowps_server == 'litespeed')) {
327
- $rules .= "</IfModule>" . PHP_EOL;
328
- $rules .= AIOWPSecurity_Utility_Htaccess::$user_agent_blacklist_marker_end . PHP_EOL; //Add feature marker end
329
- }
330
- }
331
  }
332
 
333
  return implode(PHP_EOL, array_diff(explode(PHP_EOL, $rules), array('Deny from ', 'Deny from')));
@@ -344,10 +324,7 @@ class AIOWPSecurity_Utility_Htaccess
344
  if ($aio_wp_security->configs->get_value('aiowps_enable_basic_firewall') == '1') {
345
  $rules .= AIOWPSecurity_Utility_Htaccess::$basic_htaccess_rules_marker_start . PHP_EOL; //Add feature marker start
346
  //protect the htaccess file - this is done by default with apache config file but we are including it here for good measure
347
- $rules .= '<Files .htaccess>' . PHP_EOL;
348
- $rules .= 'order allow,deny' . PHP_EOL;
349
- $rules .= 'deny from all' . PHP_EOL;
350
- $rules .= '</Files>' . PHP_EOL;
351
 
352
  //disable the server signature
353
  $rules .= 'ServerSignature Off' . PHP_EOL;
@@ -355,11 +332,8 @@ class AIOWPSecurity_Utility_Htaccess
355
  //limit file uploads to 10mb
356
  $rules .= 'LimitRequestBody 10240000' . PHP_EOL;
357
 
358
- // protect wpconfig.php.
359
- $rules .= '<Files wp-config.php>' . PHP_EOL;
360
- $rules .= 'order allow,deny' . PHP_EOL;
361
- $rules .= 'deny from all' . PHP_EOL;
362
- $rules .= '</Files>' . PHP_EOL;
363
 
364
  $rules .= AIOWPSecurity_Utility_Htaccess::$basic_htaccess_rules_marker_end . PHP_EOL; //Add feature marker end
365
  }
@@ -373,11 +347,7 @@ class AIOWPSecurity_Utility_Htaccess
373
  $rules = '';
374
  if ($aio_wp_security->configs->get_value('aiowps_enable_pingback_firewall') == '1') {
375
  $rules .= AIOWPSecurity_Utility_Htaccess::$pingback_htaccess_rules_marker_start . PHP_EOL; //Add feature marker start
376
- $rules .= '<Files xmlrpc.php>' . PHP_EOL;
377
- $rules .= 'order deny,allow' . PHP_EOL;
378
- $rules .= 'deny from all' . PHP_EOL;
379
- $rules .= '</Files>' . PHP_EOL;
380
-
381
  $rules .= AIOWPSecurity_Utility_Htaccess::$pingback_htaccess_rules_marker_end . PHP_EOL; //Add feature marker end
382
  }
383
  return $rules;
@@ -389,11 +359,8 @@ class AIOWPSecurity_Utility_Htaccess
389
 
390
  $rules = '';
391
  if ($aio_wp_security->configs->get_value('aiowps_block_debug_log_file_access') == '1') {
392
- $rules .= AIOWPSecurity_Utility_Htaccess::$debug_log_block_htaccess_rules_marker_start . PHP_EOL; //Add feature marker start
393
- $rules .= '<Files debug.log>' . PHP_EOL;
394
- $rules .= 'order deny,allow' . PHP_EOL;
395
- $rules .= 'deny from all' . PHP_EOL;
396
- $rules .= '</Files>' . PHP_EOL;
397
  $rules .= AIOWPSecurity_Utility_Htaccess::$debug_log_block_htaccess_rules_marker_end . PHP_EOL; //Add feature marker end
398
  }
399
  return $rules;
@@ -913,11 +880,21 @@ class AIOWPSecurity_Utility_Htaccess
913
  <IfModule mod_setenvif.c>
914
  SetEnvIfNoCase User-Agent ([a-z0-9]{2000}) bad_bot
915
  SetEnvIfNoCase User-Agent (archive.org|binlar|casper|checkpriv|choppy|clshttp|cmsworld|diavol|dotbot|extract|feedfinder|flicky|g00g1e|harvest|heritrix|httrack|kmccrew|loader|miner|nikto|nutch|planetwork|postrank|purebot|pycurl|python|seekerspider|siclab|skygrid|sqlmap|sucker|turnit|vikspider|winhttp|xxxyy|youda|zmeu|zune) bad_bot
916
- <limit GET POST PUT>
917
- Order Allow,Deny
918
- Allow from all
919
- Deny from env=bad_bot
920
- </limit>
 
 
 
 
 
 
 
 
 
 
921
  </IfModule>' . PHP_EOL;
922
  $rules .= AIOWPSecurity_Utility_Htaccess::$six_g_blacklist_marker_end . PHP_EOL; //Add feature marker end
923
  }
@@ -1062,4 +1039,93 @@ class AIOWPSecurity_Utility_Htaccess
1062
  return FALSE;
1063
  }
1064
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1065
  }
212
  $rules = '';
213
  if ($aio_wp_security->configs->get_value('aiowps_prevent_default_wp_file_access') == '1') {
214
  $rules .= AIOWPSecurity_Utility_Htaccess::$prevent_wp_file_access_marker_start . PHP_EOL; //Add feature marker start
215
+ $rules .= self::create_apache2_access_denied_rule('license.txt');
216
+ $rules .= self::create_apache2_access_denied_rule('wp-config-sample.php');
217
+ $rules .= self::create_apache2_access_denied_rule('readme.html');
 
 
 
 
 
 
 
 
 
218
  $rules .= AIOWPSecurity_Utility_Htaccess::$prevent_wp_file_access_marker_end . PHP_EOL; //Add feature marker end
219
  }
220
 
224
  static function getrules_blacklist()
225
  {
226
  global $aio_wp_security;
227
+ // Are we on Apache or LiteSpeed webserver?
228
  $aiowps_server = AIOWPSecurity_Utility::get_server_type();
229
+ $apache_or_litespeed = $aiowps_server == 'apache' || $aiowps_server == 'litespeed';
230
+ //
231
  $rules = '';
232
  if ($aio_wp_security->configs->get_value('aiowps_enable_blacklisting') == '1') {
233
+ // Let's do the list of blacklisted IPs first
234
+ $hosts = AIOWPSecurity_Utility::explode_trim_filter_empty($aio_wp_security->configs->get_value('aiowps_banned_ip_addresses'));
235
+ // Filter out duplicate lines, add netmask to IP addresses
236
+ $ips_with_netmask = self::add_netmask(array_unique($hosts));
237
+
238
+ if ( !empty($ips_with_netmask) ) {
239
+ $rules .= AIOWPSecurity_Utility_Htaccess::$ip_blacklist_marker_start . PHP_EOL; //Add feature marker start
240
+
241
+ if ( $apache_or_litespeed ) {
242
+ // Apache or LiteSpeed webserver
243
+ // Apache 2.2 and older
244
+ $rules .= "<IfModule !mod_authz_core.c>" . PHP_EOL;
245
+ $rules .= "Order allow,deny" . PHP_EOL;
246
+ $rules .= "Allow from all" . PHP_EOL;
247
+ foreach ($ips_with_netmask as $ip_with_netmask) {
248
+ $rules .= "Deny from " . $ip_with_netmask . PHP_EOL;
249
+ }
250
+ $rules .= "</IfModule>" . PHP_EOL;
251
+ // Apache 2.3 and newer
252
+ $rules .= "<IfModule mod_authz_core.c>" . PHP_EOL;
253
+ $rules .= "<RequireAll>" . PHP_EOL;
254
+ $rules .= "Require all granted" . PHP_EOL;
255
+ foreach ($ips_with_netmask as $ip_with_netmask) {
256
+ $rules .= "Require not ip " . $ip_with_netmask . PHP_EOL;
257
+ }
258
+ $rules .= "</RequireAll>" . PHP_EOL;
259
+ $rules .= "</IfModule>" . PHP_EOL;
260
  }
261
+ else {
262
+ // Nginx webserver
263
+ foreach ($ips_with_netmask as $ip_with_netmask) {
264
+ $rules .= "\tdeny " . $ip_with_netmask . ";" . PHP_EOL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  }
 
266
  }
267
+
268
  $rules .= AIOWPSecurity_Utility_Htaccess::$ip_blacklist_marker_end . PHP_EOL; //Add feature marker end
269
  }
270
+
271
  //Now let's do the user agent list
272
  $user_agents = explode(PHP_EOL, $aio_wp_security->configs->get_value('aiowps_banned_user_agents'));
273
  if (!empty($user_agents) && !(sizeof($user_agents) == 1 && trim($user_agents[0]) == '')) {
274
+ if ( $apache_or_litespeed ) {
275
  $rules .= AIOWPSecurity_Utility_Htaccess::$user_agent_blacklist_marker_start . PHP_EOL; //Add feature marker start
276
  //Start mod_rewrite rules
277
  $rules .= "<IfModule mod_rewrite.c>" . PHP_EOL . "RewriteEngine On" . PHP_EOL . PHP_EOL;
292
 
293
  }
294
  $rules .= "RewriteRule ^(.*)$ - [F,L]" . PHP_EOL . PHP_EOL;
295
+ // End mod_rewrite rules
296
+ $rules .= "</IfModule>" . PHP_EOL;
297
+ $rules .= AIOWPSecurity_Utility_Htaccess::$user_agent_blacklist_marker_end . PHP_EOL; //Add feature marker end
298
  } else {
299
  $count = 1;
300
  $alist = '';
308
  $rules .= "\tif (\$http_user_agent ~* " . $alist . ") { return 403; }" . PHP_EOL;
309
  }
310
  }
 
 
 
 
 
 
 
 
311
  }
312
 
313
  return implode(PHP_EOL, array_diff(explode(PHP_EOL, $rules), array('Deny from ', 'Deny from')));
324
  if ($aio_wp_security->configs->get_value('aiowps_enable_basic_firewall') == '1') {
325
  $rules .= AIOWPSecurity_Utility_Htaccess::$basic_htaccess_rules_marker_start . PHP_EOL; //Add feature marker start
326
  //protect the htaccess file - this is done by default with apache config file but we are including it here for good measure
327
+ $rules .= self::create_apache2_access_denied_rule('.htaccess');
 
 
 
328
 
329
  //disable the server signature
330
  $rules .= 'ServerSignature Off' . PHP_EOL;
332
  //limit file uploads to 10mb
333
  $rules .= 'LimitRequestBody 10240000' . PHP_EOL;
334
 
335
+ // protect wpconfig.php.
336
+ $rules .= self::create_apache2_access_denied_rule('wp-config.php');
 
 
 
337
 
338
  $rules .= AIOWPSecurity_Utility_Htaccess::$basic_htaccess_rules_marker_end . PHP_EOL; //Add feature marker end
339
  }
347
  $rules = '';
348
  if ($aio_wp_security->configs->get_value('aiowps_enable_pingback_firewall') == '1') {
349
  $rules .= AIOWPSecurity_Utility_Htaccess::$pingback_htaccess_rules_marker_start . PHP_EOL; //Add feature marker start
350
+ $rules .= self::create_apache2_access_denied_rule('xmlrpc.php');
 
 
 
 
351
  $rules .= AIOWPSecurity_Utility_Htaccess::$pingback_htaccess_rules_marker_end . PHP_EOL; //Add feature marker end
352
  }
353
  return $rules;
359
 
360
  $rules = '';
361
  if ($aio_wp_security->configs->get_value('aiowps_block_debug_log_file_access') == '1') {
362
+ $rules .= AIOWPSecurity_Utility_Htaccess::$debug_log_block_htaccess_rules_marker_start . PHP_EOL; //Add feature marker start
363
+ $rules .= self::create_apache2_access_denied_rule('debug.log');
 
 
 
364
  $rules .= AIOWPSecurity_Utility_Htaccess::$debug_log_block_htaccess_rules_marker_end . PHP_EOL; //Add feature marker end
365
  }
366
  return $rules;
880
  <IfModule mod_setenvif.c>
881
  SetEnvIfNoCase User-Agent ([a-z0-9]{2000}) bad_bot
882
  SetEnvIfNoCase User-Agent (archive.org|binlar|casper|checkpriv|choppy|clshttp|cmsworld|diavol|dotbot|extract|feedfinder|flicky|g00g1e|harvest|heritrix|httrack|kmccrew|loader|miner|nikto|nutch|planetwork|postrank|purebot|pycurl|python|seekerspider|siclab|skygrid|sqlmap|sucker|turnit|vikspider|winhttp|xxxyy|youda|zmeu|zune) bad_bot
883
+
884
+ # Apache < 2.3
885
+ <IfModule !mod_authz_core.c>
886
+ Order allow,deny
887
+ Allow from all
888
+ Deny from env=bad_bot
889
+ </IfModule>
890
+
891
+ # Apache >= 2.3
892
+ <IfModule mod_authz_core.c>
893
+ <RequireAll>
894
+ Require all granted
895
+ Require not env bad_bot
896
+ </RequireAll>
897
+ </IfModule>
898
  </IfModule>' . PHP_EOL;
899
  $rules .= AIOWPSecurity_Utility_Htaccess::$six_g_blacklist_marker_end . PHP_EOL; //Add feature marker end
900
  }
1039
  return FALSE;
1040
  }
1041
  }
1042
+
1043
+ /**
1044
+ * Returns a string with <Files $filename> directive that contains rules
1045
+ * to effectively block access to any file that has basename matching
1046
+ * $filename under Apache webserver.
1047
+ *
1048
+ * @link http://httpd.apache.org/docs/current/mod/core.html#files
1049
+ *
1050
+ * @param string $filename
1051
+ * @return string
1052
+ */
1053
+ protected static function create_apache2_access_denied_rule($filename) {
1054
+ return <<<END
1055
+ <Files $filename>
1056
+ <IfModule mod_authz_core.c>
1057
+ Require all denied
1058
+ </IfModule>
1059
+ <IfModule !mod_authz_core.c>
1060
+ Order deny,allow
1061
+ Deny from all
1062
+ </IfModule>
1063
+ </Files>
1064
+
1065
+ END;
1066
+ // Keep the empty line at the end of heredoc string,
1067
+ // otherwise the string will not end with end-of-line character!
1068
+ }
1069
+
1070
+
1071
+ /**
1072
+ * Convert an array of optionally asterisk-masked or partial IPv4 addresses
1073
+ * into network/netmask notation. Netmask value for a "full" IP is not
1074
+ * added (see example below)
1075
+ *
1076
+ * Example:
1077
+ * In: array('1.2.3.4', '5.6', '7.8.9.*')
1078
+ * Out: array('1.2.3.4', '5.6.0.0/16', '7.8.9.0/24')
1079
+ *
1080
+ * Simple validation is performed:
1081
+ * In: array('1.2.3.4.5', 'abc', '1.2.xyz.4')
1082
+ * Out: array()
1083
+ *
1084
+ * Simple sanitization is performed:
1085
+ * In: array('6.7.*.9')
1086
+ * Out: array('6.7.0.0/16')
1087
+ *
1088
+ * @param array $ips
1089
+ * @return array
1090
+ */
1091
+ protected static function add_netmask($ips) {
1092
+
1093
+ $output = array();
1094
+
1095
+ foreach ( $ips as $ip ) {
1096
+
1097
+ $parts = explode('.', $ip);
1098
+
1099
+ // Skip any IP that is empty, has more parts than expected or has
1100
+ // a non-numeric first part.
1101
+ if ( empty($parts) || (count($parts) > 4) || !is_numeric($parts[0]) ) {
1102
+ continue;
1103
+ }
1104
+
1105
+ $ip_out = array( $parts[0] );
1106
+ $netmask = 8;
1107
+
1108
+ for ( $i = 1, $force_zero = false; ($i < 4) && $ip_out; $i++ ) {
1109
+ if ( $force_zero || !isset($parts[$i]) || ($parts[$i] === '') || ($parts[$i] === '*') ) {
1110
+ $ip_out[$i] = '0';
1111
+ $force_zero = true; // Forces all subsequent parts to be a zero
1112
+ }
1113
+ else if ( is_numeric($parts[$i]) ) {
1114
+ $ip_out[$i] = $parts[$i];
1115
+ $netmask += 8;
1116
+ }
1117
+ else {
1118
+ // Invalid IP part detected, invalidate entire IP
1119
+ $ip_out = false;
1120
+ }
1121
+ }
1122
+
1123
+ if ( $ip_out ) {
1124
+ // Glue IP back together, add netmask if IP denotes a subnet, store for output.
1125
+ $output[] = implode('.', $ip_out) . (($netmask < 32) ? ('/' . $netmask) : '');
1126
+ }
1127
+ }
1128
+
1129
+ return $output;
1130
+ }
1131
  }
classes/wp-security-utility.php CHANGED
@@ -17,6 +17,11 @@ class AIOWPSecurity_Utility
17
  return array_filter(array_map('trim', explode($delimiter, $string)), 'strlen');
18
  }
19
 
 
 
 
 
 
20
  static function get_current_page_url()
21
  {
22
  $pageURL = 'http';
@@ -32,6 +37,13 @@ class AIOWPSecurity_Utility
32
  return $pageURL;
33
  }
34
 
 
 
 
 
 
 
 
35
  static function redirect_to_url($url, $delay = '0', $exit = '1')
36
  {
37
  if (empty($url)) {
@@ -48,13 +60,22 @@ class AIOWPSecurity_Utility
48
  }
49
  }
50
 
 
 
 
 
 
 
51
  static function get_logout_url_with_after_logout_url_value($after_logout_url)
52
  {
53
  return AIOWPSEC_WP_URL . '?aiowpsec_do_log_out=1&after_logout=' . $after_logout_url;
54
  }
55
 
56
- /*
57
  * Checks if a particular username exists in the WP Users table
 
 
 
58
  */
59
  static function check_user_exists($username)
60
  {
@@ -96,8 +117,10 @@ class AIOWPSecurity_Utility
96
  }
97
  }
98
 
99
- /*
100
  * This function will return a list of user accounts which have login and nick names which are identical
 
 
101
  */
102
  static function check_identical_login_and_nick_names()
103
  {
@@ -119,8 +142,10 @@ class AIOWPSecurity_Utility
119
  }
120
 
121
 
122
- /*
123
  * Generates a random alpha-numeric number
 
 
124
  */
125
  static function generate_alpha_numeric_random_string($string_length)
126
  {
@@ -135,8 +160,10 @@ class AIOWPSecurity_Utility
135
  }
136
 
137
 
138
- /*
139
- * Generates a random number using a-z characters
 
 
140
  */
141
  static function generate_alpha_random_string($string_length)
142
  {
@@ -150,6 +177,14 @@ class AIOWPSecurity_Utility
150
  return $string;
151
  }
152
 
 
 
 
 
 
 
 
 
153
  static function set_cookie_value($cookie_name, $cookie_value, $expiry_seconds = 86400, $path = '/', $cookie_domain = '')
154
  {
155
  $expiry_time = time() + intval($expiry_seconds);
@@ -158,7 +193,12 @@ class AIOWPSecurity_Utility
158
  }
159
  setcookie($cookie_name, $cookie_value, $expiry_time, $path, $cookie_domain);
160
  }
161
-
 
 
 
 
 
162
  static function get_cookie_value($cookie_name)
163
  {
164
  if (isset($_COOKIE[$cookie_name])) {
@@ -167,12 +207,18 @@ class AIOWPSecurity_Utility
167
  return "";
168
  }
169
 
 
 
 
 
170
  static function is_multisite_install()
171
  {
172
  return function_exists('is_multisite') && is_multisite();
173
  }
174
 
175
- //This is a general yellow box message for when we want to suppress a feature's config items because site is subsite of multi-site
 
 
176
  static function display_multisite_message()
177
  {
178
  echo '<div class="aio_yellow_box">';
@@ -181,12 +227,16 @@ class AIOWPSecurity_Utility
181
  echo '</div>';
182
  }
183
 
184
- /*
185
  * Modifies the wp-config.php file to disable PHP file editing from the admin panel
186
- * This func will add the following code:
187
  * define('DISALLOW_FILE_EDIT', false);
188
  *
189
- * NOTE: This function will firstly check if the above code already exists and it will modify the bool value, otherwise it will insert the code mentioned above
 
 
 
 
190
  */
191
  static function disable_file_edits()
192
  {
@@ -244,12 +294,14 @@ class AIOWPSecurity_Utility
244
  }
245
  }
246
 
247
- /*
248
  * Modifies the wp-config.php file to allow PHP file editing from the admin panel
249
  * This func will modify the following code by replacing "true" with "false":
250
  * define('DISALLOW_FILE_EDIT', true);
 
 
 
251
  */
252
-
253
  static function enable_file_edits()
254
  {
255
  global $aio_wp_security;
@@ -373,10 +425,9 @@ class AIOWPSecurity_Utility
373
 
374
  /**
375
  * Returns list of IP addresses locked out
376
- *
377
- * * @returns array of addresses or FALSE otherwise
378
- *
379
- **/
380
  static function get_locked_ips()
381
  {
382
  global $wpdb;
@@ -391,8 +442,13 @@ class AIOWPSecurity_Utility
391
  }
392
 
393
 
394
- /*
395
  * Locks an IP address - Adds an entry to the aiowps_lockdowns table
 
 
 
 
 
396
  */
397
  static function lock_IP($ip, $lock_reason = '', $username = '')
398
  {
@@ -423,9 +479,12 @@ class AIOWPSecurity_Utility
423
  }
424
  }
425
 
426
- /*
427
  * Returns an array of blog_ids for a multisite install
428
- * If site is not multisite returns empty array
 
 
 
429
  */
430
  static function get_blog_ids()
431
  {
@@ -440,7 +499,14 @@ class AIOWPSecurity_Utility
440
  }
441
 
442
 
443
- //This function will delete the oldest rows from a table which are over the max amount of rows specified
 
 
 
 
 
 
 
444
  static function cleanup_table($table_name, $max_rows = '10000')
445
  {
446
  global $wpdb, $aio_wp_security;
@@ -468,8 +534,35 @@ class AIOWPSecurity_Utility
468
  }
469
  return ($result === false) ? false : true;
470
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
471
 
472
- //Gets server type. Returns -1 if server is not supported
 
 
 
 
473
  static function get_server_type()
474
  {
475
  //figure out what server they're using
@@ -485,8 +578,12 @@ class AIOWPSecurity_Utility
485
 
486
  }
487
 
488
- /*
489
- * Checks if the string exists in the array key value of the provided array. If it doesn't exist, it returns the first key element from the valid values.
 
 
 
 
490
  */
491
  static function sanitize_value_by_array($to_check, $valid_values)
492
  {
@@ -495,7 +592,7 @@ class AIOWPSecurity_Utility
495
  if (in_array(strtolower($to_check), $keys)) {
496
  return $to_check;
497
  }
498
- return reset($keys);//Return he first element from the valid values
499
  }
500
 
501
  }
17
  return array_filter(array_map('trim', explode($delimiter, $string)), 'strlen');
18
  }
19
 
20
+ /**
21
+ * Returns the current URL
22
+ *
23
+ * @return string
24
+ */
25
  static function get_current_page_url()
26
  {
27
  $pageURL = 'http';
37
  return $pageURL;
38
  }
39
 
40
+ /**
41
+ * Redirects to specified URL
42
+ *
43
+ * @param type $url
44
+ * @param type $delay
45
+ * @param type $exit
46
+ */
47
  static function redirect_to_url($url, $delay = '0', $exit = '1')
48
  {
49
  if (empty($url)) {
60
  }
61
  }
62
 
63
+ /**
64
+ * Returns logout URL with "after logout URL" query params
65
+ *
66
+ * @param type $after_logout_url
67
+ * @return type
68
+ */
69
  static function get_logout_url_with_after_logout_url_value($after_logout_url)
70
  {
71
  return AIOWPSEC_WP_URL . '?aiowpsec_do_log_out=1&after_logout=' . $after_logout_url;
72
  }
73
 
74
+ /**
75
  * Checks if a particular username exists in the WP Users table
76
+ * @global type $wpdb
77
+ * @param type $username
78
+ * @return boolean
79
  */
80
  static function check_user_exists($username)
81
  {
117
  }
118
  }
119
 
120
+ /**
121
  * This function will return a list of user accounts which have login and nick names which are identical
122
+ * @global type $wpdb
123
+ * @return type
124
  */
125
  static function check_identical_login_and_nick_names()
126
  {
142
  }
143
 
144
 
145
+ /**
146
  * Generates a random alpha-numeric number
147
+ * @param type $string_length
148
+ * @return string
149
  */
150
  static function generate_alpha_numeric_random_string($string_length)
151
  {
160
  }
161
 
162
 
163
+ /**
164
+ * Generates a random string using a-z characters
165
+ * @param type $string_length
166
+ * @return string
167
  */
168
  static function generate_alpha_random_string($string_length)
169
  {
177
  return $string;
178
  }
179
 
180
+ /**
181
+ * Sets cookie
182
+ * @param type $cookie_name
183
+ * @param type $cookie_value
184
+ * @param type $expiry_seconds
185
+ * @param type $path
186
+ * @param string $cookie_domain
187
+ */
188
  static function set_cookie_value($cookie_name, $cookie_value, $expiry_seconds = 86400, $path = '/', $cookie_domain = '')
189
  {
190
  $expiry_time = time() + intval($expiry_seconds);
193
  }
194
  setcookie($cookie_name, $cookie_value, $expiry_time, $path, $cookie_domain);
195
  }
196
+
197
+ /**
198
+ * Gets cookie
199
+ * @param type $cookie_name
200
+ * @return string
201
+ */
202
  static function get_cookie_value($cookie_name)
203
  {
204
  if (isset($_COOKIE[$cookie_name])) {
207
  return "";
208
  }
209
 
210
+ /**
211
+ * Checks if installation is multisite
212
+ * @return type
213
+ */
214
  static function is_multisite_install()
215
  {
216
  return function_exists('is_multisite') && is_multisite();
217
  }
218
 
219
+ /**
220
+ * This is a general yellow box message for when we want to suppress a feature's config items because site is subsite of multi-site
221
+ */
222
  static function display_multisite_message()
223
  {
224
  echo '<div class="aio_yellow_box">';
227
  echo '</div>';
228
  }
229
 
230
+ /**
231
  * Modifies the wp-config.php file to disable PHP file editing from the admin panel
232
+ * This function will add the following code:
233
  * define('DISALLOW_FILE_EDIT', false);
234
  *
235
+ * NOTE: This function will firstly check if the above code already exists
236
+ * and it will modify the bool value, otherwise it will insert the code mentioned above
237
+ *
238
+ * @global type $aio_wp_security
239
+ * @return boolean
240
  */
241
  static function disable_file_edits()
242
  {
294
  }
295
  }
296
 
297
+ /**
298
  * Modifies the wp-config.php file to allow PHP file editing from the admin panel
299
  * This func will modify the following code by replacing "true" with "false":
300
  * define('DISALLOW_FILE_EDIT', true);
301
+ *
302
+ * @global type $aio_wp_security
303
+ * @return boolean
304
  */
 
305
  static function enable_file_edits()
306
  {
307
  global $aio_wp_security;
425
 
426
  /**
427
  * Returns list of IP addresses locked out
428
+ * @global type $wpdb
429
+ * @return array of addresses found or FALSE otherwise
430
+ */
 
431
  static function get_locked_ips()
432
  {
433
  global $wpdb;
442
  }
443
 
444
 
445
+ /**
446
  * Locks an IP address - Adds an entry to the aiowps_lockdowns table
447
+ * @global type $wpdb
448
+ * @global type $aio_wp_security
449
+ * @param type $ip
450
+ * @param type $lock_reason
451
+ * @param type $username
452
  */
453
  static function lock_IP($ip, $lock_reason = '', $username = '')
454
  {
479
  }
480
  }
481
 
482
+ /**
483
  * Returns an array of blog_ids for a multisite install
484
+ *
485
+ * @global type $wpdb
486
+ * @global type $wpdb
487
+ * @return array or empty array if not multisite
488
  */
489
  static function get_blog_ids()
490
  {
499
  }
500
 
501
 
502
+ /**
503
+ * This function will delete the oldest rows from a table which are over the max amount of rows specified
504
+ * @global type $wpdb
505
+ * @global type $aio_wp_security
506
+ * @param type $table_name
507
+ * @param type $max_rows
508
+ * @return bool
509
+ */
510
  static function cleanup_table($table_name, $max_rows = '10000')
511
  {
512
  global $wpdb, $aio_wp_security;
534
  }
535
  return ($result === false) ? false : true;
536
  }
537
+
538
+ /**
539
+ * Delete expired captcha info transients
540
+ *
541
+ * Note: A unique instance these transients is created everytime the login page is loaded with captcha enabled
542
+ * This function will help prune the options table of old expired entries.
543
+ *
544
+ * @global wpdb $wpdb
545
+ */
546
+ static function delete_expired_captcha_transients(){
547
+ global $wpdb;
548
+
549
+ $current_unix_time = current_time( 'timestamp', true );
550
+ $tbl = $wpdb->prefix . 'options';
551
+ $query = "SELECT * FROM ".$tbl." WHERE `option_name` LIKE '%\_transient\_timeout\_aiowps\_captcha\_string\_info%' AND `option_value` < ".$current_unix_time;
552
+ $res = $wpdb->get_results( $query, ARRAY_A );
553
+ if(!empty($res)){
554
+ foreach($res as $item){
555
+ $transient_name = str_replace('_transient_timeout_', '', $item['option_name']); //extract transient name
556
+ AIOWPSecurity_Utility::is_multisite_install()?delete_site_transient($transient_name):delete_transient($transient_name);
557
+ }
558
+ }
559
+ }
560
 
561
+ /**
562
+ * Gets server type.
563
+ *
564
+ * @return string or -1 if server is not supported
565
+ */
566
  static function get_server_type()
567
  {
568
  //figure out what server they're using
578
 
579
  }
580
 
581
+ /**
582
+ * Checks if the string exists in the array key value of the provided array.
583
+ * If it doesn't exist, it returns the first key element from the valid values.
584
+ * @param type $to_check
585
+ * @param type $valid_values
586
+ * @return type
587
  */
588
  static function sanitize_value_by_array($to_check, $valid_values)
589
  {
592
  if (in_array(strtolower($to_check), $keys)) {
593
  return $to_check;
594
  }
595
+ return reset($keys); //Return the first element from the valid values
596
  }
597
 
598
  }
other-includes/wp-security-rename-login-feature.php CHANGED
@@ -908,7 +908,7 @@ switch ($action) {
908
 
909
  <form name="loginform" id="loginform" action="<?php echo esc_url( site_url( 'wp-login.php', 'login_post' ) ); ?>" method="post">
910
  <p>
911
- <label for="user_login"><?php _e('Username') ?><br />
912
  <input type="text" name="log" id="user_login"<?php echo $aria_describedby_error; ?> class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" /></label>
913
  </p>
914
  <p>
908
 
909
  <form name="loginform" id="loginform" action="<?php echo esc_url( site_url( 'wp-login.php', 'login_post' ) ); ?>" method="post">
910
  <p>
911
+ <label for="user_login"><?php _e('Username or Email') ?><br />
912
  <input type="text" name="log" id="user_login"<?php echo $aria_describedby_error; ?> class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" /></label>
913
  </p>
914
  <p>
other-includes/wp-security-unlock-request.php CHANGED
@@ -79,7 +79,7 @@ if (isset($_POST['aiowps_wp_submit_unlock_request']))
79
  }else{
80
  //Send an email to the user
81
  AIOWPSecurity_User_Login::send_unlock_request_email($email, $unlock_url);
82
- echo '<p class="message">An email has been sent to you with the unlock instructions.</p>';
83
  }
84
  }
85
  $display_form = false;
@@ -95,9 +95,11 @@ if (isset($_POST['aiowps_wp_submit_unlock_request']))
95
  function display_unlock_form($email='')
96
  {
97
  ob_start();
98
- //Display the unlock request form
99
- $unlock_form_msg = '<p>You are here because you have been locked out due to too many incorrect login attempts.</p>
100
- <p>Please enter your email address and you will receive an email with instructions on how to unlock yourself.</p>'
 
 
101
  ?>
102
  <div class="message"><?php echo $unlock_form_msg; ?></div>
103
  <form name="loginform" id="loginform" action="<?php echo wp_login_url(); ?>" method="post">
@@ -106,7 +108,7 @@ function display_unlock_form($email='')
106
  <input type="text" name="aiowps_unlock_request_email" id="aiowps_unlock_request_email" class="input" value="<?php echo $email; ?>" size="20"></label>
107
  </p>
108
  <p class="submit">
109
- <input type="submit" name="aiowps_wp_submit_unlock_request" id="aiowps_wp_submit_unlock_request" class="button button-primary button-large" value="Send Unlock Request">
110
  </p>
111
  </form>
112
  <?php
79
  }else{
80
  //Send an email to the user
81
  AIOWPSecurity_User_Login::send_unlock_request_email($email, $unlock_url);
82
+ echo '<p class="message">' . __('An email has been sent to you with the unlock instructions.', 'all-in-one-wp-security-and-firewall') . '</p>';
83
  }
84
  }
85
  $display_form = false;
95
  function display_unlock_form($email='')
96
  {
97
  ob_start();
98
+ // Display the unlock request form
99
+ $unlock_form_msg
100
+ = '<p>' . __('You are here because you have been locked out due to too many incorrect login attempts.', 'all-in-one-wp-security-and-firewall') . '</p>'
101
+ . '<p>' . __('Please enter your email address and you will receive an email with instructions on how to unlock yourself.', 'all-in-one-wp-security-and-firewall') . '</p>'
102
+ ;
103
  ?>
104
  <div class="message"><?php echo $unlock_form_msg; ?></div>
105
  <form name="loginform" id="loginform" action="<?php echo wp_login_url(); ?>" method="post">
108
  <input type="text" name="aiowps_unlock_request_email" id="aiowps_unlock_request_email" class="input" value="<?php echo $email; ?>" size="20"></label>
109
  </p>
110
  <p class="submit">
111
+ <input type="submit" name="aiowps_wp_submit_unlock_request" id="aiowps_wp_submit_unlock_request" class="button button-primary button-large" value="<?php esc_attr_e('Send Unlock Request', 'all-in-one-wp-security-and-firewall'); ?>">
112
  </p>
113
  </form>
114
  <?php
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.tipsandtricks-hq.com
4
  Tags: security, secure, Anti Virus, antivirus, ban, ban hacker, virus, firewall, firewall security, login, lockdown, htaccess, hack, malware, vulnerability, protect, protection, phishing, database, backup, plugin, sql injection, ssl, restrict, login captcha, bot, hotlink, 404 detection, admin, rename, all in one, scan, scanner, iframe,
5
  Requires at least: 3.5
6
  Tested up to: 4.6
7
- Stable tag: 4.1.4
8
  License: GPLv3
9
 
10
  A comprehensive, user-friendly, all in one WordPress security and firewall plugin for your site.
@@ -183,6 +183,22 @@ None
183
 
184
  == Changelog ==
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  = 4.1.4 =
187
  - Improved and tweaked the login captcha feature to avoid some issues people had with the last modification.
188
  - Deleted reference to ini_get('safe_mode') to avoid fatal errors for newer versions of PHP where that setting has been totally removed.
4
  Tags: security, secure, Anti Virus, antivirus, ban, ban hacker, virus, firewall, firewall security, login, lockdown, htaccess, hack, malware, vulnerability, protect, protection, phishing, database, backup, plugin, sql injection, ssl, restrict, login captcha, bot, hotlink, 404 detection, admin, rename, all in one, scan, scanner, iframe,
5
  Requires at least: 3.5
6
  Tested up to: 4.6
7
+ Stable tag: 4.1.7
8
  License: GPLv3
9
 
10
  A comprehensive, user-friendly, all in one WordPress security and firewall plugin for your site.
183
 
184
  == Changelog ==
185
 
186
+ = 4.1.7 =
187
+ - Added sanitisation for log file data in textarea.
188
+ - Disabled autocomplete for Captcha field.
189
+
190
+ = 4.1.6 =
191
+ - Added cleanup code for captcha string info transients.
192
+ - Minor change to the username label in the renamed login page to keep it inline with the standard WordPress login page.
193
+ - Fixed a potential vulnerability when viewing AIOWPS log files in the Dashboard menu. Thanks to Manuel LLOP for pointing this out.
194
+
195
+ = 4.1.5 =
196
+ - Fixed bug where username is an email and captcha was being ignored.
197
+ - Reduce memory footprint of database backup.
198
+ - Improvements: Make hard-coded strings localizable.
199
+ - Partial Apache 2.3 compatibility.
200
+ - Improved: Hide WP version number by replacing it with a hash. This way, WordPress version number is not exposed, but browser caching is not obscured by missing version numbers.
201
+
202
  = 4.1.4 =
203
  - Improved and tweaked the login captcha feature to avoid some issues people had with the last modification.
204
  - Deleted reference to ini_get('safe_mode') to avoid fatal errors for newer versions of PHP where that setting has been totally removed.
wp-security-core.php CHANGED
@@ -3,7 +3,7 @@
3
  if (!class_exists('AIO_WP_Security')){
4
 
5
  class AIO_WP_Security{
6
- var $version = '4.1.4';
7
  var $db_version = '1.8';
8
  var $plugin_url;
9
  var $plugin_path;
3
  if (!class_exists('AIO_WP_Security')){
4
 
5
  class AIO_WP_Security{
6
+ var $version = '4.1.7';
7
  var $db_version = '1.8';
8
  var $plugin_url;
9
  var $plugin_path;
wp-security.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  Plugin Name: All In One WP Security
4
- Version: 4.1.4
5
  Plugin URI: https://www.tipsandtricks-hq.com/wordpress-security-and-firewall-plugin
6
  Author: Tips and Tricks HQ, Peter, Ruhul, Ivy
7
  Author URI: https://www.tipsandtricks-hq.com/
1
  <?php
2
  /*
3
  Plugin Name: All In One WP Security
4
+ Version: 4.1.7
5
  Plugin URI: https://www.tipsandtricks-hq.com/wordpress-security-and-firewall-plugin
6
  Author: Tips and Tricks HQ, Peter, Ruhul, Ivy
7
  Author URI: https://www.tipsandtricks-hq.com/