PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 3.0.1
Defender Security – Malware Scanner, Login Security & Firewall v3.0.1
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
defender-security / src / controller / hub.php

hub.php in Defender Security – Malware Scanner, Login Security & Firewall 3.0.1, at src/controller/hub.php

600 lines 17.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WP_Defender\Controller;
4
5 use WP_Defender\Behavior\WPMUDEV;
6 use WP_Defender\Component\Config\Config_Hub_Helper;
7 use WP_Defender\Controller;
8 use WP_Defender\Model\Lockout_Log;
9 use WP_Defender\Model\Notification\Audit_Report;
10 use WP_Defender\Model\Notification\Firewall_Notification;
11 use WP_Defender\Model\Notification\Firewall_Report;
12 use WP_Defender\Model\Notification\Malware_Notification;
13 use WP_Defender\Model\Notification\Malware_Report;
14 use WP_Defender\Model\Notification\Tweak_Reminder;
15 use WP_Defender\Model\Setting\Blacklist_Lockout;
16 use WP_Defender\Model\Setting\Login_Lockout;
17 use WP_Defender\Model\Setting\Notfound_Lockout;
18 use WP_Defender\Model\Setting\User_Agent_Lockout;
19 use WP_Defender\Model\Setting\Two_Fa;
20 use WP_Defender\Traits\Formats;
21 use WP_Defender\Traits\IO;
22
23 /**
24 * Class HUB
25 * @package WP_Defender\Controller
26 */
27 class HUB extends Controller {
28 use IO, Formats;
29
30 private $view_onboard = false;
31
32 public function __construct() {
33 $this->attach_behavior( WPMUDEV::class, WPMUDEV::class );
34 add_action( 'wdp_register_hub_action', array( &$this, 'add_hub_endpoint' ) );
35 add_action( 'defender_hub_sync', array( &$this, 'hub_sync' ) );
36 }
37
38 public function add_hub_endpoint( $actions ) {
39 $actions['defender_new_scan'] = array( &$this, 'new_scan' );
40 $actions['defender_schedule_scan'] = array( &$this, 'schedule_scan' );
41 $actions['defender_manage_audit_log'] = array( &$this, 'manage_audit_log' );
42 $actions['defender_manage_lockout'] = array( &$this, 'manage_lockout' );
43 $actions['defender_whitelist_ip'] = array( &$this, 'whitelist_ip' );
44 $actions['defender_blacklist_ip'] = array( &$this, 'blacklist_ip' );
45 $actions['defender_get_scan_progress'] = array( &$this, 'get_scan_progress' );
46 $actions['defender_manage_recaptcha'] = array( &$this, 'manage_recaptcha' );
47 $actions['defender_manage_2fa'] = array( &$this, 'manage_2fa' );
48
49 // Backup/restore settings.
50 $actions['defender_export_settings'] = array( &$this, 'export_settings' );
51 $actions['defender_import_settings'] = array( &$this, 'import_settings' );
52 // Get stats, version#1.
53 $actions['defender_get_stats'] = array( &$this, 'get_stats' );
54 // Version#2.
55 $actions['defender_get_stats_v2'] = array( &$this, 'defender_get_stats_v2' );
56
57 return $actions;
58 }
59
60 /**
61 * Create new scan, triggered from HUB.
62 */
63 public function new_scan() {
64 $scan = \WP_Defender\Model\Scan::create();
65 if ( is_wp_error( $scan ) ) {
66 wp_send_json_error(
67 array(
68 'message' => $scan->get_error_message(),
69 )
70 );
71 }
72 //Todo: need to save Malware_Report last_sent & est_timestamp?
73 wd_di()->get( Scan::class )->do_async_scan( 'hub' );
74 $this->maybe_change_onboarding_status();
75 wp_send_json_success();
76 }
77
78 /**
79 * Schedule a scan, from HUB.
80 *
81 * @param array $params
82 */
83 public function schedule_scan( $params ) {
84 $frequency = $params['frequency'];
85 $day = $params['day'];
86 $time = $params['time'];
87 $allowed_freq = array( 1, 7, 30 );
88 if (
89 ! in_array( $frequency, $allowed_freq, true )
90 || ! in_array( $day, $this->get_days_of_week(), true )
91 || ! in_array( $time, $this->get_times(), true )
92 ) {
93 wp_send_json_error();
94 }
95 $malware_report = new Malware_Report();
96 $malware_report->frequency = $frequency;
97 $malware_report->day = $day;
98 $malware_report->time = $time;
99 $malware_report->save();
100
101 $this->maybe_change_onboarding_status();
102 wp_send_json_success();
103 }
104
105 public function manage_audit_log() {
106 $response = null;
107 if ( class_exists( \WP_Defender\Model\Setting\Audit_Logging::class ) ) {
108 $settings = new \WP_Defender\Model\Setting\Audit_Logging();
109 $response = array();
110 if ( true === $settings->enabled ) {
111 $settings->enabled = false;
112 $response['enabled'] = false;
113 } else {
114 $settings->enabled = true;
115 $response['enabled'] = true;
116 }
117 $settings->save();
118 }
119 $this->maybe_change_onboarding_status();
120 wp_send_json_success( $response );
121 }
122
123 /**
124 * @param array $params
125 * @param string $action
126 */
127 public function manage_lockout( $params, $action ) {
128 $type = $params['type'];
129 $response = array();
130 if ( 'login' === $type ) {
131 $settings = new Login_Lockout();
132 if ( $settings->enabled ) {
133 $settings->enabled = false;
134 $response[ $type ] = 'disabled';
135 } else {
136 $settings->enabled = true;
137 $response[ $type ] = 'enabled';
138 }
139 $settings->save();
140 } elseif ( '404' === $type ) {
141 $settings = new Notfound_Lockout();
142 if ( $settings->enabled ) {
143 $settings->enabled = false;
144 $response[ $type ] = 'disabled';
145 } else {
146 $settings->enabled = true;
147 $response[ $type ] = 'enabled';
148 }
149 $settings->save();
150 } elseif ( 'ua-lockout' === $type ) {
151 $settings = new User_Agent_Lockout();
152 if ( $settings->enabled ) {
153 $settings->enabled = false;
154 $response[ $type ] = 'disabled';
155 } else {
156 $settings->enabled = true;
157 $response[ $type ] = 'enabled';
158 }
159 $settings->save();
160 } else {
161 $response[ $type ] = 'invalid';
162 }
163 $this->maybe_change_onboarding_status();
164 wp_send_json_success( $response );
165 }
166
167 /**
168 * @param array $params
169 * @param string $action
170 */
171 public function whitelist_ip( $params, $action ) {
172 $settings = new Blacklist_Lockout();
173 $ip = $params['ip'];
174 if ( $ip && filter_var( $ip, FILTER_VALIDATE_IP ) ) {
175 $settings->remove_from_list( $ip, 'blocklist' );
176 $settings->add_to_list( $ip, 'allowlist' );
177 } else {
178 wp_send_json_error();
179 }
180 $this->maybe_change_onboarding_status();
181 wp_send_json_success();
182 }
183
184 /**
185 * @param array $params
186 * @param string $action
187 */
188 public function blacklist_ip( $params, $action ) {
189 $settings = new Blacklist_Lockout();
190 $ip = $params['ip'];
191 if ( $ip && filter_var( $ip, FILTER_VALIDATE_IP ) ) {
192 $settings->remove_from_list( $ip, 'allowlist' );
193 $settings->add_to_list( $ip, 'blocklist' );
194 } else {
195 wp_send_json_error();
196 }
197 $this->maybe_change_onboarding_status();
198 wp_send_json_success();
199 }
200
201 /**
202 * Push data into HUB.
203 *
204 * @param array $params
205 * @param string $action
206 */
207 public function get_stats( $params, $action ) {
208 $data = $this->build_stats_to_hub();
209 wp_send_json_success(
210 array(
211 'stats' => $data,
212 )
213 );
214 }
215
216 /**
217 * Push scan data into HUB.
218 */
219 public function get_scan_progress() {
220 $model = \WP_Defender\Model\Scan::get_active();
221 if ( ! is_object( $model ) ) {
222 wp_send_json_success(
223 array(
224 'progress' => - 1,
225 )
226 );
227 }
228 $percent = $model->percent;
229 if ( $percent > 100 ) {
230 $percent = 100;
231 }
232 $this->maybe_change_onboarding_status();
233 wp_send_json_success(
234 array(
235 'progress' => $percent,
236 )
237 );
238 }
239
240 /**
241 * Export settings to HUB.
242 * Analog to export_strings but return not array. So separated method.
243 */
244 public function export_settings() {
245 $config_component = wd_di()->get( \WP_Defender\Component\Backup_Settings::class );
246 $data = $config_component->parse_data_for_hub();
247 // Replace all the new line in configs.
248 $configs = $data['configs'];
249 foreach ( $configs as $module => $mdata ) {
250 foreach ( $mdata as $key => $value ) {
251 if ( is_string( $value ) ) {
252 $value = str_replace( array( "\r", "\n" ), '{nl}', $value );
253 $mdata[ $key ] = $value;
254 }
255 }
256 $configs[ $module ] = $mdata;
257 }
258 $data['configs'] = $configs;
259 $this->maybe_change_onboarding_status();
260 wp_send_json_success( $data );
261 }
262
263 /**
264 * Import settings from HUB.
265 * Analog to import_data but with object $params. So separated method.
266 */
267 public function import_settings( $params ) {
268 // Dirty but quick.
269 if ( empty( $params->configs ) ) {
270 wp_send_json_error(
271 array(
272 'message' => __( 'Invalid config', 'wpdef' ),
273 )
274 );
275 }
276
277 $configs = json_decode( json_encode( $params->configs ), true );
278 if ( empty( $configs ) ) {
279 wp_send_json_error(
280 array(
281 'message' => __( 'Empty data', 'wpdef' ),
282 )
283 );
284 }
285
286 $config_component = wd_di()->get( \WP_Defender\Component\Backup_Settings::class );
287 $lockout_service = wd_di()->get( \WP_Defender\Component\Blacklist_Lockout::class );
288 foreach ( $configs as $module => $mdata ) {
289 foreach ( $mdata as $key => $value ) {
290 // Todo: update logic to import/export whitelisted/blocklisted countries via maxmind_license_key.
291 if ( in_array( $key, array( 'geoIP_db', 'geodb_path' ), true ) ) {
292 if ( ! empty( $value ) ) {
293 // Download it.
294 $lockout_service->download_geo_ip();
295 } else {
296 // Reset it.
297 $mdata[ $key ] = '';
298 }
299 } elseif ( is_string( $value ) ) {
300 $value = str_replace( '{nl}', PHP_EOL, $value );
301 $mdata[ $key ] = $value;
302 }
303 }
304 $configs[ $module ] = $mdata;
305 }
306
307 // If it's old config structure then we upgrade configs to new format.
308 if ( ! empty( $configs ) && ! $config_component->check_for_new_structure( $configs ) ) {
309 $adapter = wd_di()->get( \WP_Defender\Component\Config\Config_Adapter::class );
310 $configs = $adapter->upgrade( $configs );
311 }
312 $restore_result = $config_component->restore_data( $configs, 'hub' );
313 if ( is_string( $restore_result ) ) {
314 wp_send_json_error(
315 array(
316 'message' => $restore_result,
317 )
318 );
319 }
320 $this->maybe_change_onboarding_status();
321
322 // Active config.
323 Config_Hub_Helper::active_config_from_hub_id( $params->hub_config_id );
324
325 wp_send_json_success();
326 }
327
328 /**
329 * Build the json data for HUB 2.0.
330 */
331 public function defender_get_stats_v2() {
332 global $wp_version;
333
334 $audit_log = wd_di()->get( Audit_Logging::class );
335 $audit = $audit_log->summary_data( true );
336
337 $scan = \WP_Defender\Model\Scan::get_last();
338 $total = 0;
339 if ( is_object( $scan ) ) {
340 $total += count( $scan->get_issues() );
341 }
342 // Total number of Scan issues and Ignored items.
343 $scan_total_issues = $total;
344
345 $tweaks = wd_di()->get( Security_Tweaks::class )->data_frontend();
346 $total += $tweaks['summary']['issues_count'];
347 // Get statuses of login/404-request if Firewall Notification is enabled.
348 // Todo: add ua_lockout to structure when Firewall - Notification will have an option for that.
349 $firewall_notification = wd_di()->get( Firewall_Notification::class );
350 if ( 'enabled' === $firewall_notification->status ) {
351 $login_lockout = $firewall_notification->configs['login_lockout'];
352 $nf_lockout = $firewall_notification->configs['nf_lockout'];
353 } else {
354 $login_lockout = $nf_lockout = false;// phpcs:ignore
355 }
356 $status_active = \WP_Defender\Model\Notification::STATUS_ACTIVE;
357 $model_sec_headers = wd_di()->get( \WP_Defender\Model\Setting\Security_Headers::class );
358 $scan_report = wd_di()->get( Malware_Report::class );
359 $ret = array(
360 'summary' => array(
361 'count' => $total,
362 'next_scan' => $scan_report->get_next_run_for_hub(),
363 ),
364 'report' => array(
365 'malware_scan' => $scan_report->get_next_run_as_string( true ),
366 'firewall' => wd_di()->get( Firewall_Report::class )->get_next_run_as_string( true ),
367 'audit_logging' => wd_di()->get( Audit_Report::class )->get_next_run_as_string( true ),
368 ),
369 'security_tweaks' => array(
370 'issues' => $tweaks['summary']['issues_count'],
371 'fixed' => $tweaks['summary']['fixed_count'],
372 'notification' => wd_di()->get( Tweak_Reminder::class )->status === $status_active,
373 'wp_version' => $wp_version,
374 'php_version' => PHP_VERSION,
375 ),
376 'malware_scan' => array(
377 'count' => $scan_total_issues,
378 'notification' => wd_di()->get( Malware_Notification::class )->status === $status_active,
379 ),
380 'firewall' => array(
381 'last_lockout' => Lockout_Log::get_last_lockout_date( true ),
382 '24_hours' => array(
383 'login_lockout' => Lockout_Log::count(
384 strtotime( '-24 hours' ),
385 time(),
386 array(
387 Lockout_Log::AUTH_LOCK,
388 )
389 ),
390 '404_lockout' => Lockout_Log::count(
391 strtotime( '-24 hours' ),
392 time(),
393 array(
394 Lockout_Log::LOCKOUT_404,
395 )
396 ),
397 'user_agent_lockout' => Lockout_Log::count(
398 strtotime( '-24 hours' ),
399 time(),
400 array(
401 Lockout_Log::LOCKOUT_UA,
402 )
403 ),
404 ),
405 '7_days' => array(
406 'login_lockout' => Lockout_Log::count_login_lockout_last_7_days(),
407 '404_lockout' => Lockout_Log::count_404_lockout_last_7_days(),
408 'user_agent_lockout' => Lockout_Log::count_ua_lockout_last_7_days(),
409 ),
410 '30_days' => array(
411 'login_lockout' => Lockout_Log::count(
412 strtotime( '-30 days' ),
413 time(),
414 array(
415 Lockout_Log::AUTH_LOCK,
416 )
417 ),
418 '404_lockout' => Lockout_Log::count(
419 strtotime( '-30 days' ),
420 time(),
421 array(
422 Lockout_Log::LOCKOUT_404,
423 )
424 ),
425 'user_agent_lockout' => Lockout_Log::count(
426 strtotime( '-30 days' ),
427 time(),
428 array(
429 Lockout_Log::LOCKOUT_UA,
430 )
431 ),
432 ),
433 'notification_status' => array(
434 'login_lockout' => $login_lockout,
435 '404_lockout' => $nf_lockout,
436 // Todo: add ua_lockout later.
437 ),
438 'login_lockout_enabled' => wd_di()->get( Login_Lockout::class )->enabled,
439 'lockout_404_enabled' => wd_di()->get( Notfound_Lockout::class )->enabled,
440 'user_agent_lockout_enabled' => wd_di()->get( User_Agent_Lockout::class )->enabled,
441 ),
442 'audit' => array(
443 'last_event' => $audit['lastEvent'],
444 '24_hours' => $audit['dayCount'],
445 '7_days' => $audit['weekCount'],
446 '30_days' => $audit['monthCount'],
447 'enabled' => $audit_log->model->is_active(),
448 ),
449 'advanced_tools' => array(
450 'security_headers' => array(
451 'sh_xframe' => $model_sec_headers->sh_xframe,
452 'sh_xss_protection' => $model_sec_headers->sh_xss_protection,
453 'sh_content_type_options' => $model_sec_headers->sh_content_type_options,
454 'sh_strict_transport' => $model_sec_headers->sh_strict_transport,
455 'sh_referrer_policy' => $model_sec_headers->sh_referrer_policy,
456 'sh_feature_policy' => $model_sec_headers->sh_feature_policy,
457 ),
458 'mask_login' => wd_di()->get( \WP_Defender\Model\Setting\Mask_Login::class )->is_active(),
459 'google_recaptcha' => array(
460 'status' => wd_di()->get( \WP_Defender\Model\Setting\Recaptcha::class )->is_active(),
461 ),
462 'password_protection' => array(
463 'status' => wd_di()->get( \WP_Defender\Model\Setting\Password_Protection::class )->is_active(),
464 ),
465 ),
466 'two_fa' => array(
467 'status' => wd_di()->get( Two_Fa::class )->enabled,
468 'lost_phone' => wd_di()->get( Two_Fa::class )->lost_phone,
469 ),
470 );
471
472 wp_send_json_success(
473 array(
474 'stats' => $ret,
475 )
476 );
477 }
478
479 public function hub_sync() {
480 $data = $this->build_stats_to_hub();
481 $this->make_wpmu_request(
482 WPMUDEV::API_HUB_SYNC,
483 $data,
484 array(
485 'method' => 'POST',
486 )
487 );
488 }
489
490 public function remove_settings() {}
491
492 public function remove_data() {}
493
494 public function data_frontend() {}
495
496 public function to_array() {}
497
498 public function import_data( $data ) {}
499
500 /**
501 * @return array
502 */
503 public function export_strings() {
504 return array();
505 }
506
507 /**
508 * Change status of Onboarding if there are remoted requests, e.g. from Hub.
509 */
510 private function maybe_change_onboarding_status() {
511 if ( $this->view_onboard ) {
512 update_site_option( 'wp_defender_shown_activator', true );
513 $this->view_onboard = false;
514 }
515 }
516
517 /**
518 * Display Onboard if the bool value 'true' and vice versa.
519 * @param bool $is_show
520 */
521 public function set_onboarding_status( $is_show ) {
522 $this->view_onboard = $is_show;
523 }
524
525 /**
526 * @return bool
527 */
528 public function get_onboarding_status() {
529 return $this->view_onboard;
530 }
531
532 /**
533 * Only requests from Hub and for separate pages.
534 */
535 public function listen_to_requests() {
536 if ( $this->view_onboard && is_admin() && isset( $_GET['page'] ) && ! empty( $_GET['page'] ) ) {
537 // Redirect from the Plugins page after clicking on the Settings link.
538 $pages = array( 'wdf-setting' );
539 if ( $this->is_wpmu_dev_admin() ) {
540 // No 'wp-defender' because it's a default slug for Def Dashboard.
541 array_push(
542 $pages,
543 'wdf-hardener',
544 'wdf-scan',
545 'wdf-logging',
546 'wdf-ip-lockout',
547 'wdf-2fa',
548 'wdf-advanced-tools'
549 );
550 }
551 if ( in_array( sanitize_text_field( $_GET['page'] ), $pages, true ) ) {
552 update_site_option( 'wp_defender_shown_activator', true );
553 $this->view_onboard = false;
554 }
555 }
556 }
557
558 /**
559 * Activate/deactivate reCaptcha from HUB.
560 */
561 public function manage_recaptcha() {
562 $response = null;
563 if ( class_exists( \WP_Defender\Model\Setting\Recaptcha::class ) ) {
564 $settings = new \WP_Defender\Model\Setting\Recaptcha();
565 $response = array();
566 if ( true === $settings->enabled ) {
567 $settings->enabled = false;
568 $response['enabled'] = false;
569 } else {
570 $settings->enabled = true;
571 $response['enabled'] = true;
572 }
573 $settings->save();
574 }
575 $this->maybe_change_onboarding_status();
576 wp_send_json_success( $response );
577 }
578
579 /**
580 * Activate/deactivate 2FA from HUB.
581 */
582 public function manage_2fa() {
583 $response = null;
584 if ( class_exists( \WP_Defender\Model\Setting\Two_Fa::class ) ) {
585 $settings = new \WP_Defender\Model\Setting\Two_Fa();
586 $response = array();
587 if ( true === $settings->enabled ) {
588 $settings->enabled = false;
589 $response['enabled'] = false;
590 } else {
591 $settings->enabled = true;
592 $response['enabled'] = true;
593 }
594 $settings->save();
595 }
596 $this->maybe_change_onboarding_status();
597 wp_send_json_success( $response );
598 }
599 }
600