646 lines
29 KiB
PHP
646 lines
29 KiB
PHP
<?php
|
|
/**
|
|
* WPVulnerability REST API Endpoints
|
|
*
|
|
* @package WPVulnerability
|
|
*
|
|
* @since 3.3.0
|
|
*/
|
|
|
|
defined( 'ABSPATH' ) || die( 'No script kiddies please!' );
|
|
|
|
/**
|
|
* Handle the core vulnerabilities REST API request.
|
|
*
|
|
* This function handles the request for retrieving core vulnerabilities.
|
|
* It includes the necessary files and fetches the vulnerabilities data.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @return WP_REST_Response Core vulnerabilities data or a message if none found.
|
|
*/
|
|
function wpvulnerability_rest_core_vulnerabilities() {
|
|
// Include the files containing the functions to get core vulnerabilities.
|
|
require_once WPVULNERABILITY_PLUGIN_PATH . '/wpvulnerability-general.php';
|
|
require_once WPVULNERABILITY_PLUGIN_PATH . '/wpvulnerability-core.php';
|
|
|
|
// Get the core vulnerabilities.
|
|
$core_vulnerabilities = wpvulnerability_core_get_vulnerabilities();
|
|
|
|
$core_complete = array();
|
|
|
|
// Check if vulnerabilities are found and is an array.
|
|
if ( $core_vulnerabilities ) {
|
|
// Loop through each core vulnerability.
|
|
foreach ( $core_vulnerabilities as $vulnerability ) {
|
|
if ( ! is_array( $vulnerability ) ) {
|
|
continue; }
|
|
$vuln_impact = isset( $vulnerability['impact'] ) && is_array( $vulnerability['impact'] ) ? $vulnerability['impact'] : array();
|
|
$vuln_cvss = isset( $vuln_impact['cvss'] ) && is_array( $vuln_impact['cvss'] ) ? $vuln_impact['cvss'] : array();
|
|
$vuln_cvss3 = isset( $vuln_impact['cvss3'] ) && is_array( $vuln_impact['cvss3'] ) ? $vuln_impact['cvss3'] : array();
|
|
$vuln_ssvc = isset( $vuln_impact['ssvc'] ) && is_array( $vuln_impact['ssvc'] ) ? $vuln_impact['ssvc'] : array();
|
|
$vuln_cwe = isset( $vuln_impact['cwe'] ) && is_array( $vuln_impact['cwe'] ) ? $vuln_impact['cwe'] : array();
|
|
$vuln_sources = isset( $vulnerability['source'] ) && is_array( $vulnerability['source'] ) ? $vulnerability['source'] : array();
|
|
|
|
$core_complete_temp = array();
|
|
|
|
// UUID — unique vulnerability identifier.
|
|
$core_complete_temp['uuid'] = is_scalar( $vulnerability['uuid'] ?? '' ) ? (string) ( $vulnerability['uuid'] ?? '' ) : '';
|
|
|
|
// Process vulnerability version.
|
|
$core_complete_temp['version'] = trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability['name'] ?? null ) ? (string) $vulnerability['name'] : '' ), 'strip' ) ) );
|
|
|
|
// Process vulnerability severity — prefer cvss3 full-word value.
|
|
$cvss3_sev_raw = isset( $vuln_cvss3['severity'] ) ? $vuln_cvss3['severity'] : null;
|
|
$cvss3_sev = is_string( $cvss3_sev_raw ) && '' !== $cvss3_sev_raw ? $cvss3_sev_raw : null;
|
|
$cvss_sev = isset( $vuln_cvss['severity'] ) && is_scalar( $vuln_cvss['severity'] ) ? (string) $vuln_cvss['severity'] : null;
|
|
$sev_input = null !== $cvss3_sev ? $cvss3_sev : $cvss_sev;
|
|
$core_complete_temp['severity'] = null !== $sev_input ? wpvulnerability_severity( $sev_input ) : null;
|
|
|
|
// KEV flag — Known Exploited Vulnerability (CISA KEV catalog).
|
|
$core_complete_temp['kev'] = isset( $vuln_ssvc['kev'] ) && true === $vuln_ssvc['kev'];
|
|
|
|
// SSVC block.
|
|
if ( ! empty( $vuln_ssvc ) ) {
|
|
$core_complete_temp['ssvc'] = array(
|
|
'exploitation' => is_scalar( $vuln_ssvc['exploitation'] ?? '' ) ? (string) ( $vuln_ssvc['exploitation'] ?? '' ) : '',
|
|
'automatable' => is_scalar( $vuln_ssvc['automatable'] ?? '' ) ? (string) ( $vuln_ssvc['automatable'] ?? '' ) : '',
|
|
'technical_impact' => is_scalar( $vuln_ssvc['technical_impact'] ?? '' ) ? (string) ( $vuln_ssvc['technical_impact'] ?? '' ) : '',
|
|
);
|
|
} else {
|
|
$core_complete_temp['ssvc'] = null;
|
|
}
|
|
|
|
// Process CWE details.
|
|
$core_complete_temp['cwe'] = array();
|
|
foreach ( $vuln_cwe as $vulnerability_cwe ) {
|
|
if ( ! is_array( $vulnerability_cwe ) ) {
|
|
continue; }
|
|
$core_complete_temp['cwe'][] = array(
|
|
'name' => trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability_cwe['name'] ?? null ) ? (string) $vulnerability_cwe['name'] : '' ), 'strip' ) ) ),
|
|
'description' => trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability_cwe['description'] ?? null ) ? (string) $vulnerability_cwe['description'] : '' ), 'strip' ) ) ),
|
|
);
|
|
}
|
|
|
|
// Process CVSS score.
|
|
$core_complete_temp['score'] = isset( $vuln_cvss['score'] ) ? number_format( is_scalar( $vuln_cvss['score'] ) ? (float) $vuln_cvss['score'] : 0.0, 1, '.', '' ) : null;
|
|
|
|
// Process vulnerability sources.
|
|
$core_complete_temp['source'] = array();
|
|
foreach ( $vuln_sources as $vulnerability_source ) {
|
|
if ( ! is_array( $vulnerability_source ) ) {
|
|
continue; }
|
|
$core_complete_temp['source'][] = array(
|
|
'name' => trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability_source['name'] ?? null ) ? (string) $vulnerability_source['name'] : '' ), 'strip' ) ) ),
|
|
'link' => esc_url_raw( ( is_scalar( $vulnerability_source['link'] ?? null ) ? (string) $vulnerability_source['link'] : '' ) ),
|
|
'description' => trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability_source['description'] ?? null ) ? (string) $vulnerability_source['description'] : '' ), 'strip' ) ) ),
|
|
'date' => is_scalar( $vulnerability_source['date'] ?? '' ) ? (string) ( $vulnerability_source['date'] ?? '' ) : '',
|
|
);
|
|
}
|
|
|
|
$core_complete[] = $core_complete_temp;
|
|
unset( $core_complete_temp );
|
|
}
|
|
}
|
|
|
|
// Return the vulnerabilities in the response.
|
|
return new WP_REST_Response( $core_complete, 200 );
|
|
}
|
|
|
|
/**
|
|
* Handle the plugins vulnerabilities REST API request.
|
|
*
|
|
* This function handles the request for retrieving plugins vulnerabilities.
|
|
* It includes the necessary files and fetches the vulnerabilities data.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @return WP_REST_Response Plugins vulnerabilities data or a message if none found.
|
|
*/
|
|
function wpvulnerability_rest_plugins_vulnerabilities() {
|
|
// Include the files containing the functions to get plugins vulnerabilities.
|
|
require_once WPVULNERABILITY_PLUGIN_PATH . '/wpvulnerability-general.php';
|
|
require_once WPVULNERABILITY_PLUGIN_PATH . '/wpvulnerability-plugins.php';
|
|
|
|
// Get the plugins vulnerabilities.
|
|
$plugins_vulnerabilities = wpvulnerability_plugin_get_vulnerabilities();
|
|
|
|
$plugins_complete = array();
|
|
|
|
// Loop through each plugin vulnerability.
|
|
foreach ( $plugins_vulnerabilities as $plugin ) {
|
|
if ( ! is_array( $plugin ) ) {
|
|
continue; }
|
|
// Check if the plugin is vulnerable.
|
|
if ( 1 === ( is_scalar( $plugin['vulnerable'] ?? null ) ? (int) $plugin['vulnerable'] : 0 ) ) {
|
|
$plugins_complete_temp = array();
|
|
|
|
// Process plugin name and slug.
|
|
$plugins_complete_temp['name'] = trim( html_entity_decode( wp_kses( ( is_scalar( $plugin['Name'] ?? null ) ? (string) $plugin['Name'] : '' ), 'strip' ) ) );
|
|
$plugins_complete_temp['slug'] = trim( html_entity_decode( wp_kses( ( is_scalar( $plugin['slug'] ?? null ) ? (string) $plugin['slug'] : '' ), 'strip' ) ) );
|
|
|
|
// Prepare the vulnerabilities array for output.
|
|
$p_vulns = isset( $plugin['vulnerabilities'] ) && is_array( $plugin['vulnerabilities'] ) ? $plugin['vulnerabilities'] : array();
|
|
foreach ( $p_vulns as $vulnerability ) {
|
|
if ( ! is_array( $vulnerability ) ) {
|
|
continue; }
|
|
$vuln_impact = isset( $vulnerability['impact'] ) && is_array( $vulnerability['impact'] ) ? $vulnerability['impact'] : array();
|
|
$vuln_cvss = isset( $vuln_impact['cvss'] ) && is_array( $vuln_impact['cvss'] ) ? $vuln_impact['cvss'] : array();
|
|
$vuln_cvss3 = isset( $vuln_impact['cvss3'] ) && is_array( $vuln_impact['cvss3'] ) ? $vuln_impact['cvss3'] : array();
|
|
$vuln_ssvc = isset( $vuln_impact['ssvc'] ) && is_array( $vuln_impact['ssvc'] ) ? $vuln_impact['ssvc'] : array();
|
|
$vuln_cwe = isset( $vuln_impact['cwe'] ) && is_array( $vuln_impact['cwe'] ) ? $vuln_impact['cwe'] : array();
|
|
$vuln_sources = isset( $vulnerability['source'] ) && is_array( $vulnerability['source'] ) ? $vulnerability['source'] : array();
|
|
|
|
$plugins_complete_temp_vulnerabilities = array();
|
|
|
|
// UUID — unique vulnerability identifier.
|
|
$plugins_complete_temp_vulnerabilities['uuid'] = is_scalar( $vulnerability['uuid'] ?? '' ) ? (string) ( $vulnerability['uuid'] ?? '' ) : '';
|
|
|
|
// Process vulnerability severity — prefer cvss3 full-word value.
|
|
$cvss3_sev_raw = isset( $vuln_cvss3['severity'] ) ? $vuln_cvss3['severity'] : null;
|
|
$cvss3_sev = is_string( $cvss3_sev_raw ) && '' !== $cvss3_sev_raw ? $cvss3_sev_raw : null;
|
|
$cvss_sev = isset( $vuln_cvss['severity'] ) && is_scalar( $vuln_cvss['severity'] ) ? (string) $vuln_cvss['severity'] : null;
|
|
$sev_input = null !== $cvss3_sev ? $cvss3_sev : $cvss_sev;
|
|
$plugins_complete_temp_vulnerabilities['severity'] = null !== $sev_input ? wpvulnerability_severity( $sev_input ) : null;
|
|
|
|
// KEV flag — Known Exploited Vulnerability (CISA KEV catalog).
|
|
$plugins_complete_temp_vulnerabilities['kev'] = isset( $vuln_ssvc['kev'] ) && true === $vuln_ssvc['kev'];
|
|
|
|
// SSVC block.
|
|
if ( ! empty( $vuln_ssvc ) ) {
|
|
$plugins_complete_temp_vulnerabilities['ssvc'] = array(
|
|
'exploitation' => is_scalar( $vuln_ssvc['exploitation'] ?? '' ) ? (string) ( $vuln_ssvc['exploitation'] ?? '' ) : '',
|
|
'automatable' => is_scalar( $vuln_ssvc['automatable'] ?? '' ) ? (string) ( $vuln_ssvc['automatable'] ?? '' ) : '',
|
|
'technical_impact' => is_scalar( $vuln_ssvc['technical_impact'] ?? '' ) ? (string) ( $vuln_ssvc['technical_impact'] ?? '' ) : '',
|
|
);
|
|
} else {
|
|
$plugins_complete_temp_vulnerabilities['ssvc'] = null;
|
|
}
|
|
|
|
// Process vulnerability details.
|
|
$plugins_complete_temp_vulnerabilities['version'] = trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability['version'] ?? null ) ? (string) $vulnerability['version'] : '' ), 'strip' ) ) );
|
|
$plugins_complete_temp_vulnerabilities['affected'] = trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability['versions'] ?? null ) ? (string) $vulnerability['versions'] : '' ), 'strip' ) ) );
|
|
$plugins_complete_temp_vulnerabilities['name'] = trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability['name'] ?? null ) ? (string) $vulnerability['name'] : '' ), 'strip' ) ) );
|
|
$plugins_complete_temp_vulnerabilities['closed'] = is_numeric( $vulnerability['closed'] ?? 0 ) ? (int) ( $vulnerability['closed'] ?? 0 ) : 0;
|
|
$plugins_complete_temp_vulnerabilities['unfixed'] = is_numeric( $vulnerability['unfixed'] ?? 0 ) ? (int) ( $vulnerability['unfixed'] ?? 0 ) : 0;
|
|
|
|
// Process CWE details.
|
|
$plugins_complete_temp_vulnerabilities['cwe'] = array();
|
|
foreach ( $vuln_cwe as $vulnerability_cwe ) {
|
|
if ( ! is_array( $vulnerability_cwe ) ) {
|
|
continue; }
|
|
$plugins_complete_temp_vulnerabilities['cwe'][] = array(
|
|
'name' => trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability_cwe['name'] ?? null ) ? (string) $vulnerability_cwe['name'] : '' ), 'strip' ) ) ),
|
|
'description' => trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability_cwe['description'] ?? null ) ? (string) $vulnerability_cwe['description'] : '' ), 'strip' ) ) ),
|
|
);
|
|
}
|
|
|
|
// Process CVSS score.
|
|
$plugins_complete_temp_vulnerabilities['score'] = isset( $vuln_cvss['score'] ) ? number_format( is_scalar( $vuln_cvss['score'] ) ? (float) $vuln_cvss['score'] : 0.0, 1, '.', '' ) : null;
|
|
|
|
// Process vulnerability sources.
|
|
$plugins_complete_temp_vulnerabilities['source'] = array();
|
|
foreach ( $vuln_sources as $vulnerability_source ) {
|
|
if ( ! is_array( $vulnerability_source ) ) {
|
|
continue; }
|
|
$plugins_complete_temp_vulnerabilities['source'][] = array(
|
|
'name' => trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability_source['name'] ?? null ) ? (string) $vulnerability_source['name'] : '' ), 'strip' ) ) ),
|
|
'link' => esc_url_raw( ( is_scalar( $vulnerability_source['link'] ?? null ) ? (string) $vulnerability_source['link'] : '' ) ),
|
|
'date' => is_scalar( $vulnerability_source['date'] ?? '' ) ? (string) ( $vulnerability_source['date'] ?? '' ) : '',
|
|
);
|
|
}
|
|
|
|
// Add processed vulnerability to the temporary array.
|
|
$plugins_complete_temp['vulnerabilities'][] = $plugins_complete_temp_vulnerabilities;
|
|
}
|
|
|
|
// Add processed plugin data to the complete array.
|
|
$plugins_complete[] = $plugins_complete_temp;
|
|
}
|
|
}
|
|
|
|
// Return the vulnerabilities in the response.
|
|
return new WP_REST_Response( $plugins_complete, 200 );
|
|
}
|
|
|
|
/**
|
|
* Handle the themes vulnerabilities REST API request.
|
|
*
|
|
* This function handles the request for retrieving themes vulnerabilities.
|
|
* It includes the necessary files and fetches the vulnerabilities data.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @return WP_REST_Response Themes vulnerabilities data or a message if none found.
|
|
*/
|
|
function wpvulnerability_rest_themes_vulnerabilities() {
|
|
// Include the file containing the function to get themes vulnerabilities.
|
|
require_once WPVULNERABILITY_PLUGIN_PATH . '/wpvulnerability-general.php';
|
|
require_once WPVULNERABILITY_PLUGIN_PATH . '/wpvulnerability-themes.php';
|
|
|
|
// Get the themes vulnerabilities.
|
|
$themes_vulnerabilities = wpvulnerability_theme_get_vulnerabilities();
|
|
|
|
$themes_complete = array();
|
|
|
|
// Loop through each theme vulnerability.
|
|
foreach ( $themes_vulnerabilities as $theme ) {
|
|
if ( ! is_array( $theme ) ) {
|
|
continue;
|
|
}
|
|
$theme_wpv = isset( $theme['wpvulnerability'] ) && is_array( $theme['wpvulnerability'] ) ? $theme['wpvulnerability'] : array();
|
|
// Check if the theme is vulnerable.
|
|
if ( 1 === ( is_numeric( $theme_wpv['vulnerable'] ?? 0 ) ? (int) ( $theme_wpv['vulnerable'] ?? 0 ) : 0 ) ) {
|
|
$themes_complete_temp = array();
|
|
|
|
// Process theme name and slug.
|
|
$themes_complete_temp['name'] = trim( html_entity_decode( wp_kses( ( is_scalar( $theme_wpv['name'] ?? null ) ? (string) $theme_wpv['name'] : '' ), 'strip' ) ) );
|
|
$themes_complete_temp['slug'] = trim( html_entity_decode( wp_kses( ( is_scalar( $theme_wpv['slug'] ?? null ) ? (string) $theme_wpv['slug'] : '' ), 'strip' ) ) );
|
|
|
|
// Prepare the vulnerabilities array for output.
|
|
$theme_vulns = isset( $theme_wpv['vulnerabilities'] ) && is_array( $theme_wpv['vulnerabilities'] ) ? $theme_wpv['vulnerabilities'] : array();
|
|
foreach ( $theme_vulns as $vulnerability ) {
|
|
if ( ! is_array( $vulnerability ) ) {
|
|
continue; }
|
|
$vuln_impact = isset( $vulnerability['impact'] ) && is_array( $vulnerability['impact'] ) ? $vulnerability['impact'] : array();
|
|
$vuln_cvss = isset( $vuln_impact['cvss'] ) && is_array( $vuln_impact['cvss'] ) ? $vuln_impact['cvss'] : array();
|
|
$vuln_cvss3 = isset( $vuln_impact['cvss3'] ) && is_array( $vuln_impact['cvss3'] ) ? $vuln_impact['cvss3'] : array();
|
|
$vuln_ssvc = isset( $vuln_impact['ssvc'] ) && is_array( $vuln_impact['ssvc'] ) ? $vuln_impact['ssvc'] : array();
|
|
$vuln_cwe = isset( $vuln_impact['cwe'] ) && is_array( $vuln_impact['cwe'] ) ? $vuln_impact['cwe'] : array();
|
|
$vuln_sources = isset( $vulnerability['source'] ) && is_array( $vulnerability['source'] ) ? $vulnerability['source'] : array();
|
|
|
|
$themes_complete_temp_vulnerabilities = array();
|
|
|
|
// UUID — unique vulnerability identifier.
|
|
$themes_complete_temp_vulnerabilities['uuid'] = is_scalar( $vulnerability['uuid'] ?? '' ) ? (string) ( $vulnerability['uuid'] ?? '' ) : '';
|
|
|
|
// Process vulnerability severity — prefer cvss3 full-word value.
|
|
$cvss3_sev_raw = isset( $vuln_cvss3['severity'] ) ? $vuln_cvss3['severity'] : null;
|
|
$cvss3_sev = is_string( $cvss3_sev_raw ) && '' !== $cvss3_sev_raw ? $cvss3_sev_raw : null;
|
|
$cvss_sev = isset( $vuln_cvss['severity'] ) && is_scalar( $vuln_cvss['severity'] ) ? (string) $vuln_cvss['severity'] : null;
|
|
$sev_input = null !== $cvss3_sev ? $cvss3_sev : $cvss_sev;
|
|
$themes_complete_temp_vulnerabilities['severity'] = null !== $sev_input ? wpvulnerability_severity( $sev_input ) : null;
|
|
|
|
// KEV flag — Known Exploited Vulnerability (CISA KEV catalog).
|
|
$themes_complete_temp_vulnerabilities['kev'] = isset( $vuln_ssvc['kev'] ) && true === $vuln_ssvc['kev'];
|
|
|
|
// SSVC block.
|
|
if ( ! empty( $vuln_ssvc ) ) {
|
|
$themes_complete_temp_vulnerabilities['ssvc'] = array(
|
|
'exploitation' => is_scalar( $vuln_ssvc['exploitation'] ?? '' ) ? (string) ( $vuln_ssvc['exploitation'] ?? '' ) : '',
|
|
'automatable' => is_scalar( $vuln_ssvc['automatable'] ?? '' ) ? (string) ( $vuln_ssvc['automatable'] ?? '' ) : '',
|
|
'technical_impact' => is_scalar( $vuln_ssvc['technical_impact'] ?? '' ) ? (string) ( $vuln_ssvc['technical_impact'] ?? '' ) : '',
|
|
);
|
|
} else {
|
|
$themes_complete_temp_vulnerabilities['ssvc'] = null;
|
|
}
|
|
|
|
// Process vulnerability details.
|
|
$themes_complete_temp_vulnerabilities['version'] = trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability['version'] ?? null ) ? (string) $vulnerability['version'] : '' ), 'strip' ) ) );
|
|
$themes_complete_temp_vulnerabilities['affected'] = trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability['versions'] ?? null ) ? (string) $vulnerability['versions'] : '' ), 'strip' ) ) );
|
|
$themes_complete_temp_vulnerabilities['name'] = trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability['name'] ?? null ) ? (string) $vulnerability['name'] : '' ), 'strip' ) ) );
|
|
$themes_complete_temp_vulnerabilities['closed'] = ( is_scalar( $vulnerability['closed'] ?? null ) ? (int) $vulnerability['closed'] : 0 );
|
|
$themes_complete_temp_vulnerabilities['unfixed'] = ( is_scalar( $vulnerability['unfixed'] ?? null ) ? (int) $vulnerability['unfixed'] : 0 );
|
|
|
|
// Process CWE details.
|
|
$themes_complete_temp_vulnerabilities['cwe'] = array();
|
|
foreach ( $vuln_cwe as $vulnerability_cwe ) {
|
|
if ( ! is_array( $vulnerability_cwe ) ) {
|
|
continue; }
|
|
$themes_complete_temp_vulnerabilities['cwe'][] = array(
|
|
'name' => trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability_cwe['name'] ?? null ) ? (string) $vulnerability_cwe['name'] : '' ), 'strip' ) ) ),
|
|
'description' => trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability_cwe['description'] ?? null ) ? (string) $vulnerability_cwe['description'] : '' ), 'strip' ) ) ),
|
|
);
|
|
}
|
|
|
|
// Process CVSS score.
|
|
$themes_complete_temp_vulnerabilities['score'] = isset( $vuln_cvss['score'] ) ? number_format( is_scalar( $vuln_cvss['score'] ) ? (float) $vuln_cvss['score'] : 0.0, 1, '.', '' ) : null;
|
|
|
|
// Process vulnerability sources.
|
|
$themes_complete_temp_vulnerabilities['source'] = array();
|
|
foreach ( $vuln_sources as $vulnerability_source ) {
|
|
if ( ! is_array( $vulnerability_source ) ) {
|
|
continue; }
|
|
$themes_complete_temp_vulnerabilities['source'][] = array(
|
|
'name' => trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability_source['name'] ?? null ) ? (string) $vulnerability_source['name'] : '' ), 'strip' ) ) ),
|
|
'link' => esc_url_raw( ( is_scalar( $vulnerability_source['link'] ?? null ) ? (string) $vulnerability_source['link'] : '' ) ),
|
|
'date' => is_scalar( $vulnerability_source['date'] ?? '' ) ? (string) ( $vulnerability_source['date'] ?? '' ) : '',
|
|
);
|
|
}
|
|
|
|
// Add processed vulnerability to the temporary array.
|
|
$themes_complete_temp['vulnerabilities'][] = $themes_complete_temp_vulnerabilities;
|
|
}
|
|
|
|
// Add processed theme data to the complete array.
|
|
$themes_complete[] = $themes_complete_temp;
|
|
}
|
|
}
|
|
|
|
// Return the vulnerabilities in the response.
|
|
return new WP_REST_Response( $themes_complete, 200 );
|
|
}
|
|
|
|
/**
|
|
* Handle vulnerabilities REST API request for different software types.
|
|
*
|
|
* This function processes the request to retrieve vulnerabilities for the specified software type.
|
|
* It loads the necessary files and fetches the vulnerability data, then returns the data in a structured format.
|
|
*
|
|
* @since 3.5.0
|
|
*
|
|
* @param string $software_type The type of software to retrieve vulnerabilities for.
|
|
* @return WP_REST_Response The vulnerabilities data or an empty array if none found.
|
|
*/
|
|
function wpvulnerability_rest_software_vulnerabilities( $software_type ) {
|
|
// Include the general file for retrieving vulnerabilities.
|
|
require_once WPVULNERABILITY_PLUGIN_PATH . '/wpvulnerability-general.php';
|
|
require_once WPVULNERABILITY_PLUGIN_PATH . '/wpvulnerability-software.php';
|
|
|
|
// Get vulnerabilities based on the software type.
|
|
$software_data = array();
|
|
$vulnerabilities = array();
|
|
switch ( $software_type ) {
|
|
case 'php':
|
|
case 'apache':
|
|
case 'nginx':
|
|
case 'mariadb':
|
|
case 'mysql':
|
|
case 'imagemagick':
|
|
case 'curl':
|
|
case 'memcached':
|
|
case 'redis':
|
|
case 'sqlite':
|
|
$software_data = wpvulnerability_software_get_vulnerabilities( $software_type );
|
|
if ( is_array( $software_data ) && isset( $software_data['vulnerabilities'] ) && is_array( $software_data['vulnerabilities'] ) ) {
|
|
$vulnerabilities = $software_data['vulnerabilities'];
|
|
}
|
|
break;
|
|
default:
|
|
return new WP_REST_Response( array(), 400 ); // Invalid software type.
|
|
}
|
|
|
|
$complete_vulnerabilities = array();
|
|
|
|
// Process each vulnerability.
|
|
foreach ( $vulnerabilities as $vulnerability ) {
|
|
if ( ! is_array( $vulnerability ) ) {
|
|
continue; }
|
|
$sw_sources = isset( $vulnerability['source'] ) && is_array( $vulnerability['source'] ) ? $vulnerability['source'] : array();
|
|
$sw_impact = isset( $vulnerability['impact'] ) && is_array( $vulnerability['impact'] ) ? $vulnerability['impact'] : array();
|
|
$sw_cvss3 = isset( $sw_impact['cvss3'] ) && is_array( $sw_impact['cvss3'] ) ? $sw_impact['cvss3'] : array();
|
|
$raw_unfixed = $vulnerability['unfixed'] ?? 0;
|
|
|
|
$temp = array();
|
|
$temp['uuid'] = is_scalar( $vulnerability['uuid'] ?? '' ) ? (string) ( $vulnerability['uuid'] ?? '' ) : '';
|
|
|
|
// Severity from cvss3 if available.
|
|
$sw_cvss3_sev_raw = isset( $sw_cvss3['severity'] ) ? $sw_cvss3['severity'] : null;
|
|
$sw_cvss3_sev = is_string( $sw_cvss3_sev_raw ) && '' !== $sw_cvss3_sev_raw ? $sw_cvss3_sev_raw : null;
|
|
$temp['severity'] = null !== $sw_cvss3_sev ? wpvulnerability_severity( $sw_cvss3_sev ) : null;
|
|
|
|
// KEV flag — for software, kev is at impact level (not inside ssvc).
|
|
$temp['kev'] = isset( $sw_impact['kev'] ) && true === $sw_impact['kev'];
|
|
|
|
$temp['version'] = trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability['version'] ?? null ) ? (string) $vulnerability['version'] : '' ), 'strip' ) ) );
|
|
$temp['affected'] = trim( html_entity_decode( wp_kses( ( is_scalar( $vulnerability['versions'] ?? null ) ? (string) $vulnerability['versions'] : '' ), 'strip' ) ) );
|
|
$temp['unfixed'] = is_numeric( $raw_unfixed ) ? (int) $raw_unfixed : 0;
|
|
|
|
// Process vulnerability sources.
|
|
$temp['source'] = array();
|
|
foreach ( $sw_sources as $source ) {
|
|
if ( ! is_array( $source ) ) {
|
|
continue; }
|
|
$temp['source'][] = array(
|
|
'name' => trim( html_entity_decode( wp_kses( ( is_scalar( $source['id'] ?? null ) ? (string) $source['id'] : '' ), 'strip' ) ) ),
|
|
'description' => trim( html_entity_decode( wp_kses( ( is_scalar( $source['description'] ?? null ) ? (string) $source['description'] : '' ), 'strip' ) ) ),
|
|
'link' => esc_url_raw( ( is_scalar( $source['link'] ?? null ) ? (string) $source['link'] : '' ) ),
|
|
'date' => is_scalar( $source['date'] ?? '' ) ? (string) ( $source['date'] ?? '' ) : '',
|
|
);
|
|
}
|
|
|
|
// Add processed vulnerability to the complete array.
|
|
$complete_vulnerabilities[] = $temp;
|
|
}
|
|
|
|
// Return the vulnerabilities in the response.
|
|
return new WP_REST_Response( $complete_vulnerabilities, 200 );
|
|
}
|
|
|
|
/**
|
|
* Handle the PHP vulnerabilities REST API request.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @return WP_REST_Response PHP vulnerabilities data or a message if none found.
|
|
*/
|
|
function wpvulnerability_rest_php_vulnerabilities() {
|
|
return wpvulnerability_rest_software_vulnerabilities( 'php' );
|
|
}
|
|
|
|
/**
|
|
* Handle the Apache vulnerabilities REST API request.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @return WP_REST_Response Apache vulnerabilities data or a message if none found.
|
|
*/
|
|
function wpvulnerability_rest_apache_vulnerabilities() {
|
|
return wpvulnerability_rest_software_vulnerabilities( 'apache' );
|
|
}
|
|
|
|
/**
|
|
* Handle the Nginx vulnerabilities REST API request.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @return WP_REST_Response Nginx vulnerabilities data or a message if none found.
|
|
*/
|
|
function wpvulnerability_rest_nginx_vulnerabilities() {
|
|
return wpvulnerability_rest_software_vulnerabilities( 'nginx' );
|
|
}
|
|
|
|
/**
|
|
* Handle the MariaDB vulnerabilities REST API request.
|
|
*
|
|
* @since 3.4.0
|
|
*
|
|
* @return WP_REST_Response MariaDB vulnerabilities data or an empty array if none found.
|
|
*/
|
|
function wpvulnerability_rest_mariadb_vulnerabilities() {
|
|
return wpvulnerability_rest_software_vulnerabilities( 'mariadb' );
|
|
}
|
|
|
|
/**
|
|
* Handle the MySQL vulnerabilities REST API request.
|
|
*
|
|
* @since 3.4.0
|
|
*
|
|
* @return WP_REST_Response MySQL vulnerabilities data or an empty array if none found.
|
|
*/
|
|
function wpvulnerability_rest_mysql_vulnerabilities() {
|
|
return wpvulnerability_rest_software_vulnerabilities( 'mysql' );
|
|
}
|
|
|
|
/**
|
|
* Handle the ImageMagick vulnerabilities REST API request.
|
|
*
|
|
* @since 3.5.0
|
|
*
|
|
* @return WP_REST_Response ImageMagick vulnerabilities data or an empty array if none found.
|
|
*/
|
|
function wpvulnerability_rest_imagemagick_vulnerabilities() {
|
|
return wpvulnerability_rest_software_vulnerabilities( 'imagemagick' );
|
|
}
|
|
|
|
/**
|
|
* Handle the curl vulnerabilities REST API request.
|
|
*
|
|
* @since 3.5.0
|
|
*
|
|
* @return WP_REST_Response curl vulnerabilities data or an empty array if none found.
|
|
*/
|
|
function wpvulnerability_rest_curl_vulnerabilities() {
|
|
return wpvulnerability_rest_software_vulnerabilities( 'curl' );
|
|
}
|
|
|
|
/**
|
|
* Handle the memcached vulnerabilities REST API request.
|
|
*
|
|
* @since 3.5.0
|
|
*
|
|
* @return WP_REST_Response memcached vulnerabilities data or an empty array if none found.
|
|
*/
|
|
function wpvulnerability_rest_memcached_vulnerabilities() {
|
|
return wpvulnerability_rest_software_vulnerabilities( 'memcached' );
|
|
}
|
|
|
|
/**
|
|
* Handle the Redis vulnerabilities REST API request.
|
|
*
|
|
* @since 3.5.0
|
|
*
|
|
* @return WP_REST_Response Redis vulnerabilities data or an empty array if none found.
|
|
*/
|
|
function wpvulnerability_rest_redis_vulnerabilities() {
|
|
return wpvulnerability_rest_software_vulnerabilities( 'redis' );
|
|
}
|
|
|
|
/**
|
|
* Handle the SQLite vulnerabilities REST API request.
|
|
*
|
|
* @since 3.5.0
|
|
*
|
|
* @return WP_REST_Response SQLite vulnerabilities data or an empty array if none found.
|
|
*/
|
|
function wpvulnerability_rest_sqlite_vulnerabilities() {
|
|
return wpvulnerability_rest_software_vulnerabilities( 'sqlite' );
|
|
}
|
|
|
|
/**
|
|
* Custom permission check for the WPVulnerability REST API.
|
|
*
|
|
* This function checks if the request is authenticated using an Application Password or
|
|
* an authenticated session and verifies the user has admin capabilities.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @param WP_REST_Request $request The REST API request.
|
|
*
|
|
* @return bool True if the user has permission, false otherwise.
|
|
*/
|
|
function wpvulnerability_permission_check( WP_REST_Request $request ) {
|
|
|
|
$capability = is_multisite() ? 'manage_network_options' : 'manage_options';
|
|
|
|
if ( is_user_logged_in() && current_user_can( $capability ) ) {
|
|
return true;
|
|
}
|
|
|
|
// Check if application passwords are available (WordPress 5.6+).
|
|
// On older WordPress versions this authentication method is skipped and
|
|
// only cookie-authenticated sessions with admin capabilities are accepted.
|
|
if ( function_exists( 'wp_is_application_passwords_available' ) && function_exists( 'wp_authenticate_application_password' ) && wp_is_application_passwords_available() ) {
|
|
$authorization_header = $request->get_header( 'authorization' );
|
|
|
|
// Check if the authorization header is present and properly formatted.
|
|
if ( $authorization_header && preg_match( '/^Basic\s(.+)$/i', $authorization_header, $matches ) ) {
|
|
$auth_string = base64_decode( (string) $matches[1], true ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode -- Decoding HTTP Basic auth; strict mode enforced.
|
|
|
|
if ( false === $auth_string ) {
|
|
return false;
|
|
}
|
|
|
|
$credentials = explode( ':', $auth_string, 2 );
|
|
|
|
if ( 2 !== count( $credentials ) ) {
|
|
return false;
|
|
}
|
|
|
|
$user = $credentials[0];
|
|
$password = $credentials[1];
|
|
|
|
// Authenticate the user using the application password.
|
|
$authenticated_user = wp_authenticate_application_password( null, $user, $password );
|
|
|
|
if ( $authenticated_user instanceof WP_User ) {
|
|
// Check if user has the required capability.
|
|
// For multisite, require manage_network_options.
|
|
// For single site, require manage_options.
|
|
if ( is_multisite() ) {
|
|
return user_can( $authenticated_user, 'manage_network_options' );
|
|
}
|
|
|
|
return user_can( $authenticated_user, 'manage_options' );
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Registers REST API routes for WPVulnerability.
|
|
*
|
|
* This function sets up the REST API routes for WPVulnerability to handle requests
|
|
* related to vulnerabilities in various components like core, plugins, themes, PHP, and more.
|
|
*
|
|
* @since 3.3.0
|
|
*
|
|
* @return void
|
|
*/
|
|
function wpvulnerability_register_rest_routes() {
|
|
|
|
// Define the endpoints to be registered.
|
|
$endpoints = array(
|
|
'core',
|
|
'plugins',
|
|
'themes',
|
|
'php',
|
|
'apache',
|
|
'nginx',
|
|
'mariadb',
|
|
'mysql',
|
|
'imagemagick',
|
|
'curl',
|
|
'memcached',
|
|
'redis',
|
|
'sqlite',
|
|
);
|
|
|
|
// Loop through each endpoint and register it.
|
|
foreach ( $endpoints as $endpoint ) {
|
|
register_rest_route(
|
|
'wpvulnerability/v1', // Namespace and version.
|
|
'/' . $endpoint, // Endpoint URL.
|
|
array(
|
|
'methods' => 'GET', // HTTP method.
|
|
'callback' => 'wpvulnerability_rest_' . $endpoint . '_vulnerabilities', // Callback function.
|
|
'permission_callback' => 'wpvulnerability_permission_check', // Permission check callback.
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
// Hook to initialize REST API endpoints.
|
|
add_action( 'rest_api_init', 'wpvulnerability_register_rest_routes' );
|