PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
← All changes | src/component/class-fake-bot-detection.php +19 -109 5.7.1 → 6.3.0 View file →
@@ -7,13 +7,15 @@
7 7
8 8 namespace WP_Defender\Component;
9 9
10 10 use WP_Defender\Component;
11 +use WP_Defender\Traits\Country;
12 +use WP_Defender\Model\Lockout_Ip;
13 +use WP_Defender\Model\Lockout_Log;
11 14 use WP_Defender\Controller\Firewall;
12 -use WP_Defender\Model\Lockout_Log;
13 15 use WP_Defender\Model\Setting\User_Agent_Lockout;
14 -use WP_Defender\Model\Lockout_Ip;
15 -use WP_Defender\Traits\Country;
16 +use WP_Defender\Component\Known_Bots\Bots\Facebook_Bot;
17 +use WP_Defender\Model\Notification\Firewall_Notification;
16 18
17 19 /**
18 20 * Class Fake_Bot_Detection
19 21 *
@@ -77,13 +79,9 @@
77 79 * API endpoints to query for IP info.
78 80 *
79 81 * @var string[]
80 82 */
81 - public const IP_INFO_SERVICES = array(
82 - 'https://ipinfo.io/%s/json',
83 - 'https://ipwho.is/%s',
84 - 'http://ip-api.com/json/%s',
85 - );
83 + public const IP_INFO_SERVICES = Facebook_Bot::IP_INFO_SERVICES;
86 84
87 85 /**
88 86 * Prefix for site transient cache keys.
89 87 *
@@ -88,15 +86,15 @@
88 86 * Prefix for site transient cache keys.
89 87 *
90 88 * @var string
91 89 */
92 - public const FB_CACHE_KEY_PREFIX = 'wpdef_ip_is_fb_';
90 + public const FB_CACHE_KEY_PREFIX = Facebook_Bot::FB_CACHE_KEY_PREFIX;
93 91
94 92 /**
95 93 * Cache lifetimes.
96 94 */
97 - public const FB_CACHE_TTL_CONFIRMED = WEEK_IN_SECONDS;
98 - public const FB_CACHE_TTL_UNCONFIRMED = HOUR_IN_SECONDS;
95 + public const FB_CACHE_TTL_CONFIRMED = Facebook_Bot::FB_CACHE_TTL_CONFIRMED;
96 + public const FB_CACHE_TTL_UNCONFIRMED = Facebook_Bot::FB_CACHE_TTL_UNCONFIRMED;
99 97
100 98 /**
101 99 * Fake_Bot_Detection constructor.
102 100 *
@@ -155,15 +153,10 @@
155 153 return;
156 154 }
157 155
158 156 // Facebook specific IP verification.
159 - if ( 'facebook' === strtolower( $name ) ) {
160 - if ( $this->is_facebook_ip( $ip ) ) {
161 - return; // Confirmed legit Facebook bot.
162 - }
163 -
164 - $this->block_ip( $ip, $agent, $name );
165 - return;
157 + if ( 'facebook' === strtolower( $name ) && $this->is_facebook_ip( $ip ) ) {
158 + return; // Confirmed legit Facebook bot.
166 159 }
167 160
168 161 // 3. Reverse DNS lookup.
169 162 $hostname = gethostbyaddr( $ip );
@@ -184,9 +177,11 @@
184 177 return; // Verified by forward + reverse DNS.
185 178 }
186 179 }
187 180
188 - $this->block_ip( $ip, $agent, $name );
181 + if ( isset( $ip ) ) {
182 + $this->block_ip( $ip, $agent, $name );
183 + }
189 184 return; // UA matched, but DNS validation failed.
190 185 }
191 186 }
192 187
@@ -295,22 +290,10 @@
295 290 * @param string $scenario The scenario under which the event is logged.
296 291 * @param string $bot_name The name of the bot being impersonated.
297 292 */
298 293 public function log_event( $ip, $scenario, $bot_name ) {
299 - $model = new Lockout_Log();
300 - $model->ip = $ip;
301 - $user_agent = defender_get_data_from_request( 'HTTP_USER_AGENT', 's' );
302 - $model->user_agent = isset( $user_agent ) ? User_Agent::fast_cleaning( $user_agent ) : null;
303 - $model->date = time();
304 - $model->tried = $user_agent;
305 - $model->blog_id = get_current_blog_id();
294 + $model = Lockout_Log::create( $ip );
306 295
307 - $ip_to_country = $this->ip_to_country( $ip );
308 -
309 - if ( ! empty( $ip_to_country ) && isset( $ip_to_country['iso'] ) ) {
310 - $model->country_iso_code = $ip_to_country['iso'];
311 - }
312 -
313 296 switch ( $scenario ) {
314 297 case self::SCENARIO_FAKE_BOT:
315 298 default:
316 299 $model->type = Lockout_Log::LOCKOUT_FAKE_BOT;
@@ -321,8 +304,10 @@
321 304 );
322 305 break;
323 306 }
324 307 $model->save();
308 + // Notify directly because the 'defender_notify' hook isn't registered yet at firewall-time.
309 + wd_di()->get( Firewall_Notification::class )->notify_lockout( $model );
325 310 }
326 311
327 312 /**
328 313 * Creates a lockout for a blocked IP.
@@ -343,63 +328,9 @@
343 328 * @param string $ip IPv4 or IPv6 address.
344 329 * @return bool True if owned by Facebook, false otherwise.
345 330 */
346 331 public function is_facebook_ip( string $ip ): bool {
347 - if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
348 - return false;
349 - }
350 -
351 - $cache_key = self::FB_CACHE_KEY_PREFIX . md5( $ip );
352 -
353 - $cached = get_site_transient( $cache_key );
354 - if ( false !== $cached ) {
355 - return (bool) $cached;
356 - }
357 -
358 - $is_fb = false;
359 -
360 - // Fetch from APIs.
361 - foreach ( self::IP_INFO_SERVICES as $endpoint ) {
362 - $url = sprintf( $endpoint, $ip );
363 -
364 - $response = wp_remote_get(
365 - $url,
366 - array(
367 - 'timeout' => 3,
368 - 'headers' => array( 'Accept' => 'application/json' ),
369 - )
370 - );
371 -
372 - if ( is_wp_error( $response ) ) {
373 - continue;
374 - }
375 -
376 - $body = wp_remote_retrieve_body( $response );
377 - $data = json_decode( $body, true );
378 -
379 - if ( ! is_array( $data ) ) {
380 - continue;
381 - }
382 -
383 - $org = $data['org'] ?? $data['connection']['org'] ?? null;
384 - $isp = $data['isp'] ?? $data['connection']['isp'] ?? null;
385 -
386 - if (
387 - preg_match( '/facebook|meta/i', $org ?? '' ) ||
388 - preg_match( '/facebook|meta/i', $isp ?? '' )
389 - ) {
390 - $is_fb = true;
391 - break;
392 - }
393 - }
394 -
395 - set_site_transient(
396 - $cache_key,
397 - $is_fb ? 1 : 0,
398 - $is_fb ? self::FB_CACHE_TTL_CONFIRMED : self::FB_CACHE_TTL_UNCONFIRMED
399 - );
400 -
401 - return $is_fb;
332 + return ( new Facebook_Bot() )->is_ip( $ip );
402 333 }
403 334
404 335 /**
405 336 * Clear all Facebook IP check transients.
@@ -404,28 +335,7 @@
404 335 /**
405 336 * Clear all Facebook IP check transients.
406 337 */
407 338 public function clear_fb_transients(): void {
408 - global $wpdb;
409 -
410 - $cache_key = self::FB_CACHE_KEY_PREFIX;
411 - $like_pattern = "_site_transient_{$cache_key}_%";
412 - $timeout_pattern = "_site_transient_timeout_{$cache_key}_%";
413 -
414 - if ( is_multisite() ) {
415 - $table = $wpdb->sitemeta;
416 - $key_column = 'meta_key';
417 - } else {
418 - $table = $wpdb->options;
419 - $key_column = 'option_name';
420 - }
421 -
422 - // Delete Facebook IP check transients.
423 - $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
424 - $wpdb->prepare(
425 - "DELETE FROM {$table} WHERE {$key_column} LIKE %s OR {$key_column} LIKE %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
426 - $like_pattern,
427 - $timeout_pattern
428 - )
429 - );
339 + ( new Facebook_Bot() )->clear_fb_transients();
430 340 }
431 341 }