| @@ -10,8 +10,9 @@ | ||
| 10 | 10 | use WP_Defender\Component; |
| 11 | 11 | use WP_Defender\Traits\Country; |
| 12 | 12 | use WP_Defender\Model\Lockout_Ip; |
| 13 | 13 | use WP_Defender\Model\Lockout_Log; |
| 14 | +use WP_Defender\Component\Known_Bots\Known_Bots_Factory; | |
| 14 | 15 | |
| 15 | 16 | /** |
| 16 | 17 | * Handles the detection of 404 errors and manages lockouts based on configured settings. |
| 17 | 18 | */ |
| @@ -55,12 +56,12 @@ | ||
| 55 | 56 | // Don't interfere with WP-CLI, Cron, AJAX and legit internal requests. |
| 56 | 57 | if ( defender_is_wp_cli() ) { |
| 57 | 58 | return; |
| 58 | 59 | } |
| 59 | - if ( defined( 'DOING_CRON' ) && DOING_CRON ) { | |
| 60 | + if ( wp_doing_cron() ) { | |
| 60 | 61 | return; |
| 61 | 62 | } |
| 62 | - if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { | |
| 63 | + if ( wp_doing_ajax() ) { | |
| 63 | 64 | return; |
| 64 | 65 | } |
| 65 | 66 | if ( false === $this->model->detect_logged && is_user_logged_in() ) { |
| 66 | 67 | return; |
| @@ -151,136 +152,17 @@ | ||
| 151 | 152 | add_action( 'template_redirect', array( $this, 'process_404_detect_multiple' ) ); |
| 152 | 153 | } |
| 153 | 154 | |
| 154 | 155 | /** |
| 155 | - * Check if user-agent is looks like from googlebot. | |
| 156 | - * | |
| 157 | - * @param string $user_agent The user agent string to check. | |
| 158 | - * | |
| 159 | - * @return bool | |
| 160 | - */ | |
| 161 | - private function is_google_ua( $user_agent = '' ): bool { | |
| 162 | - if ( empty( $user_agent ) ) { | |
| 163 | - $user_agent = defender_get_data_from_request( 'HTTP_USER_AGENT', 's' ); | |
| 164 | - if ( empty( $user_agent ) ) { | |
| 165 | - return false; | |
| 166 | - } | |
| 167 | - $user_agent = User_Agent::fast_cleaning( $user_agent ); | |
| 168 | - } | |
| 169 | - if ( function_exists( 'mb_strtolower' ) ) { | |
| 170 | - $user_agent = mb_strtolower( $user_agent, 'UTF-8' ); | |
| 171 | - } else { | |
| 172 | - $user_agent = strtolower( $user_agent ); | |
| 173 | - } | |
| 174 | - | |
| 175 | - if ( false !== stristr( $user_agent, 'googlebot' ) ) { | |
| 176 | - return true; | |
| 177 | - } | |
| 178 | - | |
| 179 | - return false; | |
| 180 | - } | |
| 181 | - | |
| 182 | - /** | |
| 183 | - * Check if IP is from Google, base on https://support.google.com/webmasters/answer/80553?hl=en. | |
| 184 | - * | |
| 185 | - * @param string $ip The IP address to check. | |
| 186 | - * | |
| 187 | - * @return bool | |
| 188 | - */ | |
| 189 | - private function is_google_ip( $ip ): bool { | |
| 190 | - $hostname = gethostbyaddr( $ip ); | |
| 191 | - // Check if this hostname has googlebot or google.com. | |
| 192 | - if ( preg_match( '/\.googlebot|google\.com$/i', $hostname ) ) { | |
| 193 | - $hosts = gethostbynamel( $hostname ); | |
| 194 | - | |
| 195 | - if ( ! is_array( $hosts ) ) { | |
| 196 | - return false; | |
| 197 | - } | |
| 198 | - | |
| 199 | - // Check if this match the original ip. | |
| 200 | - foreach ( $hosts as $host ) { | |
| 201 | - if ( $ip === $host ) { | |
| 202 | - return true; | |
| 203 | - } | |
| 204 | - } | |
| 205 | - } | |
| 206 | - | |
| 207 | - return false; | |
| 208 | - } | |
| 209 | - | |
| 210 | - /** | |
| 211 | - * Checks if the user agent belongs to Bing. | |
| 212 | - * | |
| 213 | - * @param string $user_agent The user agent string to check. | |
| 214 | - * | |
| 215 | - * @return bool Returns true if the user agent is identified as belonging to Bing, false otherwise. | |
| 216 | - */ | |
| 217 | - private function is_bing_ua( $user_agent = '' ): bool { | |
| 218 | - | |
| 219 | - if ( empty( $user_agent ) ) { | |
| 220 | - $user_agent = defender_get_data_from_request( 'HTTP_USER_AGENT', 's' ); | |
| 221 | - if ( empty( $user_agent ) ) { | |
| 222 | - return false; | |
| 223 | - } | |
| 224 | - $user_agent = User_Agent::fast_cleaning( $user_agent ); | |
| 225 | - } | |
| 226 | - | |
| 227 | - if ( function_exists( 'mb_strtolower' ) ) { | |
| 228 | - $user_agent = mb_strtolower( $user_agent, 'UTF-8' ); | |
| 229 | - } else { | |
| 230 | - $user_agent = strtolower( $user_agent ); | |
| 231 | - } | |
| 232 | - // MSN Bot Useragent https://www.bing.com/webmaster/help/which-crawlers-does-bing-use-8c184ec0. | |
| 233 | - $msn_ua = 'Bingbot|MSNBot|MSNBot-Media|AdIdxBot|BingPreview'; | |
| 234 | - | |
| 235 | - if ( preg_match( '/' . $msn_ua . '/i', $user_agent ) ) { | |
| 236 | - return true; | |
| 237 | - } | |
| 238 | - | |
| 239 | - return false; | |
| 240 | - } | |
| 241 | - | |
| 242 | - /** | |
| 243 | - * Check if IP is from Bing, base on https://www.bing.com/webmaster/help/how-to-verify-bingbot-3905dc26. | |
| 244 | - * | |
| 245 | - * @param string $ip The IP address to check. | |
| 246 | - * | |
| 247 | - * @return bool | |
| 248 | - */ | |
| 249 | - private function is_bing_ip( $ip ): bool { | |
| 250 | - $hostname = gethostbyaddr( $ip ); | |
| 251 | - if ( preg_match( '/\.msnbot|msn\.com$/i', $hostname ) ) { | |
| 252 | - $hosts = gethostbynamel( $hostname ); | |
| 253 | - | |
| 254 | - if ( ! is_array( $hosts ) ) { | |
| 255 | - return false; | |
| 256 | - } | |
| 257 | - | |
| 258 | - // Check if this match the original ip. | |
| 259 | - foreach ( $hosts as $host ) { | |
| 260 | - if ( $ip === $host ) { | |
| 261 | - return true; | |
| 262 | - } | |
| 263 | - } | |
| 264 | - } | |
| 265 | - | |
| 266 | - return false; | |
| 267 | - } | |
| 268 | - | |
| 269 | - /** | |
| 270 | 156 | * Processes 404 detection for a single IP address. |
| 271 | 157 | * |
| 272 | 158 | * @param string $ip The IP address to process. |
| 273 | 159 | */ |
| 274 | 160 | public function process_404_detect( string $ip ): void { |
| 275 | - // Check if this from Google. | |
| 276 | - if ( $this->is_google_ua() && $this->is_google_ip( $ip ) ) { | |
| 161 | + // Check if request is from a legitimate known bot (Google, Bing, Facebook). | |
| 162 | + if ( Known_Bots_Factory::create()->is_known_bot( $ip ) ) { | |
| 277 | 163 | return; |
| 278 | 164 | } |
| 279 | - // or bing. | |
| 280 | - if ( $this->is_bing_ua() && $this->is_bing_ip( $ip ) ) { | |
| 281 | - return; | |
| 282 | - } | |
| 283 | 165 | |
| 284 | 166 | $uri = defender_get_data_from_request( 'REQUEST_URI', 's' ); |
| 285 | 167 | // Strip encode. |
| 286 | 168 | $uri = urldecode( $uri ); |
| @@ -442,21 +324,9 @@ | ||
| 442 | 324 | * @param string $uri The URI that was accessed. |
| 443 | 325 | * @param string $scenario The scenario under which the event is logged. |
| 444 | 326 | */ |
| 445 | 327 | public function log_event( $ip, $uri, $scenario ) { |
| 446 | - $model = new Lockout_Log(); | |
| 447 | - $model->ip = $ip; | |
| 448 | - $user_agent = defender_get_data_from_request( 'HTTP_USER_AGENT', 's' ); | |
| 449 | - $model->user_agent = isset( $user_agent ) ? User_Agent::fast_cleaning( $user_agent ) : null; | |
| 450 | - $model->date = time(); | |
| 451 | - $model->tried = $uri; | |
| 452 | - $model->blog_id = get_current_blog_id(); | |
| 453 | - | |
| 454 | - $ip_to_country = $this->ip_to_country( $ip ); | |
| 455 | - | |
| 456 | - if ( isset( $ip_to_country['iso'] ) ) { | |
| 457 | - $model->country_iso_code = $ip_to_country['iso']; | |
| 458 | - } | |
| 328 | + $model = Lockout_Log::create( $ip, $uri ); | |
| 459 | 329 | |
| 460 | 330 | switch ( $scenario ) { |
| 461 | 331 | case self::SCENARIO_ERROR_404: |
| 462 | 332 | $model->type = Lockout_Log::ERROR_404; |