245 lines
4.8 KiB
PHP
245 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace WPScan\Checks;
|
|
|
|
// Exit if accessed directly.
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
/**
|
|
* Security Checks.
|
|
*
|
|
* Handles the security checks system.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
abstract class Check {
|
|
/**
|
|
* A list of identified vulnerabilities for this check.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @var array|null
|
|
*/
|
|
public $vulnerabilities;
|
|
|
|
/**
|
|
* Actions list.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @var array|null
|
|
*/
|
|
public $actions = array();
|
|
|
|
/**
|
|
* Class constructor.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $id id.
|
|
* @param string $dir dir.
|
|
* @param string $parent parent.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public final function __construct( $id, $dir, $parent ) {
|
|
$this->id = $id;
|
|
$this->dir = $dir;
|
|
$this->parent = $parent;
|
|
|
|
$count = $this->get_vulnerabilities_count();
|
|
|
|
$this->actions[] = array(
|
|
'id' => 'run',
|
|
'title' => __( 'Run', 'wpscan' ),
|
|
'method' => 'run',
|
|
);
|
|
|
|
if ( $count > 0 ) {
|
|
$this->actions[] = array(
|
|
'id' => 'dismiss',
|
|
'title' => __( 'Dismiss', 'wpscan' ),
|
|
'method' => 'dismiss',
|
|
'confirm' => true,
|
|
);
|
|
}
|
|
|
|
if ( method_exists( $this, 'init' ) ) {
|
|
$this->init();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check title.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
abstract public function title();
|
|
|
|
/**
|
|
* Check description.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
abstract public function description();
|
|
|
|
/**
|
|
* Success message.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
abstract public function success_message();
|
|
|
|
/**
|
|
* Add vulnerability
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $title The vulnerability title.
|
|
* @param string $severity The severity, can be critical, high, medium, low and info.
|
|
* @param string $id Unique string to represent the vulnerability in the report object.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
final public function add_vulnerability( $title, $severity, $id, $remediation_url ) {
|
|
$vulnerability = array(
|
|
'title' => $title,
|
|
'severity' => $severity,
|
|
'id' => $id,
|
|
'remediation_url' => $remediation_url,
|
|
);
|
|
|
|
$this->vulnerabilities[] = $vulnerability;
|
|
}
|
|
|
|
/**
|
|
* Get vulnerabilities.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @return array|null
|
|
*/
|
|
final public function get_vulnerabilities() {
|
|
if ( ! empty( $this->vulnerabilities ) ) {
|
|
return $this->vulnerabilities;
|
|
}
|
|
|
|
$report = $this->parent->get_report();
|
|
|
|
if ( isset( $report['security-checks'] ) ) {
|
|
if ( isset( $report['security-checks'][ $this->id ] ) ) {
|
|
return $report['security-checks'][ $this->id ]['vulnerabilities'];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get item non-ignored vulnerabilities count
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @access public
|
|
* @return int
|
|
*/
|
|
public function get_vulnerabilities_count() {
|
|
$vulnerabilities = $this->get_vulnerabilities();
|
|
$ignored = $this->parent->get_ignored_vulnerabilities();
|
|
|
|
if ( empty( $vulnerabilities ) ) {
|
|
return 0;
|
|
}
|
|
|
|
foreach ( $vulnerabilities as $key => &$item ) {
|
|
if ( in_array( $item['id'], $ignored, true ) ) {
|
|
unset( $vulnerabilities[ $key ] );
|
|
}
|
|
}
|
|
|
|
return count( $vulnerabilities );
|
|
}
|
|
|
|
/**
|
|
* Dismiss action
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
public function dismiss() {
|
|
$report = $this->parent->get_report();
|
|
$updated = $report;
|
|
|
|
if ( isset( $updated['security-checks'] ) ) {
|
|
if ( isset( $updated['security-checks'][ $this->id ] ) ) {
|
|
$updated['security-checks'][ $this->id ]['vulnerabilities'] = array();
|
|
}
|
|
}
|
|
|
|
if ( $report === $updated ) {
|
|
return true;
|
|
} else {
|
|
return update_option( $this->parent->OPT_REPORT, $updated );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run action.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
public function run() {
|
|
$report = $this->parent->get_report();
|
|
$updated = $report;
|
|
|
|
if ( empty( $updated ) ) {
|
|
$updated = array(
|
|
'security-checks' => array(),
|
|
'plugins' => array(),
|
|
'themes' => array(),
|
|
'wordpress' => array(),
|
|
);
|
|
}
|
|
|
|
if ( isset( $updated['security-checks'][ $this->id ] ) ) {
|
|
$updated['security-checks'][ $this->id ] = array();
|
|
}
|
|
|
|
$this->perform();
|
|
|
|
if ( is_array( $this->vulnerabilities ) ) {
|
|
$updated['security-checks'][ $this->id ]['vulnerabilities'] = $this->vulnerabilities;
|
|
|
|
$this->parent->maybe_fire_issue_found_action('security-check', $this->id, $updated['security-checks'][ $this->id ]);
|
|
} else {
|
|
$updated['security-checks'][ $this->id ]['vulnerabilities'] = array();
|
|
}
|
|
|
|
if ( $report === $updated ) {
|
|
return true;
|
|
} else {
|
|
return update_option( $this->parent->OPT_REPORT, $updated );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Perform the check and save the results.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
abstract public function perform();
|
|
}
|