PluginProbe ʕ •ᴥ•ʔ
Really Simple Security – Simple and Performant Security (formerly Really Simple SSL) / 9.5.0.1
Really Simple Security – Simple and Performant Security (formerly Really Simple SSL) v9.5.0.1
9.5.11 9.5.10.1 9.5.10 trunk 9.4.0 9.4.1 9.4.2 9.4.3 9.5.0 9.5.0.1 9.5.0.2 9.5.1 9.5.2 9.5.2.2 9.5.2.3 9.5.3 9.5.3.1 9.5.3.2 9.5.4 9.5.5 9.5.6 9.5.7 9.5.8 9.5.9
really-simple-ssl / security / includes / check404 / class-rsssl-simple-404-interceptor.php
really-simple-ssl / security / includes / check404 Last commit date
class-rsssl-simple-404-interceptor.php 1 year ago class-rsssl-test-404.php 1 year ago
class-rsssl-simple-404-interceptor.php
147 lines
1 <?php
2 namespace RSSSL\Security\Includes\Check404;
3
4 class Rsssl_Simple_404_Interceptor {
5
6 private $attempts = 10; // Default attempts threshold
7 private $time_span = 5; // Time span in seconds (5 seconds)
8 private $option_name = 'rsssl_404_cache';
9 private $notice_option = 'rsssl_404_notice_shown';
10
11 public function __construct() {
12 // Load the 404 test class only if the firewall has been enabled
13 if ( rsssl_get_option('enable_firewall') == '1' ) {
14 add_action( 'admin_init', array( $this, 'maybe_load_class_404_test' ), 20, 4 );
15 }
16
17 add_filter( 'rsssl_notices', array( $this, 'show_help_notices' ) );
18
19 if ( defined( 'rsssl_pro' ) ) {
20 return;
21 }
22
23 add_action( 'template_redirect', array( $this, 'detect_404' ) );
24 }
25 /**
26 * Detect and handle 404 errors.
27 */
28 public function detect_404(): void {
29 if (is_404()) {
30 if ( get_option( $this->notice_option ) ) {
31 return;
32 }
33 $ip_address = $this->get_ip_address();
34 $current_time = time();
35
36 // Prevent the option from becoming too large
37 $cache = get_option($this->option_name, []);
38
39 if (!isset($cache[$ip_address])) {
40 $cache[$ip_address] = [];
41 }
42
43 $cache[$ip_address][] = $current_time;
44 $cache[$ip_address] = $this->clean_up_old_entries($cache[$ip_address]);
45
46 if (count($cache[$ip_address]) > $this->attempts && !get_option($this->notice_option)) {
47 update_option($this->notice_option, true, false);
48
49 return;
50 }
51
52 update_option($this->option_name, $cache, false);
53 }
54 }
55
56 /**
57 * Cleans up old entries based on the given timestamps.
58 *
59 * This method filters the given timestamps array and only keeps the entries where the difference between the current time
60 * and the timestamp is less than the specified time span.
61 *
62 * @param array $timestamps An array of timestamps.
63 *
64 * @return array The cleaned up timestamps array.
65 */
66 private function clean_up_old_entries($timestamps): array {
67 $current_time = time();
68 return array_filter($timestamps, function($timestamp) use ($current_time) {
69 return ($current_time - $timestamp) < $this->time_span;
70 });
71 }
72
73 /**
74 * Retrieves the IP address of the client.
75 *
76 * This method checks for the IP address in the following order:
77 * 1. HTTP_CLIENT_IP: Represents the IP address of the client if the client is a shared internet device.
78 * 2. HTTP_X_FORWARDED_FOR: Represents the IP address of the client if the client is accessing the server through a proxy server.
79 * 3. REMOTE_ADDR: Represents the IP address of the client if the client is accessing the server directly.
80 *
81 * @return string The IP address of the client.
82 */
83 private function get_ip_address(): string {
84 if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
85 return $_SERVER['HTTP_CLIENT_IP'];
86 }
87
88 if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
89 return $_SERVER['HTTP_X_FORWARDED_FOR'];
90 }
91
92 if (!empty($_SERVER['REMOTE_ADDR'])) {
93 return $_SERVER['REMOTE_ADDR'];
94 }
95
96 return 'UNKNOWN';
97 }
98
99 /**
100 * Add a help notice for 404 detection warning.
101 *
102 * @param array $notices The existing notices array.
103 *
104 * @return array Updated notices array with 404 detection warning notice.
105 */
106 public function show_help_notices(array $notices): array {
107 if (get_option($this->notice_option)) {
108 $message = __('We detected suspected bots triggering large numbers of 404 errors on your site.', 'really-simple-ssl');
109 $notice = [
110 'callback' => '_true_',
111 'score' => 1,
112 'show_with_options' => ['enable_404_detection'],
113 'output' => [
114 'true' => [
115 'msg' => $message,
116 'icon' => 'warning',
117 'type' => 'warning',
118 'dismissible' => true,
119 'admin_notice' => false,
120 'highlight_field_id' => 'enable_firewall',
121 'plusone' => true,
122 'url' => 'https://really-simple-ssl.com/suspected-bots-causing-404-errors/',
123 ]
124 ]
125 ];
126
127 $notices['404_detection_warning'] = $notice;
128 }
129 return $notices;
130 }
131
132 /**
133 * @param $field
134 * @param $value
135 * @param $old_value
136 * @param $option_name
137 *
138 * @return void
139 */
140 public function maybe_load_class_404_test() {
141 if ( ! get_option( 'rsssl_homepage_contains_404_resources' ) ) {
142 Rsssl_Test_404::get_instance();
143 }
144 }
145 }
146
147 new Rsssl_Simple_404_Interceptor();