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-blacklist-lockout.php +90 -44 5.7.2 → 6.3.0 View file →
@@ -13,9 +13,9 @@
13 13 use Calotes\Helper\Array_Cache;
14 14 use WP_Defender\Traits\Country;
15 15 use WP_Defender\Traits\Continent;
16 16 use WP_Defender\Model\Lockout_Log;
17 -use MaxMind\Db\Reader\InvalidDatabaseException;
17 +use WP_DEFENDER_VENDOR\MaxMind\Db\Reader\InvalidDatabaseException;
18 18 use WP_Defender\Integrations\MaxMind_Geolocation;
19 19 use WP_Defender\Model\Setting\Blacklist_Lockout as Model_Blacklist_Lockout;
20 20 use WP_Defender\Integrations\Main_Wp;
21 21 use WP_Filesystem_Base;
@@ -75,26 +75,18 @@
75 75 return false;
76 76 }
77 77 $model = new Model_Blacklist_Lockout();
78 78 $whitelist = $model->get_country_whitelist();
79 - if ( empty( $whitelist ) ) {
79 + if ( array() === $whitelist ) {
80 80 return false;
81 81 }
82 82
83 - if ( ! empty( $country['iso'] ) ) {
83 + if ( isset( $country['iso'] ) && '' !== $country['iso'] ) {
84 84 $country_iso = strtoupper( $country['iso'] );
85 85
86 - // Check if the specific country is in the whitelist.
87 - if ( in_array( $country_iso, $whitelist, true ) ) {
86 + if ( $this->is_country_iso_in_list( $country_iso, $whitelist ) ) {
88 87 return true;
89 88 }
90 -
91 - // Check if any continent containing this country is in the whitelist.
92 - foreach ( $whitelist as $allowed_code ) {
93 - if ( $this->is_country_in_continent( $country_iso, $allowed_code ) ) {
94 - return true;
95 - }
96 - }
97 89 }
98 90
99 91 return false;
100 92 }
@@ -107,14 +99,15 @@
107 99 private function get_default_ip_whitelisted(): array {
108 100 $server_addr = defender_get_data_from_request( 'SERVER_ADDR', 's' );
109 101 $remote_addr = defender_get_data_from_request( 'REMOTE_ADDR', 's' );
110 102 $ips = array(
111 - ...$this->fetch_latest_ips(),
103 + ...self::fetch_latest_ips(),
112 104 '127.0.0.1',
113 - isset( $server_addr ) ? $server_addr : $remote_addr,
105 + $server_addr ?? $remote_addr,
114 106 );
115 107
116 - return (array) apply_filters( 'ip_lockout_default_whitelist_ip', $ips );
108 + $whitelist_ips = apply_filters( 'ip_lockout_default_whitelist_ip', $ips );
109 + return is_array( $whitelist_ips ) ? $whitelist_ips : (array) $whitelist_ips;
117 110 }
118 111
119 112 /**
120 113 * Fetch the latest IP list from the API.
@@ -123,9 +116,9 @@
123 116 */
124 117 public static function fetch_latest_ips(): array {
125 118 // Attempt to retrieve IPs from the cache.
126 119 $cached_ips = get_site_transient( self::IP_LIST_KEY );
127 - if ( $cached_ips && is_array( $cached_ips ) ) {
120 + if ( is_array( $cached_ips ) && array() !== $cached_ips ) {
128 121 return $cached_ips;
129 122 }
130 123
131 124 // Fetch the IP list from the remote API.
@@ -142,17 +135,25 @@
142 135 }
143 136
144 137 // Retrieve the response body.
145 138 $body = wp_remote_retrieve_body( $response );
146 - if ( empty( $body ) ) {
139 + if ( '' === $body ) {
147 140 return array();
148 141 }
149 142
150 143 // Process the response body into an array of IPs.
151 - $ip_list = array_filter( array_map( 'sanitize_text_field', explode( "\n", $body ) ) );
144 + $ip_list = array_filter(
145 + array_map(
146 + 'sanitize_text_field',
147 + explode( "\n", $body )
148 + ),
149 + function ( $value ) {
150 + return '' !== trim( $value );
151 + }
152 + );
152 153
153 154 // Cache the IP list for a week if it is not empty.
154 - if ( ! empty( $ip_list ) ) {
155 + if ( array() !== $ip_list ) {
155 156 set_site_transient( self::IP_LIST_KEY, $ip_list, WEEK_IN_SECONDS );
156 157 }
157 158
158 159 // Return the fetched IP list.
@@ -172,15 +173,15 @@
172 173 }
173 174
174 175 // If the IP is the server public IP.
175 176 $server_public_ip = wd_di()->get( Firewall::class )->get_whitelist_server_public_ip();
176 - if ( ! empty( $server_public_ip ) && $server_public_ip === $ip ) {
177 + if ( '' !== $server_public_ip && $server_public_ip === $ip ) {
177 178 return true;
178 179 }
179 180
180 181 // If the IP is the MainWP Dashboard public IP.
181 182 $mainwp_dashboard_public_ip = wd_di()->get( Main_Wp::class )->get_whitelist_dashboard_public_ip();
182 - if ( ! empty( $mainwp_dashboard_public_ip ) && in_array( $ip, $mainwp_dashboard_public_ip, true ) ) {
183 + if ( array() !== $mainwp_dashboard_public_ip && in_array( $ip, $mainwp_dashboard_public_ip, true ) ) {
183 184 return true;
184 185 }
185 186
186 187 $blacklist_settings = new Model_Blacklist_Lockout();
@@ -216,9 +217,9 @@
216 217 return false;
217 218 }
218 219 $blacklist_settings = new Model_Blacklist_Lockout();
219 220 $blacklisted = $blacklist_settings->get_country_blacklist();
220 - if ( empty( $blacklisted ) ) {
221 + if ( array() === $blacklisted ) {
221 222 return false;
222 223 }
223 224 if ( in_array( 'all', $blacklisted, true ) ) {
224 225 return true;
@@ -223,22 +224,14 @@
223 224 if ( in_array( 'all', $blacklisted, true ) ) {
224 225 return true;
225 226 }
226 227
227 - if ( ! empty( $country['iso'] ) ) {
228 + if ( isset( $country['iso'] ) && '' !== $country['iso'] ) {
228 229 $country_iso = strtoupper( $country['iso'] );
229 230
230 - // Check if the specific country is in the blacklist.
231 - if ( in_array( $country_iso, $blacklisted, true ) ) {
231 + if ( $this->is_country_iso_in_list( $country_iso, $blacklisted ) ) {
232 232 return true;
233 233 }
234 -
235 - // Check if any continent containing this country is in the blacklist.
236 - foreach ( $blacklisted as $blocked_code ) {
237 - if ( $this->is_country_in_continent( $country_iso, $blocked_code ) ) {
238 - return true;
239 - }
240 - }
241 234 }
242 235
243 236 return false;
244 237 }
@@ -284,9 +277,9 @@
284 277 * @return Model_Blacklist_Lockout The updated model.
285 278 * @since 2.8.0
286 279 */
287 280 public function add_default_whitelisted_country( Model_Blacklist_Lockout $model, $country_iso ) {
288 - if ( empty( $model->country_whitelist ) ) {
281 + if ( array() === $model->country_whitelist ) {
289 282 $model->country_whitelist[] = $country_iso;
290 283 } elseif ( ! in_array( $country_iso, $model->country_whitelist, true ) ) {
291 284 $model->country_whitelist[] = $country_iso;
292 285 }
@@ -303,9 +296,9 @@
303 296 public function is_geodb_downloaded(): bool {
304 297 $model = new Model_Blacklist_Lockout();
305 298 $license_key = $model->maxmind_license_key;
306 299 // Using Geo DB without a license key is not advisable.
307 - if ( empty( $license_key ) && is_file( $model->geodb_path ) ) {
300 + if ( '' === $license_key && is_string( $model->geodb_path ) && is_file( $model->geodb_path ) ) {
308 301 $service_geo = wd_di()->get( MaxMind_Geolocation::class );
309 302 $service_geo->delete_database();
310 303 $model->geodb_path = '';
311 304 $model->save();
@@ -314,10 +307,10 @@
314 307 }
315 308
316 309 // Likely the case after the config import with the existed MaxMind license key.
317 310 if (
318 - ! empty( $license_key )
319 - && ( is_null( $model->geodb_path ) || ! is_file( $model->geodb_path ) )
311 + '' !== $license_key
312 + && ( ! is_string( $model->geodb_path ) || ! is_file( $model->geodb_path ) )
320 313 ) {
321 314 $service_geo = wd_di()->get( MaxMind_Geolocation::class );
322 315 $tmp = $service_geo->get_downloaded_url( $license_key );
323 316 if ( ! is_wp_error( $tmp ) ) {
@@ -334,14 +327,14 @@
334 327 if ( file_exists( $tmp ) ) {
335 328 wp_delete_file( $tmp );
336 329 }
337 330
338 - if ( empty( $model->country_whitelist ) ) {
331 + if ( array() === $model->country_whitelist ) {
339 332 $is_country = false;
340 333 foreach ( $this->get_user_ip() as $ip ) {
341 334 $country = $this->get_current_country( $ip );
342 335
343 - if ( ! empty( $country['iso'] ) ) {
336 + if ( isset( $country['iso'] ) && '' !== $country['iso'] ) {
344 337 $model = $this->add_default_whitelisted_country( $model, $country['iso'] );
345 338 $is_country = true;
346 339 }
347 340 }
@@ -354,9 +347,9 @@
354 347 }
355 348 }
356 349
357 350 // Check again.
358 - if ( is_null( $model->geodb_path ) || ! is_file( $model->geodb_path ) ) {
351 + if ( ! is_string( $model->geodb_path ) || ! is_file( $model->geodb_path ) ) {
359 352 return false;
360 353 }
361 354
362 355 // Check if the file exists on the site. The file can exist on the same server but for different sites.
@@ -372,9 +365,9 @@
372 365
373 366 $rel_path = $abs_path . DIRECTORY_SEPARATOR . $path_parts['basename'];
374 367 if ( file_exists( $rel_path ) ) {
375 368 return true;
376 - } elseif ( ! empty( $model->geodb_path ) && file_exists( $model->geodb_path ) ) {
369 + } elseif ( '' !== $model->geodb_path && file_exists( $model->geodb_path ) ) {
377 370 // The case if ABSPATH was changed e.g. in wp-config.php.
378 371 return true;
379 372 }
380 373
@@ -423,9 +416,9 @@
423 416 return false;
424 417 }
425 418
426 419 global $wp_filesystem;
427 - if ( empty( $wp_filesystem ) ) {
420 + if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
428 421 require_once ABSPATH . 'wp-admin/includes/file.php';
429 422 WP_Filesystem();
430 423 }
431 424
@@ -452,9 +445,9 @@
452 445 * @return array List of countries and their blocked IP count.
453 446 */
454 447 public function get_top_countries_blocked( $limit = 10, $max_age_days = 7 ) {
455 448 $result = Array_Cache::get( 'countries', 'ip_lockout', array() );
456 - if ( empty( $result ) ) {
449 + if ( array() === $result ) {
457 450 global $wpdb;
458 451
459 452 $result = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
460 453 $wpdb->prepare(
@@ -461,8 +454,9 @@
461 454 "SELECT country_iso_code, COUNT(ip) AS ip_count FROM {$wpdb->base_prefix}defender_lockout_log WHERE (type = %s OR type = %s OR type = %s) AND date >= %d AND country_iso_code IS NOT NULL GROUP BY country_iso_code ORDER BY ip_count DESC LIMIT %d",
462 455 Lockout_Log::LOCKOUT_404,
463 456 Lockout_Log::AUTH_LOCK,
464 457 Lockout_Log::LOCKOUT_UA,
458 + // todo: add other 404- and UA-lockouts.
465 459 strtotime( '-' . $max_age_days . ' days', time() ),
466 460 $limit
467 461 ),
468 462 ARRAY_A
@@ -470,9 +464,9 @@
470 464 // Get data from cache.
471 465 Array_Cache::set( 'countries', $result, 'ip_lockout' );
472 466 }
473 467
474 - return ! empty( $result ) ? $result : array();
468 + return array() !== $result ? $result : array();
475 469 }
476 470
477 471 /**
478 472 * Is IP on BLC Whitelist?
@@ -488,9 +482,9 @@
488 482 '144.202.86.106',
489 483 );
490 484 $diff = array_diff( $ips, $blc_ips );
491 485
492 - return empty( $diff );
486 + return array() === $diff;
493 487 }
494 488
495 489 /**
496 490 * Checks if a list of IPs are all whitelisted.
@@ -507,6 +501,58 @@
507 501 }
508 502 }
509 503
510 504 return true;
505 + }
506 +
507 + /**
508 + * Check whether a code identifies a continent without also identifying a country.
509 + *
510 + * @param string $code The code to check.
511 + * @return bool True when the code identifies only a continent.
512 + */
513 + private function is_continent_code( $code ): bool {
514 + $countries_with_continents = $this->get_countries_with_continents();
515 +
516 + if ( ! isset( $countries_with_continents[ $code ] ) ) {
517 + return false;
518 + }
519 +
520 + foreach ( $countries_with_continents as $continent ) {
521 + if ( ! isset( $continent['area'] ) ) {
522 + continue;
523 + }
524 +
525 + foreach ( $continent['area'] as $area ) {
526 + if ( isset( $area['countries'][ $code ] ) ) {
527 + return false;
528 + }
529 + }
530 + }
531 +
532 + return true;
533 + }
534 +
535 + /**
536 + * Checks whether a country ISO code (or any continent it belongs to) is present in the given list.
537 + *
538 + * @param string $country_iso The upcased two-letter ISO country code.
539 + * @param array $iso_list The list of country/continent codes to check against.
540 + *
541 + * @return bool True if the country or one of its continents is found in the list.
542 + */
543 + private function is_country_iso_in_list( string $country_iso, array $iso_list ): bool {
544 + // Check if the specific country is in the list.
545 + if ( in_array( $country_iso, $iso_list, true ) ) {
546 + return true;
547 + }
548 +
549 + // Check if any continent containing this country is in the list.
550 + foreach ( $iso_list as $code ) {
551 + if ( $this->is_continent_code( $code ) && $this->is_country_in_continent( $country_iso, $code ) ) {
552 + return true;
553 + }
554 + }
555 +
556 + return false;
511 557 }
512 558 }