File manager - Edit - /home/xfekoga/grenier/wp-content/plugins/defender-security/src/traits/defender-hub-client.php
Back
<?php /** * Handle HUB based functionalities of WPMUDEV class. * * @package WP_Defender\Traits */ namespace WP_Defender\Traits; use WP_Error; use DateTime; use Exception; use WP_User_Query; use WPMUDEV_Dashboard; use WP_Defender\Model\Scan; use WP_Defender\Model\Audit_Log; use WP_Defender\Model\Notification; use WP_Defender\Controller\Firewall; use WP_Defender\Component\Quarantine; use WP_Defender\Model\Setting\Two_Fa; use WP_Defender\Component\IP\Antibot_Global_Firewall; use WP_Defender\Model\Setting\Recaptcha; use WP_Defender\Model\Setting\Mask_Login; use WP_Defender\Controller\Security_Tweaks; use WP_Defender\Controller\Security_Headers; use WP_Defender\Model\Setting\Audit_Logging; use WP_Defender\Model\Setting\Login_Lockout; use WP_Defender\Model\Setting\Notfound_Lockout; use WP_Defender\Model\Notification\Audit_Report; use WP_Defender\Model\Setting\Global_Ip_Lockout; use WP_Defender\Model\Setting\User_Agent_Lockout; use WP_Defender\Model\Notification\Malware_Report; use WP_Defender\Model\Setting\Password_Protection; use WP_Defender\Model\Notification\Firewall_Report; use WP_Defender\Model\Setting\Scan as Scan_Settings; use WP_Defender\Model\Notification\Firewall_Notification; use WP_Defender\Model\Setting\Security_Tweaks as Model_Security_Tweaks; trait Defender_Hub_Client { use IP; /** * Get API base URL. * * @return string * @since 3.4.0 */ public function get_api_base_url(): string { return defined( 'WPMUDEV_CUSTOM_API_SERVER' ) && WPMUDEV_CUSTOM_API_SERVER ? trailingslashit( WPMUDEV_CUSTOM_API_SERVER ) : 'https://wpmudev.com/'; } /** * Retrieves the endpoint URL based on the given scenario. * * @param string $scenario The scenario identifier. * * @return string The endpoint URL. */ public function get_endpoint( $scenario ): string { $base = $this->get_api_base_url(); switch ( $scenario ) { case self::API_SCAN_KNOWN_VULN: return $base . 'api/defender/v1/vulnerabilities'; case self::API_SCAN_SIGNATURE: return $base . 'api/defender/v1/yara-signatures'; case self::API_AUDIT: // This is from another endpoint. $base = defined( 'WPMUDEV_CUSTOM_AUDIT_SERVER' ) ? constant( 'WPMUDEV_CUSTOM_AUDIT_SERVER' ) : 'https://audit.wpmudev.org/'; return $base . 'logs'; case self::API_AUDIT_ADD: $base = defined( 'WPMUDEV_CUSTOM_AUDIT_SERVER' ) ? constant( 'WPMUDEV_CUSTOM_AUDIT_SERVER' ) : 'https://audit.wpmudev.org/'; return $base . 'logs/add_multiple'; case self::API_BLACKLIST: return $base . 'api/defender/v1/blacklist-monitoring?domain=' . network_site_url(); case self::API_GLOBAL_IP_LIST: return $base . 'api/hub/v1/global-ip-list'; case self::API_PACKAGE_CONFIGS: return $base . 'api/hub/v1/package-configs'; case self::API_IP_BLOCKLIST_SUBMIT_LOGS: return $base . 'api/blocklist/v1/logs'; case self::API_ANTIBOT_GLOBAL_FIREWALL: $site_id = $this->get_site_id(); return $base . "api/hub/v1/sites/$site_id/modules/hosting/antibot"; case self::API_HUB_SYNC: default: return $base . 'api/defender/v1/scan-results'; } } /** * Get WPMUDEV site id. * * @return int|bool */ public function get_site_id() { if ( false !== $this->get_apikey() ) { return (int) WPMUDEV_Dashboard::$api->get_site_id(); } return false; } /** * HUB API remote request method. * * @param string $scenario The scenario for the API request. * @param array $body The body of the API request. Default is an empty array. * @param array $args The arguments for the API request. Default is an empty array. * @param bool $recheck Whether to recheck the API request. Default is false. * * @return array|WP_Error The response body of the API request or a WP_Error object. * @throws Exception If the Dash plugin authentication API key is missing. */ private function hub_api_request( string $scenario, array $body = array(), array $args = array(), bool $recheck = false ) { $api_key = $this->get_api_key(); $body['domain'] ??= network_site_url(); $headers = array( 'Authorization' => 'Basic ' . $api_key, 'apikey' => $api_key, ); $timeout = isset( $args['timeout'] ) ? $args['timeout'] : 30; $args = array_merge( $args, array( 'body' => $body, 'headers' => $headers, 'timeout' => $timeout, 'sslverify' => apply_filters( 'https_ssl_verify', true ), ) ); $request = wp_remote_request( $this->get_endpoint( $scenario ), $args ); if ( is_wp_error( $request ) ) { if ( ! $recheck ) { return $request; } // Sometimes a response comes with a curl error #52 so should delete Authorization header. $args['headers'] = array( 'apikey' => $api_key ); $request = wp_remote_request( $this->get_endpoint( $scenario ), $args ); if ( is_wp_error( $request ) ) { return $request; } } $result = wp_remote_retrieve_body( $request ); $result = json_decode( $result, true ); if ( 200 !== wp_remote_retrieve_response_code( $request ) ) { return new WP_Error( wp_remote_retrieve_response_code( $request ), $result['message'] ?? wp_remote_retrieve_response_message( $request ) ); } return $result; } /** * Makes a request to the WPMU API. * * @param string $scenario The scenario for the request. * @param array $body The body of the request. Default is an empty array. * @param array $args Additional arguments for the request. Default is an empty array. * @param bool $recheck Whether to recheck the request. Default is false. * * @return array|WP_Error The response from the API request. */ public function make_wpmu_request( string $scenario, array $body = array(), array $args = array(), bool $recheck = false ) { $api_key = $this->get_api_key(); if ( empty( $api_key ) ) { $link_text = sprintf( '<a target="_blank" href="%s">%s</a>', 'https://wpmudev.com/project/wpmu-dev-dashboard/', esc_html__( 'here', 'defender-security' ) ); return new WP_Error( 'dashboard_required', sprintf( /* translators: %s - wpmudev link */ esc_html__( 'WPMU DEV Dashboard will be required for this action. Please visit %s and install the WPMU DEV Dashboard.', 'defender-security' ), $link_text ) ); } return $this->hub_api_request( $scenario, $body, $args, $recheck ); } /** * Makes a request to the WPMU API for free and higher account holding users. * * @param string $scenario The scenario for the request. * @param array $body The body of the request. Default is an empty array. * @param array $args Additional arguments for the request. Default is an empty array. * @param bool $recheck Whether to recheck the request. Default is false. * * @return array|WP_Error The response from the API request. * @throws Exception If the Dash plugin authentication API key is missing. * @throws Exception If permission is denied for the API call. */ public function make_wpmu_free_request( string $scenario, array $body = array(), array $args = array(), bool $recheck = false ) { if ( ! $this->hub_connector_connected() ) { throw new Exception( esc_html__( 'API key missing.', 'defender-security' ) ); } if ( $this->can_wpmu_free_request() === false ) { throw new Exception( esc_html__( 'Permission denied API call.', 'defender-security' ) ); } return $this->hub_api_request( $scenario, $body, $args, $recheck ); } /** * Check if the current request can be made as a free API request. * * @return bool True if the request is allowed, false otherwise. * @throws Exception If the WPMU DEV Dashboard plugin is missing. */ public function can_wpmu_free_request() { return in_array( $this->get_membership_type(), array( 'free', 'full' ), true ); } /** * This will build data relate to scan module, so we can push to hub. * * @return array * @since 2.4.7 add 'plugin_integrity' args */ protected function build_scan_hub_data(): array { $scan = Scan::get_last(); $scan_result = array( 'core_integrity' => 0, 'plugin_integrity' => 0, 'vulnerability_db' => 0, 'file_suspicious' => 0, 'last_completed' => false, 'scan_items' => array(), 'num_issues' => 0, 'num_ignored_issues' => 0, ); $total_issues = 0; if ( is_object( $scan ) ) { $data = $scan->prepare_issues( 10, 1 ); $scan_result['core_integrity'] = $data['count_core']; $scan_result['plugin_integrity'] = $data['count_plugin']; $scan_result['vulnerability_db'] = $data['count_vuln']; $scan_result['file_suspicious'] = $data['count_malware']; $scan_result['last_completed'] = $scan->date_end; $scan_result['num_ignored_issues'] = $data['count_ignored']; if ( ! empty( $data['issues'] ) ) { $total_issues = $data['count_issues']; foreach ( $data['issues'] as $issue ) { $scan_result['scan_items'][] = array( 'file' => $issue['full_path'] ?? $issue['file_name'], 'detail' => $issue['short_desc'], ); } } $scan_result['num_issues'] = $total_issues + $data['count_ignored']; } $settings = new Scan_Settings(); return array( 'timestamp' => is_object( $scan ) ? strtotime( $scan->date_start ) : '', 'warning' => $total_issues, 'scan_result' => $scan_result, 'scan_schedule' => array( // @since 2.7.0 change scheduled scan logic. 'is_activated' => $settings->scheduled_scanning, // Example of frequency, day, time in build_notification_hub_data() method. 'time' => $settings->time, 'day' => $this->get_notification_day( $settings ), 'frequency' => $this->backward_frequency_compatibility( $settings->frequency ), ), ); } /** * Converts a string frequency to an integer value for backward compatibility. * * @param string $frequency The frequency to convert. Must be one of 'daily', 'weekly', or 'monthly'. * * @return int The converted integer value. Returns 1 for 'daily', 7 for 'weekly', and 30 for 'monthly' (default). */ public function backward_frequency_compatibility( string $frequency ): int { switch ( $frequency ) { case 'daily': return 1; case 'weekly': return 7; case 'monthly': default: return 30; } } /** * Build data for security tweaks. * * @return array */ protected function build_security_tweaks_hub_data(): array { // Exclude direct call of data_frontend(). $tweak_arr = wd_di()->get( Model_Security_Tweaks::class )->get_tweak_types(); $data = array( 'cautions' => $tweak_arr['count_issues'], 'issues' => array(), 'ignore' => array(), 'fixed' => array(), ); $types = array( Security_Tweaks::STATUS_ISSUES, Security_Tweaks::STATUS_IGNORE, Security_Tweaks::STATUS_RESOLVE, ); $view = ''; foreach ( $types as $type ) { if ( 'ignore' === $type ) { $view = '&view=ignored'; } elseif ( 'fixed' === $type ) { $view = '&view=resolved'; } foreach ( wd_di()->get( Security_Tweaks::class )->init_tweaks( $type ) as $slug => $tweak ) { $data[ $type ][] = array( 'label' => $tweak->get_label(), 'url' => network_admin_url( 'admin.php?page=wdf-hardener' . $view . '#' . $slug ), ); } } return $data; } /** * Builds an array of audit data to be sent to the hub. * * @return array An array containing the number of audit log entries, the timestamp of the * last audit log entry, and a boolean indicating if audit logging is enabled. */ public function build_audit_hub_data(): array { $date_from = ( new DateTime( wp_date( 'Y-m-d', strtotime( '-30 days' ) ) ) )->setTime( 0, 0, 0 )->getTimestamp(); $date_to = ( new DateTime( wp_date( 'Y-m-d' ) ) )->setTime( 23, 59, 59 )->getTimestamp(); $month_count = Audit_Log::count( $date_from, $date_to ); $last = Audit_Log::get_last(); if ( is_object( $last ) ) { $last = wp_date( 'Y-m-d g:i a', $last->timestamp ); } else { $last = 'n/a'; } $settings = new Audit_Logging(); return array( 'month' => $month_count, 'last_event' => $last, 'enabled' => $settings->is_active(), ); } /** * Builds an array of lockout data to be sent to the hub. * * @return array */ public function build_lockout_hub_data(): array { $firewall = wd_di()->get( Firewall::class )->data_frontend(); return array( 'last_lockout' => $firewall['last_lockout'], 'lp' => wd_di()->get( Login_Lockout::class )->enabled, 'lp_week' => $firewall['login']['week'], 'nf' => wd_di()->get( Notfound_Lockout::class )->enabled, 'nf_week' => $firewall['nf']['week'], 'ua' => wd_di()->get( User_Agent_Lockout::class )->enabled, 'ua_week' => $firewall['ua']['week'], 'global_ip_list_enabled' => wd_di()->get( Global_Ip_Lockout::class )->enabled, 'antibot_enabled' => wd_di()->get( Antibot_Global_Firewall::class )->frontend_is_enabled(), ); } /** * Builds an array of 2fa data to be sent to the hub. * * @return array */ public function build_2fa_hub_data(): array { $settings = new Two_Fa(); $service = wd_di()->get( \WP_Defender\Component\Two_Fa::class ); $query = new WP_User_Query( array( // Look over the network. 'blog_id' => 0, 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query array( 'key' => $service::DEFAULT_PROVIDER_USER_KEY, 'value' => array_keys( $service->get_providers() ), 'compare' => 'IN', ), ), ) ); $active_users = array(); if ( $query->get_total() > 0 ) { foreach ( $query->get_results() as $obj_user ) { $active_users[] = array( 'display_name' => $obj_user->data->display_name, ); } } return array( 'active' => $settings->enabled && count( $settings->user_roles ), 'enabled' => $settings->enabled, 'active_users' => $active_users, ); } /** * Builds an array of mask login data to be sent to the hub. * * @return array */ public function build_mask_login_hub_data(): array { $settings = new Mask_Login(); return array( 'active' => $settings->is_active(), 'masked_url' => $settings->mask_url, ); } /** * Builds an array of security headers data to be sent to the hub. * * @return array */ public function build_recaptcha_hub_data(): array { $settings = new Recaptcha(); return array( 'active' => $settings->is_active(), ); } /** * Builds an array of password protection data to be sent to the hub. * * @return array */ public function build_password_protection_hub_data(): array { $settings = new Password_Protection(); return array( 'active' => $settings->is_active(), ); } /** * Get the notification day. * * @param object $module_report The report object. * * @return string */ private function get_notification_day( $module_report ): string { if ( ! is_object( $module_report ) ) { return ''; } if ( 'daily' === $module_report->frequency ) { $day = '1'; } elseif ( 'weekly' === $module_report->frequency ) { $day = $module_report->day; } else { // For "monthly" frequency. $day = $module_report->day_n; } return $day; } /** * Frequency format: * if frequency is day, e.g.: 'frequency' => 1, 'day' => '1', 'time' => '20:30' * if frequency is week, e.g.: 'frequency' => 7, 'day' => 'wednesday', 'time' => '14:00' * if frequency is month, e.g.: 'frequency' => 30, 'day' => '4', 'time' => '4:30' * * @return array */ public function build_notification_hub_data(): array { $audit_settings = new Audit_Logging(); $audit_report = new Audit_Report(); $firewall_report = new Firewall_Report(); $malware_report = new Malware_Report(); $scan_settings = new Scan_Settings(); return array( 'file_scanning' => array( 'active' => true, // @since 2.7.0 move scheduled options to Scan settings, but we get status of Malware Scanning - Reporting here. 'enabled' => Notification::STATUS_ACTIVE === $malware_report->status, // Report enabled bool value. 'frequency' => array( 'frequency' => $this->backward_frequency_compatibility( $scan_settings->frequency ), 'day' => $this->get_notification_day( $scan_settings ), 'time' => $scan_settings->time, ), ), 'audit_logging' => array( 'active' => $audit_settings->is_active(), 'enabled' => Notification::STATUS_ACTIVE === $audit_report->status, 'frequency' => array( 'frequency' => $this->backward_frequency_compatibility( $audit_report->frequency ), 'day' => $this->get_notification_day( $audit_report ), 'time' => $audit_report->time, ), ), 'ip_lockouts' => array( // Always true as we have blacklist listening. 'active' => true, 'enabled' => Notification::STATUS_ACTIVE === $firewall_report->status, // Report enabled bool value. 'frequency' => array( 'frequency' => $this->backward_frequency_compatibility( $firewall_report->frequency ), 'day' => $this->get_notification_day( $firewall_report ), 'time' => $firewall_report->time, ), ), ); } /** * Build data for firewall notification. * * @return array */ public function build_firewall_notification_hub_data(): array { $firewall_notification = new Firewall_Notification(); if ( 'enabled' === $firewall_notification->status ) { $login_lockout = $firewall_notification->configs['login_lockout']; $nf_lockout = $firewall_notification->configs['nf_lockout']; $ua_lockout = $firewall_notification->configs['ua_lockout'] ?? false; } else { $login_lockout = false; $nf_lockout = false; $ua_lockout = false; } return array( 'firewall' => array( 'login_lockout' => $login_lockout, '404_lockout' => $nf_lockout, 'ua_lockout' => $ua_lockout, ), ); } /** * Build security headers hub data. * * @return array */ public function build_security_headers_hub_data(): array { $security_headers = wd_di()->get( Security_Headers::class )->get_type_headers(); return array( 'active' => $security_headers['active'], 'inactive' => $security_headers['inactive'], ); } /** * Build data to be sent to the hub. * * @return array */ public function build_stats_to_hub(): array { $scan_data = $this->build_scan_hub_data(); $tweaks_data = $this->build_security_tweaks_hub_data(); $audit_data = $this->build_audit_hub_data(); $firewall_data = $this->build_lockout_hub_data(); $two_fa = $this->build_2fa_hub_data(); $mask_login = $this->build_mask_login_hub_data(); $sec_headers = $this->build_security_headers_hub_data(); $recaptcha = $this->build_recaptcha_hub_data(); $pwned_password = $this->build_password_protection_hub_data(); $quarantined_files = $this->build_quarantined_files_hub_data(); return array( // Domain name. 'domain' => network_home_url(), // Last scan date. 'timestamp' => $scan_data['timestamp'], // Scan issue count. 'warnings' => $scan_data['warning'], // Security tweaks issue count. 'cautions' => $tweaks_data['cautions'], 'data_version' => wp_date( 'Ymd' ), 'scan_data' => wp_json_encode( array( 'scan_result' => $scan_data['scan_result'], 'hardener_result' => array( 'issues' => $tweaks_data[ Security_Tweaks::STATUS_ISSUES ], 'ignored' => $tweaks_data[ Security_Tweaks::STATUS_IGNORE ], 'resolved' => $tweaks_data[ Security_Tweaks::STATUS_RESOLVE ], ), 'scan_schedule' => $scan_data['scan_schedule'], 'audit_status' => array( 'events_in_month' => $audit_data['month'], 'audit_enabled' => $audit_data['enabled'], 'last_event_date' => $audit_data['last_event'], ), 'audit_page_url' => network_admin_url( 'admin.php?page=wdf-logging' ), 'labels' => array( // Todo: maybe should it remove because Scan Settings model has label() method for that? 'parent_integrity' => esc_html__( 'File change detection', 'defender-security' ), 'core_integrity' => esc_html__( 'Scan core files', 'defender-security' ), 'plugin_integrity' => esc_html__( 'Scan plugin files', 'defender-security' ), 'vulnerability_db' => esc_html__( 'Known vulnerabilities', 'defender-security' ), 'file_suspicious' => esc_html__( 'Suspicious code', 'defender-security' ), ), 'scan_page_url' => network_admin_url( 'admin.php?page=wdf-scan' ), 'hardener_page_url' => network_admin_url( 'admin.php?page=wdf-hardener' ), 'new_scan_url' => network_admin_url( 'admin.php?page=wdf-scan&wdf-action=new_scan' ), 'schedule_scans_url' => network_admin_url( 'admin.php?page=wdf-schedule-scan' ), 'settings_page_url' => network_admin_url( 'admin.php?page=wdf-settings' ), 'ip_lockout_page_url' => network_admin_url( 'admin.php?page=wdf-ip-lockout' ), 'last_lockout' => $firewall_data['last_lockout'], 'login_lockout_enabled' => $firewall_data['lp'], 'login_lockout' => $firewall_data['lp_week'], 'lockout_404_enabled' => $firewall_data['nf'], 'lockout_404' => $firewall_data['nf_week'], 'lockout_ua_enabled' => $firewall_data['ua'], 'lockout_ua' => $firewall_data['ua_week'], 'total_lockout' => (int) $firewall_data['lp_week'] + (int) $firewall_data['nf_week'] + (int) $firewall_data['ua_week'], 'global_ip_list_enabled' => $firewall_data['global_ip_list_enabled'], 'antibot_enabled' => $firewall_data['antibot_enabled'], 'advanced' => array( // This is moved but still keep here for backward compatibility. 'multi_factors_auth' => array( 'active' => $two_fa['active'], 'enabled' => $two_fa['enabled'], 'active_users' => $two_fa['active_users'], ), 'mask_login' => array( 'activate' => $mask_login['active'], 'masked_url' => $mask_login['masked_url'], ), 'security_headers' => array( 'active' => $sec_headers['active'], 'inactive' => $sec_headers['inactive'], ), 'google_recaptcha' => array( 'active' => $recaptcha['active'], ), 'password_protection' => array( 'active' => $pwned_password['active'], ), ), 'reports' => $this->build_notification_hub_data(), 'notifications' => $this->build_firewall_notification_hub_data(), 'quarantined_files' => $quarantined_files, ) ), ); } /** * Checks whether we're on WPMU DEV Hosting. * * @return bool */ public function is_wpmu_hosting(): bool { return ! empty( $_SERVER['WPMUDEV_HOSTED'] ); } /** * Checks whether we're on The Free HUB. * * @return bool */ protected function is_tfh_account(): bool { return class_exists( 'WPMUDEV_Dashboard' ) && is_object( WPMUDEV_Dashboard::$api ) && method_exists( WPMUDEV_Dashboard::$api, 'get_membership_status' ) && 'free' === WPMUDEV_Dashboard::$api->get_membership_status(); } /** * Check if WPMUDEV Hosted site is connected to The Free HUB. * * @return bool * @since 3.3.0 */ public function is_hosted_site_connected_to_tfh(): bool { return $this->is_tfh_account() && $this->is_wpmu_hosting(); } /** * Check if a site from 3rd party hosting is connected to The Free HUB. * * @return bool * @since 3.6.0 */ public function is_another_hosted_site_connected_to_tfh(): bool { return $this->is_tfh_account() && ! $this->is_wpmu_hosting(); } /** * Build notification hub data. * * @return array */ protected function build_quarantined_files_hub_data(): array { if ( ! class_exists( 'WP_Defender\Component\Quarantine' ) ) { return array(); } return wd_di()->get( Quarantine::class )->hub_list(); } /** * Schedule Hub Synchronization event. */ public function schedule_hub_sync(): void { if ( ! wp_next_scheduled( 'defender_hub_sync' ) ) { wp_schedule_single_event( time(), 'defender_hub_sync' ); } } /** * Returns the signup url. * If Dashboard plugin is active the signup url returned will be the Dashboard signup page. Else Hub signup page. * * @return string */ public function signup_url(): string { if ( class_exists( 'WPMUDEV_Dashboard' ) && is_object( WPMUDEV_Dashboard::$api ) ) { return add_query_arg( array( 'page' => 'wpmudev' ), is_multisite() ? network_admin_url() : get_admin_url() ); } return $this->hub_signup_url(); } /** * Returns the hub's signup url. * * @return string */ public function hub_signup_url(): string { return $this->get_api_base_url() . 'register/?signup=defender&defender_url=' . site_url(); } }
| ver. 1.4 |
Github
|
.
| PHP 8.0.30 | Generation time: 0 |
proxy
|
phpinfo
|
Settings