Changeset 3476940
- Timestamp:
- 03/07/2026 08:52:46 AM (3 weeks ago)
- Location:
- advanced-ip-blocker/trunk
- Files:
-
- 21 edited
-
advaipbl-loader.php (modified) (1 diff)
-
advanced-ip-blocker.php (modified) (2 diffs)
-
css/advaipbl-styles.css (modified) (1 diff)
-
includes/class-advaipbl-2fa-users-list-table.php (modified) (2 diffs)
-
includes/class-advaipbl-action-handler.php (modified) (6 diffs)
-
includes/class-advaipbl-admin-pages.php (modified) (9 diffs)
-
includes/class-advaipbl-ajax-handler.php (modified) (3 diffs)
-
includes/class-advaipbl-asn-manager.php (modified) (1 diff)
-
includes/class-advaipbl-audit-logger.php (modified) (4 diffs)
-
includes/class-advaipbl-cli.php (modified) (4 diffs)
-
includes/class-advaipbl-community-manager.php (modified) (1 diff)
-
includes/class-advaipbl-dashboard-manager.php (modified) (10 diffs)
-
includes/class-advaipbl-fingerprint-manager.php (modified) (8 diffs)
-
includes/class-advaipbl-live-feed-manager.php (modified) (6 diffs)
-
includes/class-advaipbl-main.php (modified) (77 diffs)
-
includes/class-advaipbl-notification-manager.php (modified) (2 diffs)
-
includes/class-advaipbl-threat-score-manager.php (modified) (7 diffs)
-
js/advaipbl-live-feed.js (modified) (7 diffs)
-
languages/advanced-ip-blocker.pot (modified) (1 diff)
-
readme.txt (modified) (3 diffs)
-
uninstall.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
advanced-ip-blocker/trunk/advaipbl-loader.php
r3464093 r3476940 6 6 // Explicit check for direct access to satisfy Plugin Check while allowing auto_prepend_file. 7 7 if ( ! defined( 'ABSPATH' ) ) { 8 if ( basename( $_SERVER['SCRIPT_FILENAME'] ) === basename( __FILE__ ) ) { 8 $script_filename = isset($_SERVER['SCRIPT_FILENAME']) ? sanitize_text_field(wp_unslash($_SERVER['SCRIPT_FILENAME'])) : ''; 9 if ( basename( $script_filename ) === basename( __FILE__ ) ) { 9 10 exit( 'Restricted access.' ); 10 11 } -
advanced-ip-blocker/trunk/advanced-ip-blocker.php
r3472969 r3476940 4 4 Plugin URI: https://advaipbl.com/ 5 5 Description: Your complete WordPress security firewall. Blocks IPs, bots & countries. Includes an intelligent WAF, Threat Scoring, and Two-Factor Authentication. 6 Version: 8.8. 86 Version: 8.8.9 7 7 Author: IniLerm 8 8 Author URI: https://advaipbl.com/ … … 19 19 } 20 20 21 define( 'ADVAIPBL_VERSION', '8.8. 8' );21 define( 'ADVAIPBL_VERSION', '8.8.9' ); 22 22 define( 'ADVAIPBL_PLUGIN_FILE', __FILE__ ); 23 23 -
advanced-ip-blocker/trunk/css/advaipbl-styles.css
r3472969 r3476940 1 1 /** 2 2 * Advanced IP Blocker - Admin Panel Styles 3 * Version: 8.8. 83 * Version: 8.8.9 4 4 */ 5 5 -
advanced-ip-blocker/trunk/includes/class-advaipbl-2fa-users-list-table.php
r3419894 r3476940 51 51 $tfa_status_filter = isset($_REQUEST['tfa_status']) ? sanitize_text_field(wp_unslash($_REQUEST['tfa_status'])) : 'all'; 52 52 if ( in_array( $tfa_status_filter, ['active', 'inactive'] ) ) { 53 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 53 54 $args['meta_key'] = ADVAIPBL_2fa_Manager::META_ENABLED_AT; 54 55 if ( 'active' === $tfa_status_filter ) { … … 204 205 205 206 // Contar usuarios con 2FA activo 207 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 206 208 $active_users_count = count( get_users([ 207 209 'meta_key' => ADVAIPBL_2fa_Manager::META_ENABLED_AT, -
advanced-ip-blocker/trunk/includes/class-advaipbl-action-handler.php
r3442728 r3476940 48 48 global $wpdb; 49 49 $lockdowns_table = $wpdb->prefix . 'advaipbl_endpoint_lockdowns'; 50 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 50 51 $wpdb->delete($lockdowns_table, ['id' => $lockdown_id], ['%d']); 51 52 … … 212 213 global $wpdb; 213 214 $table_name = $wpdb->prefix . 'advaipbl_ip_scores'; 214 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 215 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 215 216 $wpdb->query("TRUNCATE TABLE `{$table_name}`"); 216 217 /* translators: %s: Username. */ … … 222 223 global $wpdb; 223 224 $table_name = $wpdb->prefix . 'advaipbl_malicious_signatures'; 224 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 225 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 225 226 $wpdb->query("TRUNCATE TABLE `{$table_name}`"); 226 227 /* translators: %s: Username. */ … … 235 236 $placeholders = implode(', ', array_fill(0, count($log_types_to_clear), '%s')); 236 237 237 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare 238 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 238 239 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}advaipbl_logs WHERE log_type IN ({$placeholders})", $log_types_to_clear)); 239 240 … … 250 251 case 'clear_all_logs': 251 252 global $wpdb; 252 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 253 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 253 254 $wpdb->query("TRUNCATE TABLE `{$wpdb->prefix}advaipbl_logs`"); 254 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 255 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 255 256 $wpdb->query("TRUNCATE TABLE `{$wpdb->prefix}advaipbl_notifications_queue`"); 256 257 /* translators: %s: Username. */ … … 269 270 global $wpdb; 270 271 $table_name = $wpdb->prefix . 'advaipbl_blocked_ips'; 271 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 272 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 272 273 $exists = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$table_name} WHERE ip_range = %s", $ip_or_range)); 273 274 -
advanced-ip-blocker/trunk/includes/class-advaipbl-admin-pages.php
r3471934 r3476940 228 228 $where_sql = implode(' AND ', $where_clauses); 229 229 230 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 230 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 231 231 $total_items = $wpdb->get_var("SELECT COUNT(log_id) FROM $table_name WHERE $where_sql"); 232 232 $total_pages = ceil($total_items / $per_page); 233 233 $offset = ($current_page - 1) * $per_page; 234 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 234 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 235 235 $logs = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE $where_sql ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A); 236 236 ?> … … 469 469 // phpcs:enable 470 470 471 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 471 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 472 472 $total_items = $wpdb->get_var("SELECT COUNT(id) FROM {$table_name}"); 473 473 $total_pages = ceil($total_items / $per_page); 474 474 $offset = ($current_page - 1) * $per_page; 475 475 476 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 476 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 477 477 $items = $wpdb->get_results($wpdb->prepare( 478 478 "SELECT * FROM {$table_name} ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", … … 627 627 <?php 628 628 // Primero, limpiamos los lockdowns expirados. 629 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 629 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 630 630 $wpdb->query($wpdb->prepare("DELETE FROM {$table_name} WHERE expires_at <= %d", time())); 631 631 632 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 632 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 633 633 $items = $wpdb->get_results("SELECT * FROM {$table_name} ORDER BY created_at DESC", ARRAY_A); 634 634 ?> … … 1434 1434 $where_sql = !empty($where_clauses) ? 'WHERE ' . implode(' AND ', $where_clauses) : ''; 1435 1435 1436 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 1436 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 1437 1437 $total_items = $wpdb->get_var("SELECT COUNT(id) FROM {$table_name} {$where_sql}"); 1438 1438 $total_pages = ceil($total_items / $per_page); 1439 1439 1440 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 1440 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 1441 1441 $items_for_page = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$table_name} {$where_sql} ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A); 1442 1442 … … 1900 1900 $where_sql = implode(' AND ', $where_clauses); 1901 1901 1902 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 1902 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 1903 1903 $total_items = $wpdb->get_var("SELECT COUNT(log_id) FROM $table_name WHERE $where_sql"); 1904 1904 $total_pages = ceil($total_items / $per_page); 1905 1905 $offset = ($current_page - 1) * $per_page; 1906 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 1906 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 1907 1907 $logs = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE $where_sql ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A); 1908 1908 … … 2019 2019 $where_sql = implode(' AND ', $where_clauses); 2020 2020 2021 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 2021 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 2022 2022 $total_items = $wpdb->get_var("SELECT COUNT(id) FROM {$table_name} WHERE {$where_sql}"); 2023 2023 $total_pages = ceil($total_items / $per_page); 2024 2024 $offset = ($current_page - 1) * $per_page; 2025 2025 2026 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 2026 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 2027 2027 $items = $wpdb->get_results($wpdb->prepare( 2028 2028 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared … … 2201 2201 2202 2202 $where_sql = implode(' AND ', $where_clauses); 2203 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 2203 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 2204 2204 $total_items = $wpdb->get_var("SELECT COUNT(log_id) FROM $table_name WHERE $where_sql"); 2205 2205 $total_pages = ceil($total_items / $per_page); 2206 2206 $offset = ($current_page - 1) * $per_page; 2207 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 2207 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 2208 2208 $logs = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE $where_sql ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A); 2209 2209 ?> … … 3580 3580 $table_name = $wpdb->prefix . 'advaipbl_activity_log'; 3581 3581 3582 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 3582 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 3583 3583 if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) { 3584 3584 $logs = []; … … 3590 3590 3591 3591 // Count total for pagination (Simple implementation) 3592 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 3592 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 3593 3593 $total_items = $wpdb->get_var("SELECT COUNT(id) FROM $table_name"); 3594 3594 $total_pages = ceil($total_items / $per_page); -
advanced-ip-blocker/trunk/includes/class-advaipbl-ajax-handler.php
r3472969 r3476940 171 171 global $wpdb; 172 172 $table_name = $wpdb->prefix . 'advaipbl_endpoint_lockdowns'; 173 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 173 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 174 174 $lockdown = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$table_name} WHERE id = %d", $lockdown_id), ARRAY_A); 175 175 … … 953 953 954 954 // Check if actively blocked (expires_at is 0 OR expires_at > current_time) 955 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 955 956 $exists = $wpdb->get_var($wpdb->prepare( 956 957 "SELECT COUNT(*) FROM {$table_name} WHERE ip_range = %s AND (expires_at = 0 OR expires_at > %d)", … … 1021 1022 1022 1023 // Fetch ALL actively blocked IPs (permanent or not expired) 1023 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 1024 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 1024 1025 $results = $wpdb->get_results($wpdb->prepare("SELECT ip_range, reason, expires_at, block_type FROM {$table_name} WHERE expires_at = 0 OR expires_at > %d", $current_time), ARRAY_A); 1025 1026 -
advanced-ip-blocker/trunk/includes/class-advaipbl-asn-manager.php
r3455663 r3476940 121 121 global $wpdb; 122 122 123 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 123 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 124 124 $log_json = $wpdb->get_var($wpdb->prepare( 125 125 "SELECT log_details FROM {$this->table_name} WHERE ip = %s", 126 126 $ip 127 127 )); 128 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 128 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 129 129 130 130 if ($log_json === null) { -
advanced-ip-blocker/trunk/includes/class-advaipbl-audit-logger.php
r3455663 r3476940 58 58 $ip = $this->main_instance->get_client_ip(); 59 59 60 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery 60 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 61 61 $wpdb->insert( 62 62 $this->table_name, … … 123 123 public function get_logs($limit = 20, $offset = 0) { 124 124 global $wpdb; 125 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 125 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 126 126 return $wpdb->get_results($wpdb->prepare( 127 127 "SELECT * FROM {$this->table_name} ORDER BY timestamp DESC LIMIT %d OFFSET %d", 128 128 $limit, $offset 129 129 ), ARRAY_A); 130 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 130 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 131 131 } 132 132 … … 148 148 $cutoff_date = gmdate('Y-m-d H:i:s', current_time('timestamp') - ($retention_days * DAY_IN_SECONDS)); 149 149 150 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 150 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 151 151 $wpdb->query($wpdb->prepare("DELETE FROM {$this->table_name} WHERE timestamp < %s", $cutoff_date)); 152 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 152 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 153 153 } 154 154 … … 160 160 public function clear_all_logs() { 161 161 global $wpdb; 162 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery 162 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 163 163 return $wpdb->query("TRUNCATE TABLE {$this->table_name}"); 164 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery 164 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 165 165 } 166 166 } -
advanced-ip-blocker/trunk/includes/class-advaipbl-cli.php
r3455663 r3476940 128 128 global $wpdb; 129 129 $table_name = $wpdb->prefix . 'advaipbl_logs'; 130 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery 130 131 @$wpdb->insert( $table_name, [ 'timestamp' => current_time( 'mysql', 1 ), 'ip' => is_array($ip) ? wp_json_encode($ip) : $ip, 'log_type' => 'general', 'level' => $level, 'message' => $message, 'details' => wp_json_encode( [ 'source' => 'WP-CLI' ] ) ] ); 131 132 } … … 171 172 global $wpdb; 172 173 $table_name = $wpdb->prefix . 'advaipbl_blocked_ips'; 173 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 174 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 174 175 $exists = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$table_name} WHERE ip_range = %s", $ip_or_range)); 175 176 … … 678 679 global $wpdb; $table_name = $wpdb->prefix . 'advaipbl_logs'; $type = $assoc_args['type'] ?? 'general'; $count = $assoc_args['count'] ?? 20; 679 680 $where_clause = '1=1'; if ( 'all' !== $type ) { $where_clause = $wpdb->prepare( 'log_type = %s', $type ); } 680 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 681 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 681 682 $logs = $wpdb->get_results( $wpdb->prepare( "SELECT timestamp, level, ip, message, details FROM $table_name WHERE $where_clause ORDER BY timestamp DESC LIMIT %d", $count ), ARRAY_A ); 682 683 if ( empty( $logs ) ) { WP_CLI::line( 'No log entries found for the specified type.' ); return; } … … 688 689 if ( ! isset( $assoc_args['force'] ) ) { $confirm_message = ( 'all' === $type ) ? 'Are you sure you want to clear ALL logs? This action cannot be undone.' : "Are you sure you want to clear all '{$type}' logs?"; WP_CLI::confirm( $confirm_message ); } 689 690 global $wpdb; $table_name = $wpdb->prefix . 'advaipbl_logs'; $this->log_event_autonomo( "WP-CLI: Clearing logs of type '{$type}'.", 'warning' ); 690 if ( 'all' !== $type ) { $deleted = $wpdb->delete( $table_name, [ 'log_type' => $type ], [ '%s' ] ); WP_CLI::success( "{$deleted} logs of type '{$type}' have been cleared." ); } else { 691 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 691 if ( 'all' !== $type ) { 692 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 693 $deleted = $wpdb->delete( $table_name, [ 'log_type' => $type ], [ '%s' ] ); 694 WP_CLI::success( "{$deleted} logs of type '{$type}' have been cleared." ); 695 } else { 696 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 692 697 $wpdb->query( "TRUNCATE TABLE $table_name" ); WP_CLI::success( 'All logs have been cleared.' ); } 693 698 } -
advanced-ip-blocker/trunk/includes/class-advaipbl-community-manager.php
r3464093 r3476940 36 36 37 37 // 1. Vaciar la tabla (Truncate es más rápido que Delete) 38 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter 38 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 39 39 $wpdb->query("TRUNCATE TABLE {$table_name}"); 40 40 -
advanced-ip-blocker/trunk/includes/class-advaipbl-dashboard-manager.php
r3455663 r3476940 58 58 $results = $wpdb->get_results( 59 59 $wpdb->prepare( 60 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 60 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 61 61 "SELECT log_type, COUNT(*) as count 62 62 FROM {$table_name} … … 64 64 GROUP BY log_type 65 65 ORDER BY count DESC", 66 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 66 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 67 67 $date_after 68 68 ), … … 92 92 $results = $wpdb->get_results( 93 93 $wpdb->prepare( 94 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 94 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 95 95 "SELECT DATE(timestamp) as day, COUNT(*) as count 96 96 FROM {$table_name} … … 98 98 GROUP BY day 99 99 ORDER BY day ASC", 100 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 100 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 101 101 $date_after 102 102 ), … … 132 132 return $wpdb->get_results( 133 133 $wpdb->prepare( 134 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 134 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 135 135 "SELECT ip, COUNT(*) as count 136 136 FROM {$table_name} … … 139 139 ORDER BY count DESC 140 140 LIMIT 8", 141 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 141 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 142 142 $date_after 143 143 ), … … 157 157 return $wpdb->get_results( 158 158 $wpdb->prepare( 159 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 159 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 160 160 "SELECT JSON_UNQUOTE(JSON_EXTRACT(details, '$.country')) as country, 161 161 JSON_UNQUOTE(JSON_EXTRACT(details, '$.country_code')) as country_code, … … 169 169 ORDER BY count DESC 170 170 LIMIT 8", 171 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 171 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 172 172 $date_after 173 173 ), … … 189 189 $blocked_count = $wpdb->get_var( 190 190 $wpdb->prepare( 191 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 191 // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 192 192 "SELECT COUNT(DISTINCT ip) 193 193 FROM {$table_name} … … 195 195 AND details LIKE %s 196 196 AND timestamp >= %s", 197 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared 197 // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 198 198 '%"source":"Spamhaus"%', 199 199 $date_after -
advanced-ip-blocker/trunk/includes/class-advaipbl-fingerprint-manager.php
r3464093 r3476940 71 71 72 72 // Borramos las firmas que ya han expirado 73 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 73 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 74 74 $wpdb->query($wpdb->prepare("DELETE FROM {$signatures_table} WHERE expires_at <= %d", time())); 75 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 75 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 76 76 77 77 $start_time = time() - $analysis_window_seconds; 78 78 79 79 // 1. Encontrar firmas sospechosas (usadas por múltiples IPs) 80 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 80 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 81 81 $suspicious_signatures = $wpdb->get_results( 82 82 $wpdb->prepare( … … 90 90 ) 91 91 ); 92 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 92 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 93 93 94 94 if (empty($suspicious_signatures)) { … … 100 100 foreach ($suspicious_signatures as $sig) { 101 101 // Comprobamos si esta firma ya está marcada como maliciosa (y no ha expirado) 102 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 102 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 103 103 $is_already_flagged = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$signatures_table} WHERE signature_hash = %s", $sig->signature_hash)); 104 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 104 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 105 105 if ($is_already_flagged) { 106 106 continue; … … 108 108 109 109 // 2. Obtener un ejemplo de la petición más común para esta firma 110 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 110 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 111 111 $sample = $wpdb->get_row( 112 112 $wpdb->prepare( … … 121 121 ) 122 122 ); 123 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 123 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 124 124 125 125 // Añadimos un log si la consulta de ejemplo falla, para depuración futura. … … 213 213 214 214 // 1. Obtenemos una petición de ejemplo para desglosar la firma (cabeceras, etc.) 215 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 215 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 216 216 $sample_request = $wpdb->get_row($wpdb->prepare( 217 217 "SELECT user_agent, request_headers FROM {$log_table} WHERE signature_hash = %s LIMIT 1", 218 218 $signature_hash 219 219 )); 220 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 220 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 221 221 222 222 if (!$sample_request) { … … 225 225 226 226 // 2. Obtenemos la evidencia: las últimas 15 IPs distintas que usaron esta firma. 227 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 227 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 228 228 $evidence = $wpdb->get_results($wpdb->prepare( 229 229 "SELECT DISTINCT ip_hash, user_agent, request_uri, timestamp, is_fake_bot as is_impersonator … … 234 234 $signature_hash 235 235 )); 236 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 236 // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 237 237 238 238 $details = [ -
advanced-ip-blocker/trunk/includes/class-advaipbl-live-feed-manager.php
r3455663 r3476940 53 53 54 54 $table_name = $wpdb->prefix . 'advaipbl_activity_log'; 55 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 55 56 if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name)) != $table_name) { 56 57 return new WP_REST_Response(['attacks' => [], 'last_id' => 0], 200); … … 78 79 } 79 80 80 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter 81 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 81 82 $results = $wpdb->get_results($query, ARRAY_A); 82 83 … … 105 106 break; 106 107 case 'advanced_rule': 108 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 107 109 $block_entry = $wpdb->get_row($wpdb->prepare("SELECT reason FROM {$wpdb->prefix}advaipbl_blocked_ips WHERE ip_range = %s", $row['ip']), ARRAY_A); 108 110 if ($block_entry && !empty($block_entry['reason'])) { … … 122 124 } 123 125 126 $obfuscated_ip = $this->obfuscate_ip($row['ip']); 127 124 128 $attacks[] = [ 125 129 'id' => (int) $row['log_id'], 126 130 'time' => human_time_diff(strtotime($row['timestamp'])) . ' ago', 127 'ip' => esc_html($ row['ip']),131 'ip' => esc_html($obfuscated_ip), 128 132 'type' => esc_html(ucwords(str_replace('_', ' ', $log_type))), 129 133 'location' => esc_html($location), 130 134 'method' => esc_html($details_data['method'] ?? 'N/A'), 131 'details' => esc_html($details_message), 132 'user_agent' => esc_html($details_data['user_agent'] ?? 'N/A'), 133 'uri' => esc_html($details_data['uri'] ?? ($details_data['url'] ?? '')), 135 'details' => esc_html($details_message) 134 136 ]; 135 137 } … … 143 145 144 146 /** 147 * Obfuscates an IP address for public display (GDPR compliance). 148 * IPv4: 192.168.1.55 -> 192.168.1.* 149 * IPv6: 2001:0db8:85a3:0000:0000:8a2e:0370:7334 -> 2001:0db8:85a3:****:****:****:****:**** 150 * 151 * @param string $ip 152 * @return string 153 */ 154 private function obfuscate_ip($ip) { 155 if (empty($ip)) { 156 return ''; 157 } 158 159 // IPv4 Obfuscation 160 if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { 161 $parts = explode('.', $ip); 162 if (count($parts) === 4) { 163 // Return 192.168.1.* 164 return $parts[0] . '.' . $parts[1] . '.' . $parts[2] . '.*'; 165 } 166 } 167 // IPv6 Obfuscation 168 elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { 169 // Expand IPv6 to full length to parse correctly 170 $expanded = inet_ntop(inet_pton($ip)); 171 if ($expanded !== false) { 172 $parts = explode(':', $expanded); 173 if (count($parts) === 8) { 174 // Return first 3 blocks, obfuscate the rest 175 return $parts[0] . ':' . $parts[1] . ':' . $parts[2] . ':**::**'; 176 } 177 } 178 } 179 180 // Fallback: simply mask the last half of the string if validation fails 181 $len = strlen($ip); 182 return substr($ip, 0, (int)($len / 2)) . '***'; 183 } 184 185 /** 145 186 * API Callback for Nonce. 146 187 */ … … 155 196 */ 156 197 public function render_shortcode($atts) { 157 // Use the proper paths relative to this file's location in includes/158 // Original: plugin_dir_url(dirname(__FILE__)) . 'js/...'159 // If this file is in includes/, dirname is includes.160 // plugin_dir_url(includes) -> yields URL to includes.161 // But 'js/' is usually at the root of the plugin or assets/.162 // Original main was in includes/ too? checking...163 // Main path: .../includes/class-advaipbl-main.php164 // The original code used: plugin_dir_url(dirname(__FILE__)) . 'js/advaipbl-live-feed.js'165 // dirname(__FILE__) = .../includes166 // plugin_dir_url via dirname would point to the includes folder URL.167 // BUT 'js' folder is likely parallel to 'includes', not inside it.168 // Original code logic: plugin_dir_url(...) returns URL with trailing slash.169 // If dirname is .../includes, url is https://.../includes/170 // Then . 'js/...' -> https://.../includes/js/...171 // This implies /includes/js/ exists?172 // Re-checking list_dir: js is at logical root, includes is at logical root.173 // Wait, list_dir of includes showed 'lib' inside.174 // list_dir of root (implicit from previous context) showed 'js' folder.175 // So 'js' is a sibling of 'includes'.176 // So the original code `plugin_dir_url(dirname(__FILE__))` pointing to includes/ seems wrong if it appends 'js/' directly, unless 'js' IS inside includes.177 // Let's use `plugin_dir_url( dirname( __DIR__ ) )` to go up one level safely.178 // dirname(__DIR__) from includes/class... -> .../plugin-root179 180 $root_url = plugin_dir_url( dirname( __FILE__ ) ); // Points to .../includes/ OR plugin root?181 // plugin_dir_url accepts a FILE path.182 // plugin_dir_url( __FILE__ ) -> .../includes/183 // plugin_dir_url( dirname( __FILE__ ) . '/../advanced-ip-blocker.php' ) -> Root.184 185 // Safer approach used in many plugins:186 198 $root_url = plugins_url( '/', dirname( __FILE__ ) ); 187 199 -
advanced-ip-blocker/trunk/includes/class-advaipbl-main.php
r3471934 r3476940 243 243 add_action('wp_ajax_advaipbl_run_fim_scan', [$this->ajax_handler, 'ajax_run_fim_scan']); 244 244 245 if (is_admin() || (isset($_GET['action']) && strpos($_GET['action'], 'advaipbl_') === 0)) { 245 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 246 $action = isset($_GET['action']) ? sanitize_text_field(wp_unslash($_GET['action'])) : ''; 247 if (is_admin() || (strpos($action, 'advaipbl_') === 0)) { 246 248 add_action('admin_init', [$this, 'initialize_backend_managers'], 0); 247 249 … … 446 448 public function log_request_signature() { 447 449 if (empty($this->options['enable_signature_engine'])) { return; } 450 451 $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : ''; 448 452 // No loguear las peticiones del Live Feed interno 449 if (strpos($ _SERVER['REQUEST_URI'], '/advaipbl/v1/live-attacks') !== false) {453 if (strpos($request_uri, '/advaipbl/v1/live-attacks') !== false) { 450 454 return; 451 455 } … … 456 460 } 457 461 458 $request_uri = $_SERVER['REQUEST_URI'] ?? '';459 462 if (wp_is_json_request() && strpos($request_uri, '/telemetry/') === false && strpos($request_uri, '/aib-network/') === false && strpos($request_uri, '/aib-scanner/') === false) { 460 463 return; … … 587 590 ]; 588 591 592 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 589 593 $wpdb->insert($table_name, $data_to_log); 590 594 } … … 692 696 } 693 697 698 // phpcs:ignore WordPress.Security.NonceVerification.Missing 694 699 if (isset($_POST['_advaipbl_js_token'])) { 695 700 // Parámetros para el desafío de firmas: cookie 'advaipbl_js_verified', duración 4 horas. … … 706 711 707 712 // Fix: Check if table exists to avoid fatal error on fresh install 713 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 708 714 if ($wpdb->get_var("SHOW TABLES LIKE '$signatures_table'") != $signatures_table) { 709 715 return; 710 716 } 711 717 718 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 712 719 $is_malicious = $wpdb->get_var($wpdb->prepare( 713 720 "SELECT id FROM {$signatures_table} WHERE signature_hash = %s AND expires_at > %d", … … 742 749 return; 743 750 } 751 // phpcs:ignore WordPress.Security.NonceVerification.Missing 744 752 if (isset($_POST['_advaipbl_challenge_type']) && $_POST['_advaipbl_challenge_type'] === 'geo_challenge') { 745 753 $duration_hours = (int)($this->options['geo_challenge_cookie_duration'] ?? 24); … … 978 986 } 979 987 988 // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion 980 989 wp_enqueue_script( 981 990 'google-recaptcha', … … 1118 1127 } 1119 1128 1120 if (!isset($_POST['g-recaptcha-response']) || empty($_POST['g-recaptcha-response'])) { 1129 // phpcs:ignore WordPress.Security.NonceVerification.Missing 1130 $recaptcha_response = isset($_POST['g-recaptcha-response']) ? sanitize_text_field(wp_unslash($_POST['g-recaptcha-response'])) : ''; 1131 if (empty($recaptcha_response)) { 1121 1132 return new WP_Error('recaptcha_empty', __('<strong>ERROR</strong>: Please complete the reCAPTCHA verification.', 'advanced-ip-blocker')); 1122 1133 } 1123 1134 1124 $token = sanitize_text_field($_POST['g-recaptcha-response']);1135 $token = $recaptcha_response; 1125 1136 $visitor_ip = $this->get_client_ip(); 1126 1137 … … 1262 1273 global $wpdb; 1263 1274 $table_name = $wpdb->prefix . 'advaipbl_blocked_ips'; 1264 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 1275 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 1265 1276 $count = (int) $wpdb->get_var("SELECT COUNT(id) FROM {$table_name}"); 1266 1277 wp_cache_set('blocked_ips_count', $count, 'advaipbl', 300); // Cache por 5 minutos … … 1281 1292 $count = wp_cache_get('blocked_signatures_count', 'advaipbl'); 1282 1293 if (false === $count) { 1283 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 1294 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 1284 1295 $count = (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(id) FROM {$table_name} WHERE expires_at > %d", time())); 1285 1296 wp_cache_set('blocked_signatures_count', $count, 'advaipbl', 300); // Cache por 5 minutos … … 1298 1309 if (false === $count) { 1299 1310 // Primero, limpiamos los expirados para un conteo preciso 1300 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 1311 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 1301 1312 $wpdb->query($wpdb->prepare("DELETE FROM {$table_name} WHERE expires_at <= %d", time())); 1302 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 1313 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 1303 1314 $count = (int) $wpdb->get_var("SELECT COUNT(id) FROM {$table_name}"); 1304 1315 wp_cache_set('blocked_endpoints_count', $count, 'advaipbl', 300); // Cache por 5 minutos … … 1384 1395 global $wpdb; 1385 1396 $table_name = $wpdb->prefix . 'advaipbl_cache'; 1386 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 1397 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 1387 1398 $wpdb->query("TRUNCATE TABLE `{$table_name}`"); 1388 1399 … … 1523 1534 1524 1535 // --- 1. Determinar la pestaña y sub-pestaña activas --- 1536 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 1525 1537 $current_page_slug = isset($_GET['page']) ? sanitize_key($_GET['page']) : ''; 1526 1538 1539 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 1527 1540 if (isset($_GET['tab'])) { 1541 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 1528 1542 $active_main_tab = sanitize_key($_GET['tab']); 1529 1543 } else { … … 1547 1561 } 1548 1562 1563 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 1549 1564 $active_sub_tab = isset($_GET['sub-tab']) ? sanitize_key($_GET['sub-tab']) : null; 1550 1565 … … 1618 1633 if ( 'main_dashboard' === $active_sub_tab ) { 1619 1634 wp_enqueue_script('chartjs', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/js/chart.min.js', [], '3.9.1', true); 1635 // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion 1620 1636 wp_enqueue_style('leaflet-css', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/css/leaflet.css'); 1621 1637 wp_enqueue_script('leaflet-js', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/js/leaflet.js', [], '1.9.4', true); 1638 // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion 1622 1639 wp_enqueue_style('leaflet-markercluster-css', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/css/MarkerCluster.css'); 1640 // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion 1623 1641 wp_enqueue_style('leaflet-markercluster-default-css', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/css/MarkerCluster.Default.css'); 1624 1642 wp_enqueue_script('leaflet-markercluster-js', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/js/leaflet.markercluster.js', ['leaflet-js'], '1.5.3', true); … … 1628 1646 // Cargar assets de la página "About" 1629 1647 // STRICT CHECK: Ensure we are explicitly on the about tab to avoid loading Stripe/Sift on other pages (CSP issues) 1648 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 1630 1649 if (isset($_GET['tab']) && $_GET['tab'] === 'about') { 1650 // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion 1631 1651 wp_enqueue_script('stripe-buy-button', 'https://js.stripe.com/v3/buy-button.js', [], null, true); 1632 1652 } … … 2037 2057 if ( ! empty( $this->options['prevent_author_scanning'] ) && ! is_admin() ) { 2038 2058 // Comprobamos directamente el parámetro GET 'author'. Es mucho más fiable. 2059 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 2039 2060 if ( isset( $_GET['author'] ) && is_numeric( $_GET['author'] ) ) { 2040 2061 wp_safe_redirect( home_url(), 301 ); … … 2438 2459 // If a deadlock occurs, it just means another process is handling this IP, which is fine. 2439 2460 $wpdb->suppress_errors(); 2461 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 2440 2462 $lock_acquired = $wpdb->query($wpdb->prepare("INSERT IGNORE INTO {$wpdb->prefix}advaipbl_cache (cache_key, cache_value, expires_at) VALUES (%s, '1', %d)", $lock_key, time() + 15)); 2441 2463 $wpdb->show_errors(); … … 2448 2470 2449 2471 $table_name = $wpdb->prefix . 'advaipbl_blocked_ips'; 2450 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 2472 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 2451 2473 if ($wpdb->get_var($wpdb->prepare("SELECT id FROM {$table_name} WHERE ip_range = %s", $ip))) { 2452 2474 $wpdb->delete("{$wpdb->prefix}advaipbl_cache", ['cache_key' => $lock_key]); … … 2474 2496 $expires_at = ($duration_in_seconds > 0) ? $timestamp + $duration_in_seconds : 0; 2475 2497 2498 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 2476 2499 $wpdb->insert($table_name, [ 'ip_range' => $ip, 'block_type' => $type, 'timestamp' => $timestamp, 'expires_at' => $expires_at, 'reason' => $reason_message ]); 2477 2500 … … 2534 2557 } 2535 2558 2559 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 2536 2560 $wpdb->delete("{$wpdb->prefix}advaipbl_cache", ['cache_key' => $lock_key]); 2537 2561 … … 2597 2621 $table_name = $wpdb->prefix . 'advaipbl_logs'; 2598 2622 2599 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 2623 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter 2600 2624 $wpdb->query($wpdb->prepare("DELETE FROM $table_name WHERE timestamp < DATE_SUB(NOW(), INTERVAL %d DAY)", $retention_days)); 2601 2625 } … … 2616 2640 $table_blocked = $wpdb->prefix . 'advaipbl_blocked_ips'; 2617 2641 2642 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 2618 2643 $table_missing = ($wpdb->get_var("SHOW TABLES LIKE '$table_audit'") != $table_audit) 2619 2644 || ($wpdb->get_var("SHOW TABLES LIKE '$table_blocked'") != $table_blocked); … … 2756 2781 2757 2782 // Insertamos la fila en la nueva tabla. 2783 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 2758 2784 $wpdb->insert( 2759 2785 $table_name, … … 3260 3286 } 3261 3287 3288 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 3262 3289 @$wpdb->insert( 3263 3290 $table_name, … … 3476 3503 3477 3504 $wpdb->suppress_errors(); // Avoid deadlock noise 3505 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 3478 3506 $lock_acquired = $wpdb->query($wpdb->prepare( 3479 3507 "INSERT IGNORE INTO {$wpdb->prefix}advaipbl_cache (cache_key, cache_value, expires_at) VALUES (%s, %s, %d)", … … 3486 3514 } 3487 3515 $table_name_blocked = $wpdb->prefix . 'advaipbl_blocked_ips'; 3488 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 3516 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 3489 3517 $existing_block = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$table_name_blocked} WHERE ip_range = %s", $ip)); 3490 3518 if ($existing_block) { 3519 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 3491 3520 $wpdb->delete("{$wpdb->prefix}advaipbl_cache", ['cache_key' => $lock_key]); 3492 3521 return; … … 3507 3536 $option_key = $option_key_map[$type] ?? null; 3508 3537 if ( ! $option_key ) { 3538 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 3509 3539 $wpdb->delete("{$wpdb->prefix}advaipbl_cache", ['cache_key' => $lock_key]); // Liberar cerrojo antes de salir 3510 3540 return; … … 3579 3609 } elseif ($notification_enabled && in_array($frequency, ['daily', 'weekly'])) { 3580 3610 $table_name_queue = $wpdb->prefix . 'advaipbl_notifications_queue'; 3611 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 3581 3612 @$wpdb->insert($table_name_queue, ['timestamp' => current_time('mysql', 1), 'ip' => $ip, 'block_type' => $type, 'reason' => $reason]); 3582 3613 } … … 3599 3630 } 3600 3631 3632 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 3601 3633 $wpdb->delete("{$wpdb->prefix}advaipbl_cache", ['cache_key' => $lock_key]); 3602 3634 } … … 4085 4117 $this->block_response_initiated = true; 4086 4118 4087 $is_xmlrpc_request = (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], 'xmlrpc.php') !== false); 4119 $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : ''; 4120 $is_xmlrpc_request = (strpos($request_uri, 'xmlrpc.php') !== false); 4088 4121 4089 4122 $custom_message = $this->options['custom_block_message'] ?? ''; … … 4152 4185 $is_single_ip = filter_var($entry_to_unblock, FILTER_VALIDATE_IP); 4153 4186 4154 // Borrar de la nueva tabla4187 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 4155 4188 $wpdb->delete($table_name, ['ip_range' => $entry_to_unblock]); 4156 4189 4157 4190 // También borrar de la tabla de reportes pendientes para evitar falsos positivos 4158 4191 $table_reports = $wpdb->prefix . 'advaipbl_pending_reports'; 4192 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 4159 4193 $wpdb->delete($table_reports, ['ip' => $entry_to_unblock]); 4160 4194 … … 4212 4246 4213 4247 // 1. Vaciar la tabla de IPs bloqueadas. 4214 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 4248 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 4215 4249 $wpdb->query("TRUNCATE TABLE `{$table_name_blocked}`"); 4216 4250 4217 4251 // También vaciar la tabla de reportes pendientes 4218 4252 $table_reports = $wpdb->prefix . 'advaipbl_pending_reports'; 4219 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 4253 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 4220 4254 $wpdb->query("TRUNCATE TABLE `{$table_reports}`"); 4221 4255 … … 4260 4294 // 1. Obtener todas las IPs que van a expirar 4261 4295 // Aumentamos el límite a 100 para procesar en lotes razonables y evitar timeouts masivos 4262 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 4296 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 4263 4297 $expiring_ips = $wpdb->get_results($wpdb->prepare( 4264 4298 "SELECT ip_range, block_type FROM {$table_name} WHERE expires_at < %d AND expires_at > 0 LIMIT 100", … … 4683 4717 */ 4684 4718 public function conditionally_remove_admin_notices() { 4719 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 4685 4720 $current_page_slug = isset($_GET['page']) ? sanitize_key($_GET['page']) : ''; 4686 4721 $plugin_pages = [ … … 5003 5038 5004 5039 // Obtenemos los parámetros de la URL actual para mantenerlos al ordenar 5040 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 5005 5041 $current_params = $_GET; 5006 5042 $url_params = array_merge($current_params, [ … … 5189 5225 $definitions = $this->get_all_block_type_definitions(); 5190 5226 5191 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 5227 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 5192 5228 $results = $wpdb->get_results("SELECT * FROM {$table_name}", ARRAY_A); 5193 5229 … … 5486 5522 public function display_telemetry_notice() { 5487 5523 // Condición 1: Solo mostrar en las páginas de nuestro plugin. 5488 if (!isset($_GET['page']) || strpos($_GET['page'], 'advaipbl_settings_page') === false) { 5524 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 5525 $page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : ''; 5526 if (strpos($page, 'advaipbl_settings_page') === false) { 5489 5527 return; 5490 5528 } … … 5600 5638 5601 5639 $seven_days_ago = gmdate('Y-m-d H:i:s', strtotime('-7 days')); 5640 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 5602 5641 $blocks_by_type_results = $wpdb->get_results( $wpdb->prepare( 5603 5642 "SELECT log_type, COUNT(log_id) as count FROM {$wpdb->prefix}advaipbl_logs WHERE level = 'critical' AND timestamp >= %s GROUP BY log_type", … … 5617 5656 'blocked_user_agents_count' => count(get_option(self::OPTION_BLOCKED_UAS, [])), 5618 5657 'manual_asn_count' => count(get_option(self::OPTION_BLOCKED_ASNS, [])), 5658 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 5619 5659 'total_blocks_7d' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(log_id) FROM {$wpdb->prefix}advaipbl_logs WHERE level = 'critical' AND timestamp >= %s", $seven_days_ago)), 5620 5660 'blocks_by_type_7d' => $blocks_by_type_7d, 5621 5661 'geoblock_country_count' => count($this->options['geoblock_countries'] ?? []), 5622 5662 'active_blocks_count' => $this->get_blocked_count(), 5663 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 5623 5664 'ips_with_active_score' => (int) $wpdb->get_var("SELECT COUNT(id) FROM {$wpdb->prefix}advaipbl_ip_scores"), 5665 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 5624 5666 'active_malicious_signatures' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(id) FROM {$wpdb->prefix}advaipbl_malicious_signatures WHERE expires_at > %d", time())), 5625 5667 'geo_challenge_country_count' => count($this->options['geo_challenge_countries'] ?? []), … … 5656 5698 check_ajax_referer( 'advaipbl_export_nonce', 'nonce' ); 5657 5699 5658 $export_type = isset( $_POST['export_type'] ) && in_array( $_POST['export_type'], ['template', 'full_backup'] ) ? $_POST['export_type'] : 'template'; 5700 $export_type_raw = isset( $_POST['export_type'] ) ? sanitize_text_field(wp_unslash($_POST['export_type'])) : 'template'; 5701 $export_type = in_array( $export_type_raw, ['template', 'full_backup'] ) ? $export_type_raw : 'template'; 5659 5702 5660 5703 global $wpdb; … … 5669 5712 // 2. Exportar la tabla de IPs bloqueadas 5670 5713 $table_name = $wpdb->prefix . 'advaipbl_blocked_ips'; 5671 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 5714 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 5672 5715 $blocked_ips_data = $wpdb->get_results("SELECT ip_range, block_type, timestamp, expires_at, reason FROM {$table_name}", ARRAY_A); 5673 5716 if (!empty($blocked_ips_data)) { … … 5680 5723 'recaptcha_site_key', 'recaptcha_secret_key', 5681 5724 'api_key_ipapicom', 'api_key_ipstackcom', 'api_key_ipinfocom', 5682 'api_key_ip_apicom', 'maxmind_license_key', 'push_webhook_urls' 5725 'api_key_ip_apicom', 'maxmind_license_key', 'push_webhook_urls', 5726 'cf_api_token', 'cf_zone_id', 'abuseipdb_api_key' 5683 5727 ]; 5684 5728 foreach ($sensitive_keys as $sensitive_key) { … … 5710 5754 $type = 'error'; 5711 5755 5712 if ( isset( $_FILES['advaipbl_import_file'] ) && UPLOAD_ERR_OK === $_FILES['advaipbl_import_file']['error'] ) { 5713 $file_name = $_FILES['advaipbl_import_file']['name']; 5756 $file_error = isset($_FILES['advaipbl_import_file']['error']) ? (int) $_FILES['advaipbl_import_file']['error'] : UPLOAD_ERR_NO_FILE; 5757 if ( isset( $_FILES['advaipbl_import_file'] ) && UPLOAD_ERR_OK === $file_error ) { 5758 $file_name = isset( $_FILES['advaipbl_import_file']['name'] ) ? sanitize_file_name(wp_unslash($_FILES['advaipbl_import_file']['name'])) : ''; 5714 5759 if ( 'json' !== pathinfo( $file_name, PATHINFO_EXTENSION ) ) { 5715 5760 $message = __( 'Error: The uploaded file is not a .json file.', 'advanced-ip-blocker' ); 5716 5761 $this->log_event( sprintf( 'A failed settings import was attempted by %s (invalid file type).', $this->get_current_admin_username() ), 'error' ); 5717 5762 } else { 5718 $file_content = file_get_contents( $_FILES['advaipbl_import_file']['tmp_name'] ); 5763 $tmp_name = isset( $_FILES['advaipbl_import_file']['tmp_name'] ) ? sanitize_text_field(wp_unslash($_FILES['advaipbl_import_file']['tmp_name'])) : ''; 5764 if (empty($tmp_name)) { 5765 return; 5766 } 5767 $file_content = file_get_contents( $tmp_name ); 5719 5768 $settings_to_import = json_decode( $file_content, true ); 5720 5769 … … 5739 5788 global $wpdb; 5740 5789 $table_name = $wpdb->prefix . 'advaipbl_blocked_ips'; 5741 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 5790 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 5742 5791 $wpdb->query("TRUNCATE TABLE `{$table_name}`"); 5743 5792 … … 5897 5946 public function handle_login_action() { 5898 5947 if ( ! isset( $_POST['advaipbl_2fa_login_step'] ) ) { return; } 5899 $step = $_POST['advaipbl_2fa_login_step'];5948 $step = sanitize_text_field(wp_unslash($_POST['advaipbl_2fa_login_step'])); 5900 5949 $user_id = isset( $_POST['user_id'] ) ? absint( $_POST['user_id'] ) : 0; 5901 $code = isset( $_POST['advaipbl_2fa_code'] ) ? trim( sanitize_text_field( $_POST['advaipbl_2fa_code']) ) : '';5902 $nonce = $_POST['_wpnonce'] ??'';5950 $code = isset( $_POST['advaipbl_2fa_code'] ) ? trim( sanitize_text_field( wp_unslash($_POST['advaipbl_2fa_code']) ) ) : ''; 5951 $nonce = isset($_POST['_wpnonce']) ? sanitize_text_field(wp_unslash($_POST['_wpnonce'])) : ''; 5903 5952 $user = get_user_by( 'id', $user_id ); 5904 5953 if ( ! $user ) { wp_die( 'Authentication error: Invalid user.' ); } … … 5921 5970 if ( $is_valid ) { 5922 5971 wp_set_auth_cookie( $user->ID, isset( $_POST['rememberme'] ) ); 5923 $redirect_to = isset( $_REQUEST['redirect_to'] ) && !empty($_REQUEST['redirect_to']) ? wp_unslash( $_REQUEST['redirect_to']) : admin_url();5972 $redirect_to = (isset( $_REQUEST['redirect_to'] ) && !empty($_REQUEST['redirect_to'])) ? sanitize_text_field(wp_unslash( $_REQUEST['redirect_to'] )) : admin_url(); 5924 5973 wp_safe_redirect( $redirect_to ); 5925 5974 exit; … … 5935 5984 'user_id' => $user->ID, 5936 5985 'wp_auth_nonce' => wp_create_nonce( 'advaipbl-2fa-interim-' . $user->ID ), 5937 'redirect_to' => $_REQUEST['redirect_to'] ??'',5986 'redirect_to' => isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '', 5938 5987 ], site_url( 'wp-login.php', 'login' ) ); 5939 5988 wp_safe_redirect( $redirect_url ); … … 5976 6025 'user_id' => $user->ID, 5977 6026 'wp_auth_nonce' => wp_create_nonce( 'advaipbl-2fa-interim-' . $user->ID ), 5978 'redirect_to' => $_REQUEST['redirect_to'] ?? '', 5979 'rememberme' => $_REQUEST['rememberme'] ?? '', 6027 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 6028 'redirect_to' => isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '', 6029 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 6030 'rememberme' => isset($_REQUEST['rememberme']) ? sanitize_text_field(wp_unslash($_REQUEST['rememberme'])) : '', 5980 6031 ], site_url( 'wp-login.php', 'login' ) ); 5981 6032 wp_safe_redirect( $redirect_url ); … … 5997 6048 public function display_2fa_login_form_step_2() { 5998 6049 $user_id = isset( $_GET['user_id'] ) ? absint( $_GET['user_id'] ) : 0; 5999 $nonce = $_GET['wp_auth_nonce'] ??'';6050 $nonce = isset($_GET['wp_auth_nonce']) ? sanitize_text_field(wp_unslash($_GET['wp_auth_nonce'])) : ''; 6000 6051 6001 6052 if ( ! $user_id || ! wp_verify_nonce( $nonce, 'advaipbl-2fa-interim-' . $user_id ) ) { … … 6005 6056 $message = ''; 6006 6057 if ( isset( $_COOKIE['advaipbl_login_error'] ) ) { 6007 $message = '<div id="login_error" class="notice notice-error">' . wp_kses_post( $_COOKIE['advaipbl_login_error']) . '</div>';6058 $message = '<div id="login_error" class="notice notice-error">' . wp_kses_post( wp_unslash($_COOKIE['advaipbl_login_error']) ) . '</div>'; 6008 6059 // Borramos la cookie para que no se muestre de nuevo 6009 6060 unset( $_COOKIE['advaipbl_login_error'] ); … … 6025 6076 </p> 6026 6077 <input type="hidden" name="user_id" value="<?php echo esc_attr( $user_id ); ?>" /> 6027 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $_REQUEST['redirect_to'] ??'' ); ?>" />6028 <input type="hidden" name="rememberme" value="<?php echo esc_attr( $_REQUEST['rememberme'] ??'' ); ?>" />6078 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '' ); ?>" /> 6079 <input type="hidden" name="rememberme" value="<?php echo esc_attr( isset($_REQUEST['rememberme']) ? sanitize_text_field(wp_unslash($_REQUEST['rememberme'])) : '' ); ?>" /> 6029 6080 <input type="hidden" name="advaipbl_2fa_login_step" value="2" /> 6030 6081 <?php wp_nonce_field( 'advaipbl-2fa-verify-' . $user_id ); ?> … … 6040 6091 'user_id' => $user_id, 6041 6092 'wp_auth_nonce' => $nonce, 6042 'redirect_to' => $_REQUEST['redirect_to'] ??'',6093 'redirect_to' => isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '', 6043 6094 ], site_url( 'wp-login.php', 'login' ) ) ); 6044 6095 ?>"> … … 6057 6108 public function display_2fa_backup_code_form() { 6058 6109 $user_id = isset( $_GET['user_id'] ) ? absint( $_GET['user_id'] ) : 0; 6059 $nonce = $_GET['wp_auth_nonce'] ??'';6110 $nonce = isset($_GET['wp_auth_nonce']) ? sanitize_text_field(wp_unslash($_GET['wp_auth_nonce'])) : ''; 6060 6111 6061 6112 if ( ! $user_id || ! wp_verify_nonce( $nonce, 'advaipbl-2fa-interim-' . $user_id ) ) { … … 6065 6116 $message = ''; 6066 6117 if ( isset( $_COOKIE['advaipbl_login_error'] ) ) { 6067 $message = '<div id="login_error" class="notice notice-error">' . wp_kses_post( $_COOKIE['advaipbl_login_error']) . '</div>';6118 $message = '<div id="login_error" class="notice notice-error">' . wp_kses_post( wp_unslash($_COOKIE['advaipbl_login_error']) ) . '</div>'; 6068 6119 unset( $_COOKIE['advaipbl_login_error'] ); 6069 6120 setcookie( 'advaipbl_login_error', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN ); … … 6084 6135 </p> 6085 6136 <input type="hidden" name="user_id" value="<?php echo esc_attr( $user_id ); ?>" /> 6086 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $_REQUEST['redirect_to'] ??'' ); ?>" />6087 <input type="hidden" name="rememberme" value="<?php echo esc_attr( $_REQUEST['rememberme'] ??'' ); ?>" />6137 <input type="hidden" name="redirect_to" value="<?php echo esc_attr( isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '' ); ?>" /> 6138 <input type="hidden" name="rememberme" value="<?php echo esc_attr( isset($_REQUEST['rememberme']) ? sanitize_text_field(wp_unslash($_REQUEST['rememberme'])) : '' ); ?>" /> 6088 6139 <input type="hidden" name="advaipbl_2fa_login_step" value="backup" /> 6089 6140 <?php wp_nonce_field( 'advaipbl-2fa-verify-backup-' . $user_id ); ?> … … 6099 6150 'user_id' => $user_id, 6100 6151 'wp_auth_nonce' => $nonce, 6101 'redirect_to' => $_REQUEST['redirect_to'] ??'',6152 'redirect_to' => isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '', 6102 6153 ], site_url( 'wp-login.php', 'login' ) ) ); 6103 6154 ?>"> … … 6402 6453 ) { 6403 6454 // Increase limits for large file download/extraction 6455 // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged 6404 6456 if (function_exists('set_time_limit')) { @set_time_limit(300); } 6457 // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged 6405 6458 @ini_set('memory_limit', '256M'); 6406 6459 … … 6469 6522 $table_name = $wpdb->prefix . 'advaipbl_blocked_ips'; 6470 6523 6471 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 6524 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 6472 6525 $is_blocked_in_db = $wpdb->get_var( $wpdb->prepare( 6473 6526 "SELECT id FROM {$table_name} WHERE ip_range = %s AND (expires_at = 0 OR expires_at > %d)", … … 6523 6576 6524 6577 foreach ($options_to_optimize as $option_name) { 6578 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 6525 6579 $wpdb->query( $wpdb->prepare( 6526 6580 "UPDATE {$wpdb->options} SET `autoload` = 'no' WHERE `option_name` = %s", … … 6592 6646 static $request_method = null; 6593 6647 if (is_null($request_method)) { 6594 $request_method = sanitize_text_field($_SERVER['REQUEST_METHOD'] ?? 'GET'); 6648 $request_method_raw = isset($_SERVER['REQUEST_METHOD']) ? wp_unslash($_SERVER['REQUEST_METHOD']) : 'GET'; 6649 $request_method = sanitize_text_field($request_method_raw); 6595 6650 } 6596 6651 return $request_method; … … 6616 6671 static $remote_addr = null; 6617 6672 if (is_null($remote_addr)) { 6618 $remote_addr = filter_var($_SERVER['REMOTE_ADDR'] ?? '', FILTER_VALIDATE_IP) ?: ''; 6673 $remote_addr_raw = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : ''; 6674 $remote_addr = filter_var($remote_addr_raw, FILTER_VALIDATE_IP) ?: ''; 6619 6675 } 6620 6676 return $remote_addr; … … 6671 6727 6672 6728 // Insertamos el lockdown en nuestra nueva tabla. 6729 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 6673 6730 $wpdb->insert( 6674 6731 $lockdowns_table, … … 6683 6740 6684 6741 // Limpiamos el contador de la caché, ya que el lockdown está activo. 6742 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 6685 6743 $wpdb->delete($wpdb->prefix . 'advaipbl_cache', ['cache_key' => $cache_key]); 6686 6744 … … 6734 6792 6735 6793 // Verificamos que no haya ya un lockdown activo para este endpoint para evitar duplicados. 6736 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 6794 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 6737 6795 $is_already_active = $wpdb->get_var($wpdb->prepare( 6738 6796 "SELECT id FROM {$lockdowns_table} WHERE endpoint_key = %s AND expires_at > %d", … … 6751 6809 $details = wp_json_encode(['triggering_ip_hashes' => $trigger_data['ip_hashes']]); 6752 6810 6811 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 6753 6812 $wpdb->insert( 6754 6813 $lockdowns_table, … … 6767 6826 6768 6827 // Limpiamos el contador de la caché, ya que el lockdown está activo. 6828 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 6769 6829 $wpdb->delete($wpdb->prefix . 'advaipbl_cache', ['cache_key' => $cache_key]); 6770 6830 } … … 6788 6848 6789 6849 // Procesa la respuesta del desafío si es para este tipo. 6850 // phpcs:ignore WordPress.Security.NonceVerification.Missing 6790 6851 if (isset($_POST['_advaipbl_challenge_type']) && $_POST['_advaipbl_challenge_type'] === 'endpoint') { 6791 6852 // Un pase de 1 hora es suficiente para un endpoint crítico. … … 6815 6876 global $wpdb; 6816 6877 $lockdowns_table = $wpdb->prefix . 'advaipbl_endpoint_lockdowns'; 6817 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 6878 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 6818 6879 $is_lockdown_active = $wpdb->get_var($wpdb->prepare( 6819 6880 "SELECT id FROM {$lockdowns_table} WHERE endpoint_key = %s AND expires_at > %d", … … 6890 6951 public function display_setup_wizard_notice() { 6891 6952 // Solo mostrar el aviso si la bandera existe, el usuario puede gestionar opciones, y no estamos ya en el asistente. 6953 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 6892 6954 if ( get_option( 'advaipbl_run_setup_wizard' ) && current_user_can( 'manage_options' ) && ( ! isset( $_GET['page'] ) || $_GET['page'] !== 'advaipbl-setup-wizard' ) ) { 6893 6955 $wizard_url = admin_url( 'admin.php?page=advaipbl-setup-wizard' ); … … 7044 7106 7045 7107 // Check if already active 7046 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 7108 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 7047 7109 $is_active = $wpdb->get_var($wpdb->prepare( 7048 7110 "SELECT id FROM {$lockdowns_table} WHERE endpoint_key = %s AND expires_at > %d", … … 7068 7130 $details = wp_json_encode($details_array); 7069 7131 7132 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 7070 7133 $wpdb->insert( 7071 7134 $lockdowns_table, … … 7084 7147 7085 7148 // Clear cache as lockdown is now active 7149 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 7086 7150 $wpdb->delete($wpdb->prefix . 'advaipbl_cache', ['cache_key' => $cache_key]); 7087 7151 } … … 7094 7158 global $wpdb; 7095 7159 $lockdowns_table = $wpdb->prefix . 'advaipbl_endpoint_lockdowns'; 7096 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 7160 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 7097 7161 return $wpdb->get_var($wpdb->prepare( 7098 7162 "SELECT id FROM {$lockdowns_table} WHERE endpoint_key = %s AND expires_at > %d", … … 7102 7166 7103 7167 public function scanner_ping_endpoint() { 7168 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 7104 7169 if (isset($_GET['advaipbl-ping']) && $_GET['advaipbl-ping'] === '1') { 7105 7170 … … 7120 7185 $expected_user_agent = base64_decode($encoded_user_agent); 7121 7186 7122 $visitor_ip = $_SERVER['REMOTE_ADDR'] ??'';7123 $request_user_agent = $_SERVER['HTTP_USER_AGENT'] ??'';7187 $visitor_ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : ''; 7188 $request_user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : ''; 7124 7189 7125 7190 if (in_array($visitor_ip, $allowed_ips, true) && hash_equals($expected_user_agent, $request_user_agent)) { -
advanced-ip-blocker/trunk/includes/class-advaipbl-notification-manager.php
r3464093 r3476940 52 52 if (!empty($ids)) { 53 53 $ids_placeholder = implode(',', $ids); 54 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery 54 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 55 55 $wpdb->query("DELETE FROM $table_name WHERE id IN ($ids_placeholder)"); 56 56 } … … 94 94 if (!empty($ids)) { 95 95 $ids_placeholder = implode(',', $ids); 96 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery 96 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 97 97 $wpdb->query("DELETE FROM $table_name WHERE id IN ($ids_placeholder)"); 98 98 } -
advanced-ip-blocker/trunk/includes/class-advaipbl-threat-score-manager.php
r3419894 r3476940 38 38 global $wpdb; 39 39 40 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 40 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 41 41 $score = $wpdb->get_var($wpdb->prepare( 42 42 "SELECT score FROM {$this->table_name} WHERE ip = %s", … … 77 77 78 78 // Obtenemos el log existente para poder añadir la nueva entrada. 79 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 79 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 80 80 $existing_log_json = $wpdb->get_var($wpdb->prepare( 81 81 "SELECT log_details FROM {$this->table_name} WHERE ip = %s", … … 99 99 100 100 // Usamos una única consulta eficiente para insertar o actualizar. 101 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 101 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 102 102 $wpdb->query($wpdb->prepare( 103 103 "INSERT INTO {$this->table_name} (ip, score, last_event_timestamp, log_details) … … 140 140 // 1. Reducimos la puntuación de las IPs inactivas. 141 141 // Usamos una consulta SQL para restar los puntos, asegurándonos de que nunca baje de 0. 142 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 142 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 143 143 $updated = $wpdb->query($wpdb->prepare( 144 144 "UPDATE {$this->table_name} 145 SET score = GREATEST(0, score - %d)145 SET score = GREATEST(0, score - %d) 146 146 WHERE last_event_timestamp < %d", 147 147 $decay_points, … … 151 151 // 2. Eliminamos las filas cuya puntuación ha llegado a 0. 152 152 // Esto mantiene la tabla limpia y eficiente. 153 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 153 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 154 154 $deleted = $wpdb->query( 155 155 "DELETE FROM {$this->table_name} WHERE score <= 0" … … 172 172 global $wpdb; 173 173 174 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 174 175 $result = $wpdb->delete( 175 176 $this->table_name, … … 191 192 global $wpdb; 192 193 193 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared 194 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter 194 195 $log_json = $wpdb->get_var($wpdb->prepare( 195 196 "SELECT log_details FROM {$this->table_name} WHERE ip = %s", -
advanced-ip-blocker/trunk/js/advaipbl-live-feed.js
r3353165 r3476940 1 jQuery(document).ready(function ($) {1 jQuery(document).ready(function ($) { 2 2 3 3 const feedContainer = $('#advaipbl-live-feed-container'); … … 10 10 const nonceUrl = window.advaipbl_feed_data.nonce_url || ''; 11 11 const texts = window.advaipbl_feed_data.text || {}; 12 12 13 13 let lastId = 0; 14 14 let isFetching = false; … … 20 20 detailsHtml += `<div class="feed-label">${texts.method || 'Method'}</div><div class="feed-value"><code>${attack.method}</code></div>`; 21 21 detailsHtml += `<div class="feed-label">${texts.details || 'Details'}</div><div class="feed-value">${attack.details}</div>`; 22 if (attack.uri) {23 detailsHtml += `<div class="feed-label">${texts.uri || 'URI'}</div><div class="feed-value"><code>${attack.uri}</code></div>`;24 }25 if (attack.user_agent && attack.user_agent !== 'N/A') {26 detailsHtml += `<div class="feed-label">${texts.user_agent || 'User Agent'}</div><div class="feed-value"><code>${attack.user_agent}</code></div>`;27 }28 22 detailsHtml += '</div>'; 29 23 return ` … … 54 48 55 49 const url = `${apiUrl}?${params.toString()}`; 56 57 $.get(url, function (response) {50 51 $.get(url, function (response) { 58 52 if (response && response.attacks && response.attacks.length > 0) { 59 53 feedList.find('.placeholder').remove(); … … 65 59 } 66 60 } 67 }).always(function () {61 }).always(function () { 68 62 isFetching = false; 69 63 }); 70 64 } 71 65 72 66 function initializeFeed() { 73 67 if (!nonceUrl) { … … 76 70 } 77 71 // 1. Primero, obtenemos un nonce fresco que no esté cacheado. 78 $.get(nonceUrl, function (response) {72 $.get(nonceUrl, function (response) { 79 73 if (response && response.nonce) { 80 74 freshNonce = response.nonce; … … 86 80 console.error('Live Feed: Failed to fetch a valid nonce.'); 87 81 } 88 }).fail(function () {82 }).fail(function () { 89 83 console.error('Live Feed: AJAX error while fetching nonce.'); 90 84 }); -
advanced-ip-blocker/trunk/languages/advanced-ip-blocker.pot
r3472969 r3476940 4 4 msgid "" 5 5 msgstr "" 6 "Project-Id-Version: Advanced IP Blocker 8.8. 8\n"6 "Project-Id-Version: Advanced IP Blocker 8.8.9\n" 7 7 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/advanced-ip-blocker\n" 8 8 "POT-Creation-Date: 2025-07-22 14:47+0200\n" -
advanced-ip-blocker/trunk/readme.txt
r3472969 r3476940 6 6 Requires at least: 6.7 7 7 Tested up to: 6.9 8 Stable tag: 8.8. 88 Stable tag: 8.8.9 9 9 Requires PHP: 8.1 10 10 License: GPLv2 or later … … 224 224 == Changelog == 225 225 226 = 8.8.9 = 227 * **SECURITY UPDATE:** Fixed an issue where the "Export Template" feature was inadvertently including sensitive API keys (`cf_api_token`, `cf_zone_id`, `abuseipdb_api_key`) in the generated JSON. Templates are now completely clean of private tokens. 228 * **MAINTENANCE:** Cleaned up excessive developer comments in the frontend JS inclusion logic for better code readability. 229 * **MAINTENANCE:** Analyzed and ensured that the background Cloudflare Sync task (`advaipbl_cloudflare_sync_event`) schedules properly. 230 226 231 = 8.8.8 = 227 232 * **CRITICAL FIX:** Resolved an issue where IPs imported via the Bulk Import tool were not immediately synchronized with the Server-Level Firewall (`.htaccess`). Synchronization is now instantaneous and safely batched. 233 * **CRITICAL FIX:** Addressed a regression introduced in the `.htaccess` fix where Cloudflare Edge Firewalls stopped synchronizing imported IPs. Bulk Imports will now immediately trigger a background Cloudflare Sync Event to safely upload large IP batches without dropping connections. 228 234 229 235 = 8.8.7 = … … 399 405 == Upgrade Notice == 400 406 407 = 8.8.9 = 408 **SECURITY UPDATE:** Patches a vulnerability in the Settings exporter where the "Template (No API Keys)" file was accidentally leaking Cloudflare and AbuseIPDB API keys. Update immediately if you plan to export your configuration templates to share with others. 409 401 410 = 8.8.8 = 402 **CRITICAL UPDATE:** Fixes a `.htaccess` synchronization bug with the Bulk Import tool. Update immediately to ensure imported IPs are actively blocking threats at the server level.411 **CRITICAL UPDATE:** Fixes a `.htaccess` synchronization bug with the Bulk Import tool. Resolves a regression where Bulk Imports stopped pushing new blocks to Cloudflare. Update immediately to ensure imported IPs are actively blocking threats at both the server level and the cloud edge. 403 412 404 413 = 8.8.7 = -
advanced-ip-blocker/trunk/uninstall.php
r3464093 r3476940 39 39 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound 40 40 foreach ( $tables_to_drop as $table_name ) { 41 // phpcs:ignore WordPress.DB.DirectDatabaseQuery. NoCaching, WordPress.DB.PreparedSQL.NotPrepared41 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared 42 42 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . $table_name ); 43 43 }
Note: See TracChangeset
for help on using the changeset viewer.