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/controller/class-antibot-global-firewall.php +109 -114 5.7.2 → 6.3.0 View file →
@@ -71,8 +71,10 @@
71 71 $this->model = $model;
72 72 $this->service = $service;
73 73 $this->wpmudev = $wpmudev;
74 74
75 + add_action( 'admin_init', array( $this, 'maybe_hcm_connection_attempt' ), 20 );
76 + add_action( 'wpdef_hub_connector_synced', array( $this, 'maybe_hcm_connection_attempt' ) );
75 77 add_action( 'wpmudev_hub_connector_first_sync_completed', array( $this, 'maybe_hcm_connection_attempt' ) );
76 78
77 79 /**
78 80 * Download and store Blocklist from the API.
@@ -97,9 +99,8 @@
97 99 if ( $this->wpmudev->is_wpmu_hosting() ) {
98 100 add_action( 'init', array( $this, 'sync_state' ) );
99 101 }
100 102 add_action( 'init', array( $this, 'handle_expired_membership' ) );
101 - add_action( 'init', array( $this->service, 'maybe_set_notice_time' ) );
102 103 }
103 104
104 105 /**
105 106 * Handle request to save settings.
@@ -126,14 +127,14 @@
126 127 'redirect_to_feature_page' => array( 'type' => 'bool' ),
127 128 // End.
128 129 )
129 130 );
130 - $old_enabled = (bool) $this->model->enabled;
131 + $old_enabled = $this->model->enabled;
131 132
132 133 $location = 'Feature Page';
133 134 // Split module's titles and locations.
134 135 if ( isset( $data['module_title'] ) && 'antibot' === $data['module_title'] ) {
135 - if ( empty( $data['module_location'] ) ) {
136 + if ( ! isset( $data['module_location'] ) || '' === $data['module_location'] ) {
136 137 $location = 'Dashboard';
137 138 } else {
138 139 $location = $data['module_location'];
139 140 unset( $data['module_location'] );
@@ -165,13 +166,8 @@
165 166 }
166 167 }
167 168
168 169 Config_Hub_Helper::set_clear_active_flag();
169 -
170 - // Hide the Antibot notice on the Dashboard page.
171 - if ( ! empty( $data['enabled'] ) ) {
172 - delete_site_option( Antibot_Global_Firewall_Component::NOTICE_SLUG );
173 - }
174 170 // Maybe track.
175 171 if ( ! defender_is_wp_cli() && $old_enabled !== $data['enabled'] ) {
176 172 wd_di()->get( Antibot_Analytics::class )->track_antibot( $old_enabled, $location );
177 173 }
@@ -179,9 +175,9 @@
179 175 $update_message = $this->get_update_message( $data, $old_enabled, Antibot_Global_Firewall_Setting::get_module_name() );
180 176 $referrer = wp_get_referer();
181 177 if ( $referrer && strpos( $referrer, 'page=wp-defender' ) !== false ) {
182 178 $update_message = sprintf(
183 - /* translators: 1: Bold open tag, 2: Bold close tag */
179 + /* translators: 1: Module name. */
184 180 __( '%s is now enabled.', 'defender-security' ),
185 181 '<strong>' . Antibot_Global_Firewall_Setting::get_module_name() . '</strong>'
186 182 );
187 183 }
@@ -210,27 +206,15 @@
210 206 );
211 207 }
212 208
213 209 /**
214 - * Hide the Antibot notice.
215 - *
216 - * @return Response
217 - * @defender_route
218 - */
219 - public function hide_antibot_notice(): Response {
220 - delete_site_option( Antibot_Global_Firewall_Component::NOTICE_SLUG );
221 -
222 - return new Response( true, array() );
223 - }
224 -
225 - /**
226 210 * Queue assets and require data.
227 211 *
228 212 * @return void
229 213 */
230 214 public function enqueue_assets() {
231 - if ( $this->is_page_active() ) {
232 - wp_localize_script( 'def-iplockout', 'antibot', $this->data_frontend() );
215 + if ( ! $this->is_page_active() ) {
216 + return;
233 217 }
234 218 }
235 219
236 220 /**
@@ -238,22 +222,8 @@
238 222 *
239 223 * @return array
240 224 */
241 225 public function data_frontend(): array {
242 - /**
243 - * Show the onboarding reminder notice if:
244 - * 1. If the reminder time is set and the time difference is greater than a week.
245 - * 2. No click on the Cross icon before.
246 - */
247 - $is_reminder = false;
248 - $last_reminder = get_site_option( Onboard::REMINDER_KEY, 0 );
249 - if ( ! empty( $last_reminder ) ) {
250 - $time_diff = time() - $last_reminder;
251 - if ( $time_diff > WEEK_IN_SECONDS ) {
252 - $is_reminder = true;
253 - }
254 - }
255 -
256 226 $model_export = $this->model->export();
257 227 $model_export['managed_by'] = $this->service->get_managed_by();
258 228 $module_name = Antibot_Global_Firewall_Setting::get_module_name();
259 229
@@ -260,31 +230,30 @@
260 230 return array_merge(
261 231 array(
262 232 'model' => $model_export,
263 233 'misc' => array(
264 - 'module_slug' => Antibot_Global_Firewall_Setting::get_module_slug(),
265 - 'module_name' => $module_name,
266 - 'show_notice' => $is_reminder
267 - && (bool) get_site_option( Antibot_Global_Firewall_Component::NOTICE_SLUG, false ),
268 - 'sync_schedule' => __( 'Twice Daily', 'defender-security' ),
269 - 'ips_count' => $this->service->get_blocklisted_ip_count(),
270 - 'frontend_is_enabled' => $this->service->frontend_is_enabled(),
271 - 'frontend_mode' => $this->service->frontend_mode(),
272 - 'is_active' => $this->service->is_active(),
273 - 'show_stats_button' => ! $this->wpmudev->is_whitelabel_enabled(),
274 - 'show_checker' => ! $this->wpmudev->is_wpmu_hosting()
234 + 'module_slug' => Antibot_Global_Firewall_Setting::get_module_slug(),
235 + 'module_name' => $module_name,
236 + 'show_notice' => false,
237 + 'sync_schedule' => __( 'Twice Daily', 'defender-security' ),
238 + 'ips_count' => $this->service->get_blocklisted_ip_count(),
239 + 'blocklist_stats_full' => $this->service->get_cached_blocklist_stats_data(),
240 + 'frontend_is_enabled' => $this->service->frontend_is_enabled(),
241 + 'frontend_mode' => $this->service->frontend_mode(),
242 + 'is_active' => $this->service->is_active(),
243 + 'show_stats_button' => ! $this->wpmudev->is_whitelabel_enabled(),
244 + 'show_checker' => ! $this->wpmudev->is_wpmu_hosting()
275 245 || $this->wpmudev->is_wpmu_dev_admin()
276 246 || ! ( $this->service->is_active_via_hosting() && $this->wpmudev->is_whitelabel_enabled() ),
277 - 'active_tooltip_text' => __( 'List of exploit attempts detected and blocked across all connected sites by AntiBot Firewall.', 'defender-security' ),
278 - 'inactive_tooltip_text' => sprintf(
247 + 'active_tooltip_text' => __( 'List of exploit attempts detected and blocked across all connected sites by AntiBot Firewall.', 'defender-security' ),
248 + 'inactive_tooltip_text' => sprintf(
279 249 /* translators: %s: Module name. */
280 250 __( '%s is Inactive.', 'defender-security' ),
281 251 $module_name
282 252 ),
283 - 'current_user' => esc_html( wp_get_current_user()->display_name ?? __( 'User', 'defender-security' ) ),
284 - 'current_plan' => $this->get_membership_type(),
285 - 'is_expired_membership' => $this->is_expired_membership_type(),
286 - 'should_show_global_notice' => $this->service->should_show_global_notice(),
253 + 'current_user' => esc_html( wp_get_current_user()->display_name ?? __( 'User', 'defender-security' ) ),
254 + 'is_expired_membership' => $this->is_expired_membership_type(),
255 + 'show_antibot_options' => $this->service->get_states_of_antibot_options_for_different_hosting_types(),
287 256 ),
288 257 ),
289 258 $this->dump_routes_and_nonces()
290 259 );
@@ -296,15 +265,15 @@
296 265 * @return void
297 266 */
298 267 public function handle_download_and_store_blocklist(): void {
299 268 if ( is_multisite() ) {
300 - $next_run = get_site_option( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_NEXT_RUN_OPTION, 0 );
301 - if ( ! empty( $next_run ) && $next_run > time() ) {
269 + $next_run = (int) get_site_option( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_NEXT_RUN_OPTION, 0 );
270 + if ( $next_run > 0 && $next_run > time() ) {
302 271 return;
303 272 }
304 273
305 - $interval = wd_di()->get( Scheduler::class )->get_cron_schedule_interval( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_SCHEDULE );
306 - $next_run = time() + ( ! empty( $interval ) ? $interval : 12 * HOUR_IN_SECONDS );
274 + $interval = (int) wd_di()->get( Scheduler::class )->get_cron_schedule_interval( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_SCHEDULE );
275 + $next_run = time() + ( $interval > 0 ? $interval : 12 * HOUR_IN_SECONDS );
307 276 update_site_option( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_NEXT_RUN_OPTION, $next_run );
308 277 }
309 278
310 279 if ( true === $this->service->is_active_via_plugin() ) {
@@ -329,9 +298,9 @@
329 298 public function maybe_hcm_connection_attempt() {
330 299 $data = get_site_transient( Hub_Connector::TRANSIENT_KEY );
331 300 $module_slug = $data['module_slug'] ?? '';
332 301
333 - if ( Antibot_Global_Firewall_Setting::get_module_slug() === $module_slug && self::get_status() ) {
302 + if ( Antibot_Global_Firewall_Setting::get_module_slug() === $module_slug && self::get_hcm_status() ) {
334 303 delete_site_transient( Hub_Connector::TRANSIENT_KEY );
335 304
336 305 if ( 'plugin' === $this->service->get_managed_by() ) {
337 306 $this->service->managed_by_plugin_action();
@@ -342,10 +311,14 @@
342 311 }
343 312
344 313 /**
345 314 * Export the data of this module, we will use this for export to HUB, create a preset etc.
315 + *
316 + * @return array
346 317 */
347 - public function to_array() {}
318 + public function to_array(): array {
319 + return array();
320 + }
348 321
349 322 /**
350 323 * Import the data from the HUB, or from the preset.
351 324 *
@@ -373,13 +346,16 @@
373 346 */
374 347 public function remove_data() {
375 348 $this->service->delete_blocklist();
376 349
350 + delete_site_option( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_NEXT_RUN_OPTION );
351 + // Don't display Antibot global notice. We can delete slugs about this notice in the future.
377 352 delete_site_option( Antibot_Global_Firewall_Component::NOTICE_SLUG );
378 - delete_site_option( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_NEXT_RUN_OPTION );
379 353 delete_site_option( Antibot_Global_Firewall_Component::GLOBAL_NOTICE_TIME_OPTION );
354 + // Blocklist stats data.
380 355 delete_site_transient( Antibot_Global_Firewall_Component::BLOCKLIST_STATS_KEY . '_' . Antibot_Global_Firewall_Setting::MODE_BASIC );
381 356 delete_site_transient( Antibot_Global_Firewall_Component::BLOCKLIST_STATS_KEY . '_' . Antibot_Global_Firewall_Setting::MODE_STRICT );
357 + delete_site_transient( Antibot_Global_Firewall_Component::BLOCKLIST_STATS_FULL_KEY );
382 358 delete_site_transient( Antibot_Global_Firewall_Component::IS_SWITCHING_TO_PLUGIN_IN_PROGRESS );
383 359 }
384 360
385 361 /**
@@ -391,19 +367,8 @@
391 367 return array();
392 368 }
393 369
394 370 /**
395 - * Disconnect site from HUB.
396 - *
397 - * @defender_route
398 - * @return Response
399 - */
400 - public function disconnect_site(): Response {
401 - $this->logout();
402 - return new Response( true, array( 'message' => __( 'Your site has been disconnected successfully!', 'defender-security' ) ) );
403 - }
404 -
405 - /**
406 371 * Handle request to switch managed by.
407 372 *
408 373 * @defender_route
409 374 * @return Response
@@ -454,9 +419,9 @@
454 419 'sanitize' => 'sanitize_text_field',
455 420 ),
456 421 'email' => array(
457 422 'type' => 'string',
458 - 'sanitize' => 'sanitize_text_field',
423 + 'sanitize' => 'sanitize_email',
459 424 ),
460 425 'service' => array(
461 426 'type' => 'string',
462 427 'sanitize' => 'sanitize_text_field',
@@ -466,18 +431,40 @@
466 431 'sanitize' => 'sanitize_text_field',
467 432 ),
468 433 )
469 434 );
435 +
436 + $reporter_email = isset( $data['email'] ) ? trim( $data['email'] ) : '';
437 + if ( '' === $reporter_email || ! is_email( $reporter_email ) ) {
438 + return new Response(
439 + false,
440 + array(
441 + 'message' => esc_html__( 'A valid email address is required.', 'defender-security' ),
442 + )
443 + );
444 + }
445 +
470 446 // Logging.
471 447 $message = sprintf(
472 448 'IP: %s, email: %s, service: %s, reason: %s',
473 449 $data['ip'],
474 - $data['email'],
450 + $reporter_email,
475 451 $data['service'],
476 452 $data['reason']
477 453 );
478 454 $this->service->log_ip_message( $message );
479 455
456 + // Track the request. Forced so it operates independently of tracking consent.
457 + $this->forced_track(
458 + 'def_request_trusted_ip',
459 + array(
460 + 'IP Address' => $data['ip'],
461 + 'User Email' => $reporter_email,
462 + 'Service' => $data['service'],
463 + 'Reason' => $data['reason'],
464 + )
465 + );
466 +
480 467 return new Response( true, array() );
481 468 }
482 469
483 470 /**
@@ -511,8 +498,17 @@
511 498
512 499 $bl_service = wd_di()->get( Blacklist_Lockout::class );
513 500 $gi_service = wd_di()->get( Global_IP::class );
514 501
502 + $ip = $data['ip'];
503 +
504 + $is_ip_allowed = $bl_service->is_ip_whitelisted( $ip )
505 + || $bl_service->is_country_whitelist( $ip )
506 + || ( $gi_service->is_global_ip_enabled() && $gi_service->is_ip_allowed( $ip ) );
507 +
508 + // Fetch the latest Custom IP blocklist from the Hub so we don't rely on stale cached data.
509 + $gi_service->fetch_global_ip_list();
510 +
515 511 return new Response(
516 512 true,
517 513 array(
518 514 'success' => true,
@@ -517,11 +513,11 @@
517 513 array(
518 514 'success' => true,
519 515 'show_notice' => false,
520 516 'message' => __( 'The IP address is searched successfully.', 'defender-security' ),
521 - 'local' => $bl_service->is_blacklist( $data['ip'] ),
522 - 'central' => $gi_service->is_global_ip_enabled() && $gi_service->is_ip_blocked( $data['ip'] ),
523 - 'antibot' => $this->service->is_ip_blocked( $data['ip'] ),
517 + 'local' => ! $is_ip_allowed && $bl_service->is_blacklist( $data['ip'] ),
518 + 'central' => ! $is_ip_allowed && $gi_service->is_global_ip_enabled() && $gi_service->is_ip_blocked( $data['ip'] ),
519 + 'antibot' => ! $is_ip_allowed && $this->service->is_ip_blocked( $ip ),
524 520 )
525 521 );
526 522 }
527 523
@@ -550,17 +546,19 @@
550 546 'message' => esc_html__( 'Invalid IP address.', 'defender-security' ),
551 547 )
552 548 );
553 549 }
554 - $collection = 'allowlist';
550 + $collection = 'allowlist';
551 + $model = wd_di()->get( \WP_Defender\Model\Setting\Blacklist_Lockout::class );
552 + $already_in_list = $model->is_ip_in_list( $ip, $collection );
553 +
555 554 // Add to Local allowlist.
556 - $model = wd_di()->get( \WP_Defender\Model\Setting\Blacklist_Lockout::class );
557 - if ( ! $model->is_ip_in_list( $ip, $collection ) ) {
555 + if ( ! $already_in_list ) {
558 556 $model->add_to_list( $ip, $collection );
559 557 }
560 558 // Add to Custom IP allowlist.
561 559 $global_ip_service = wd_di()->get( Global_IP::class );
562 - if ( $global_ip_service->can_central_ip_autosync() ) {
560 + if ( ! $already_in_list && $global_ip_service->can_central_ip_autosync() ) {
563 561 $data = array(
564 562 'allow_list' => array( $ip ),
565 563 );
566 564
@@ -574,22 +572,40 @@
574 572 );
575 573 }
576 574 }
577 575
576 + $manage_link_open = '<a href="' . network_admin_url( 'admin.php?page=wdf-ip-lockout&view=blocklist#tab-ip-allowlist' ) . '">';
577 + $manage_link_close = '</a>';
578 +
579 + if ( $already_in_list ) {
580 + $message = sprintf(
581 + /* translators: 1: IP address. 2: Opening anchor tag. 3: Closing anchor tag. */
582 + esc_html__(
583 + 'IP %1$s is already in your Site\'s allowlist. You can manage it in %2$sIP Lockouts%3$s.',
584 + 'defender-security'
585 + ),
586 + $ip,
587 + $manage_link_open,
588 + $manage_link_close
589 + );
590 + } else {
591 + $message = sprintf(
592 + /* translators: 1: IP address. 2: Opening anchor tag. 3: Closing anchor tag. */
593 + esc_html__(
594 + 'IP %1$s has been added to your Site\'s allowlist. You can manage it in %2$sIP Lockouts%3$s.',
595 + 'defender-security'
596 + ),
597 + $ip,
598 + $manage_link_open,
599 + $manage_link_close
600 + );
601 + }
602 +
578 603 return new Response(
579 604 true,
580 605 array(
581 - 'message' => sprintf(
582 - /* translators: 1: IP address. 2: Opening anchor tag. 3: Closing anchor tag. */
583 - esc_html__(
584 - 'IP %1$s has been added to your Site\'s allowlist. You can manage it in %2$sIP Lockouts%3$s.',
585 - 'defender-security'
586 - ),
587 - $ip,
588 - '<a href="' . network_admin_url( 'admin.php?page=wdf-ip-lockout&view=blocklist#tab-ip-allowlist' ) . '">',
589 - '</a>'
590 - ),
591 - 'interval' => 5,
606 + 'message' => $message,
607 + 'already_in_list' => $already_in_list,
592 608 )
593 609 );
594 610 }
595 611
@@ -672,9 +688,9 @@
672 688 *
673 689 * @return void
674 690 */
675 691 public function handle_expired_membership(): void {
676 - if ( $this->is_expired_membership_type() && $this->model->enabled ) {
692 + if ( $this->model->enabled && $this->is_expired_membership_type() ) {
677 693 $this->service->managed_by_plugin_action( false );
678 694 $this->log( 'AntiBot Global Firewall automatically disabled due to expired membership.', Antibot_Global_Firewall_Component::LOG_FILE_NAME );
679 695 }
680 696 }
@@ -702,10 +718,8 @@
702 718 'Feedback' => $data['feedback'],
703 719 )
704 720 );
705 721 }
706 - // Dismiss the global notice.
707 - $this->service->dismiss_global_notice();
708 722
709 723 $message = sprintf(
710 724 /* translators: 1: Open tag, 2: Close tag */
711 725 __( '%1$sThanks for your feedback!%2$s It helps us make Defender even better.', 'defender-security' ),
@@ -717,27 +731,8 @@
717 731 true,
718 732 array(
719 733 'message' => $message,
720 734 'auto_close' => true,
721 - )
722 - );
723 - }
724 -
725 - /**
726 - * Dismiss the global notice.
727 - *
728 - * @defender_route
729 - * @return Response
730 - */
731 - public function dismiss_global_notice(): Response {
732 - $this->service->dismiss_global_notice();
733 -
734 - return new Response(
735 - true,
736 - array(
737 - 'message' => __( 'The global notice has been dismissed.', 'defender-security' ),
738 - 'success' => true,
739 - 'show_notice' => false,
740 735 )
741 736 );
742 737 }
743 738 }