Your IP : 216.73.216.44


Current Path : /home/k/r/o/krobertfnz/www/wp-content/plugins/wp-defender/src/behavior/scan/
Upload File :
Current File : /home/k/r/o/krobertfnz/www/wp-content/plugins/wp-defender/src/behavior/scan/known-vulnerability.php

<?php

namespace WP_Defender\Behavior\Scan;

use Calotes\Base\Component;
use WP_Defender\Behavior\WPMUDEV;
use WP_Defender\Model\Scan;
use WP_Defender\Model\Scan_Item;
use WP_Defender\Traits\IO;
use WP_Defender\Traits\Plugin;
use WP_Defender\Traits\Theme;

class Known_Vulnerability extends Component {
	use IO, Plugin, Theme;

	/**
	 * @var WPMUDEV
	 */
	private $wpmudev;

	/**
	 * @var Scan
	 */
	private $scan;

	public function __construct( WPMUDEV $wpmudev, Scan $scan ) {
		$this->wpmudev = $wpmudev;
		$this->scan = $scan;
	}

	public function vuln_check(): bool {
		global $wp_version;
		$info_cached = [];
		$data = [
			'plugins' => json_encode( $this->gather_fact_plugins( $info_cached ) ),
			'themes' => json_encode( $this->gather_fact_themes( $info_cached ) ),
			'wordpress' => $wp_version,
		];

		$ret = $this->make_check( $data );
		if ( is_wp_error( $ret ) ) {
			$this->log( $ret->get_error_message(), 'scan.log' );
			$this->scan->status = Scan::STATUS_ERROR;
			$this->scan->save();

			return true;
		}
		// Get ignored issues.
		$last = Scan::get_last();
		if ( is_object( $last ) ) {
			$ignored_issues = $last->get_issues( Scan_Item::TYPE_VULNERABILITY, Scan_Item::STATUS_IGNORE );
		} else {
			$ignored_issues = [];
		}
		$this->process_result( $ret['plugins'], $info_cached, 'plugin', $ignored_issues );
		$this->process_result( $ret['themes'], $info_cached, 'theme', $ignored_issues );
		$this->process_result( $ret['wordpress'], [], 'wp_core', $ignored_issues );
		$this->scan->calculate_percent( 100, 5 );

		if ( ! empty( $ignored_issues ) ) {
			foreach ( $ignored_issues as $issue ) {
				$this->scan->add_item( Scan_Item::TYPE_VULNERABILITY, $issue->raw_data, Scan_Item::STATUS_IGNORE );
			}
		}

		return true;
	}

	/**
	 * @param $data
	 *
	 * @return mixed
	 */
	public function make_check( $data ) {
		return $this->wpmudev->make_wpmu_request(
			WPMUDEV::API_SCAN_KNOWN_VULN, $data, [
				'method' => 'POST',
			]
		);
	}

	/**
	 * @param mixed  $result
	 * @param array  $info
	 * @param string $type
	 * @param array  $ignored_issues
	 */
	private function process_result( $result, $info, $type, $ignored_issues ) {
		if ( empty( $result ) ) {
			return;
		}
		$this->log( sprintf( 'Checking %s:', $type ) );
		$model = $this->scan;

		foreach ( $result as $base_slug => $bugs ) {
			// Case with WP Core.
			if ( 'wp_core' === $type ) {
				global $wp_version;
				$is_exist = false;
				if ( ! empty( $ignored_issues ) ) {
					// Stop if we already have it in the ignored list.
					foreach ( $ignored_issues as $issue ) {
						if ( $wp_version === $issue->raw_data['version'] ) {
							$is_exist = true;
						}
					}
				}
				// Prepare data for saving if it was not before.
				if ( ! $is_exist ) {
					$raw_data = [
						'type' => $type,
						'slug' => '',
						'base_slug' => '',
						'version' => $wp_version,
						'name' => 'WordPress Core',
						'bugs' => [
							[
								'vuln_type' => $bugs['vuln_type'],
								'title' => $bugs['title'],
								'ref' => $bugs['references'],
								'fixed_in' => $bugs['fixed_in'],
								'cvss_score' => $bugs['cvss']['score'] ?? '',
							],
						],
						'new_structure' => '3.4.0',
					];
					// Save it.
					$model->add_item( Scan_Item::TYPE_VULNERABILITY, $raw_data );
				}
			} elseif ( 'plugin' === $type || 'theme' === $type ) {
				// Case with WP plugin or theme.
				if ( empty( $info[ $base_slug ] ) ) {
					continue;
				}
				[ $name, $current_version, $slug ] = $info[ $base_slug ];
				$raw_data = [
					'type' => $type,
					'slug' => $slug,
					'base_slug' => $base_slug,
					'version' => $current_version,
					'name' => $name,
					'bugs' => [],
				];
				if ( isset( $bugs['confirmed'] ) &&
					( is_array( $bugs['confirmed'] ) || $bugs['confirmed'] instanceof \Countable ? count( $bugs['confirmed'] ) : 0 )
				) {
					// Do not save if the current plugin is not from wp.org, and we have bugs for plugin from wp.org.
					if (
						! $this->is_likely_wporg_slug( $base_slug ) &&
						isset( $is_wp_org_plugin['success'] ) &&
						$is_wp_org_plugin['success']
					) {
						continue;
					}

					$confirmed_bugs = (array) $bugs['confirmed'];
					// @since 3.4.0 Restructure the view in relation to the new CVSS Score field.
					$raw_data['new_structure'] = '3.4.0';
					$this->log( sprintf( '%s has %d known bugs', $slug, count( $confirmed_bugs ) ) );
					foreach ( $confirmed_bugs as $bug ) {
						$raw_data['bugs'][] = [
							'vuln_type' => $bug['vuln_type'],
							'title' => $bug['title'],
							'ref' => $bug['references'],
							'fixed_in' => $bug['fixed_in'],
							'cvss_score' => $bug['cvss']['score'] ?? '',
						];
					}

					$model->add_item( Scan_Item::TYPE_VULNERABILITY, $raw_data );
				}
			}
		}
	}

	/**
	 * Get all the plugins install on this site, no matter the plugin status.
	 *
	 * @param $info_cached
	 *
	 * @return array
	 */
	private function gather_fact_plugins( &$info_cached ): array {
		$plugins = [];
		$model = Scan::get_last();
		foreach ( $this->get_plugins() as $slug => $plugin ) {
			if ( is_object( $model ) && $model->is_issue_ignored( $slug ) ) {
				continue;
			}
			// DIRECTORY_SEPARATOR won't work on Windows OS.
			$base_slug = explode( '/', $slug );
			$base_slug = array_shift( $base_slug );
			$plugins[ $base_slug ] = $plugin['Version'];
			$info_cached[ $base_slug ] = [ $plugin['Name'], $plugin['Version'], $slug ];
		}

		return $plugins;
	}

	/**
	 * @param $info_cached
	 *
	 * @return array
	 */
	private function gather_fact_themes( &$info_cached ): array {
		$themes = [];
		$model = Scan::get_last();
		foreach ( $this->get_themes() as $theme ) {
			if ( is_object( $theme->parent() ) ) {
				continue;
			}
			if ( is_object( $model ) && $model->is_issue_ignored( $theme->get_template() ) ) {
				continue;
			}
			$themes[ $theme->get_template() ] = $theme->Version;
			$info_cached[ $theme->get_template() ] = [ $theme->Name, $theme->Version, $theme->get_template() ];
		}

		return $themes;
	}
}