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 +16 -113 6.2.2 → 6.3.0 View file →
@@ -7,14 +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;
16 +use WP_Defender\Component\Known_Bots\Bots\Facebook_Bot;
15 17 use WP_Defender\Model\Notification\Firewall_Notification;
16 -use WP_Defender\Traits\Country;
17 18
18 19 /**
19 20 * Class Fake_Bot_Detection
20 21 *
@@ -78,13 +79,9 @@
78 79 * API endpoints to query for IP info.
79 80 *
80 81 * @var string[]
81 82 */
82 - public const IP_INFO_SERVICES = array(
83 - 'https://ipinfo.io/%s/json',
84 - 'https://ipwho.is/%s',
85 - 'http://ip-api.com/json/%s',
86 - );
83 + public const IP_INFO_SERVICES = Facebook_Bot::IP_INFO_SERVICES;
87 84
88 85 /**
89 86 * Prefix for site transient cache keys.
90 87 *
@@ -89,15 +86,15 @@
89 86 * Prefix for site transient cache keys.
90 87 *
91 88 * @var string
92 89 */
93 - public const FB_CACHE_KEY_PREFIX = 'wpdef_ip_is_fb_';
90 + public const FB_CACHE_KEY_PREFIX = Facebook_Bot::FB_CACHE_KEY_PREFIX;
94 91
95 92 /**
96 93 * Cache lifetimes.
97 94 */
98 - public const FB_CACHE_TTL_CONFIRMED = WEEK_IN_SECONDS;
99 - 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;
100 97
101 98 /**
102 99 * Fake_Bot_Detection constructor.
103 100 *
@@ -137,12 +134,8 @@
137 134 if ( array() === $ips || '' === $agent ) {
138 135 return;
139 136 }
140 137
141 - if ( false !== stripos( $agent, 'facebook' ) && false !== stripos( $agent, 'twitter' ) ) {
142 - return;
143 - }
144 -
145 138 foreach ( $this->crawlers as $name => $data ) {
146 139 // 1. User-Agent check.
147 140 if ( ! $this->match_user_agent( $agent, $data['user_agents'] ?? array() ) ) {
148 141 continue;
@@ -160,15 +153,10 @@
160 153 return;
161 154 }
162 155
163 156 // Facebook specific IP verification.
164 - if ( 'facebook' === strtolower( $name ) ) {
165 - if ( $this->is_facebook_ip( $ip ) ) {
166 - return; // Confirmed legit Facebook bot.
167 - }
168 -
169 - $this->block_ip( $ip, $agent, $name );
170 - return;
157 + if ( 'facebook' === strtolower( $name ) && $this->is_facebook_ip( $ip ) ) {
158 + return; // Confirmed legit Facebook bot.
171 159 }
172 160
173 161 // 3. Reverse DNS lookup.
174 162 $hostname = gethostbyaddr( $ip );
@@ -189,9 +177,11 @@
189 177 return; // Verified by forward + reverse DNS.
190 178 }
191 179 }
192 180
193 - $this->block_ip( $ip, $agent, $name );
181 + if ( isset( $ip ) ) {
182 + $this->block_ip( $ip, $agent, $name );
183 + }
194 184 return; // UA matched, but DNS validation failed.
195 185 }
196 186 }
197 187
@@ -300,22 +290,10 @@
300 290 * @param string $scenario The scenario under which the event is logged.
301 291 * @param string $bot_name The name of the bot being impersonated.
302 292 */
303 293 public function log_event( $ip, $scenario, $bot_name ) {
304 - $model = new Lockout_Log();
305 - $model->ip = $ip;
306 - $user_agent = defender_get_data_from_request( 'HTTP_USER_AGENT', 's' );
307 - $model->user_agent = isset( $user_agent ) ? User_Agent::fast_cleaning( $user_agent ) : null;
308 - $model->date = time();
309 - $model->tried = $user_agent;
310 - $model->blog_id = get_current_blog_id();
294 + $model = Lockout_Log::create( $ip );
311 295
312 - $ip_to_country = $this->ip_to_country( $ip );
313 -
314 - if ( isset( $ip_to_country['iso'] ) ) {
315 - $model->country_iso_code = $ip_to_country['iso'];
316 - }
317 -
318 296 switch ( $scenario ) {
319 297 case self::SCENARIO_FAKE_BOT:
320 298 default:
321 299 $model->type = Lockout_Log::LOCKOUT_FAKE_BOT;
@@ -350,63 +328,9 @@
350 328 * @param string $ip IPv4 or IPv6 address.
351 329 * @return bool True if owned by Facebook, false otherwise.
352 330 */
353 331 public function is_facebook_ip( string $ip ): bool {
354 - if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
355 - return false;
356 - }
357 -
358 - $cache_key = self::FB_CACHE_KEY_PREFIX . md5( $ip );
359 -
360 - $cached = get_site_transient( $cache_key );
361 - if ( false !== $cached ) {
362 - return (bool) $cached;
363 - }
364 -
365 - $is_fb = false;
366 -
367 - // Fetch from APIs.
368 - foreach ( self::IP_INFO_SERVICES as $endpoint ) {
369 - $url = sprintf( $endpoint, $ip );
370 -
371 - $response = wp_remote_get(
372 - $url,
373 - array(
374 - 'timeout' => 3,
375 - 'headers' => array( 'Accept' => 'application/json' ),
376 - )
377 - );
378 -
379 - if ( is_wp_error( $response ) ) {
380 - continue;
381 - }
382 -
383 - $body = wp_remote_retrieve_body( $response );
384 - $data = json_decode( $body, true );
385 -
386 - if ( ! is_array( $data ) ) {
387 - continue;
388 - }
389 -
390 - $org = $data['org'] ?? $data['connection']['org'] ?? null;
391 - $isp = $data['isp'] ?? $data['connection']['isp'] ?? null;
392 -
393 - if (
394 - preg_match( '/facebook|meta/i', $org ?? '' ) ||
395 - preg_match( '/facebook|meta/i', $isp ?? '' )
396 - ) {
397 - $is_fb = true;
398 - break;
399 - }
400 - }
401 -
402 - set_site_transient(
403 - $cache_key,
404 - $is_fb ? 1 : 0,
405 - $is_fb ? self::FB_CACHE_TTL_CONFIRMED : self::FB_CACHE_TTL_UNCONFIRMED
406 - );
407 -
408 - return $is_fb;
332 + return ( new Facebook_Bot() )->is_ip( $ip );
409 333 }
410 334
411 335 /**
412 336 * Clear all Facebook IP check transients.
@@ -411,28 +335,7 @@
411 335 /**
412 336 * Clear all Facebook IP check transients.
413 337 */
414 338 public function clear_fb_transients(): void {
415 - global $wpdb;
416 -
417 - $cache_key = self::FB_CACHE_KEY_PREFIX;
418 - $like_pattern = "_site_transient_{$cache_key}_%";
419 - $timeout_pattern = "_site_transient_timeout_{$cache_key}_%";
420 -
421 - if ( is_multisite() ) {
422 - $table = $wpdb->sitemeta;
423 - $key_column = 'meta_key';
424 - } else {
425 - $table = $wpdb->options;
426 - $key_column = 'option_name';
427 - }
428 -
429 - // Delete Facebook IP check transients.
430 - $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
431 - $wpdb->prepare(
432 - "DELETE FROM {$table} WHERE {$key_column} LIKE %s OR {$key_column} LIKE %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
433 - $like_pattern,
434 - $timeout_pattern
435 - )
436 - );
339 + ( new Facebook_Bot() )->clear_fb_transients();
437 340 }
438 341 }