Skip to content

Commit

Permalink
Wordfence has been added as an option for the Mainwp Child vulnerabil…
Browse files Browse the repository at this point in the history
…ity checker
  • Loading branch information
bytepattern committed Sep 9, 2024
1 parent 34f0be0 commit 9fa5f1d
Showing 1 changed file with 171 additions and 26 deletions.
197 changes: 171 additions & 26 deletions class/class-mainwp-child-vulnerability-checker.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ class MainWP_Child_Vulnerability_Checker {
*/
private $wpvulndb_nvd_api = 'https://services.nvd.nist.gov/rest/json/cves/2.0';

/**
* Wordfence API URL
*/
private $wordfence_api_url = 'www.wordfence.com/api/intelligence/v2/vulnerabilities/';


/**
* Method instance()
Expand Down Expand Up @@ -100,7 +105,7 @@ public function vulner_recheck() {
$result = array();
// phpcs:disable WordPress.Security.NonceVerification
$force = ( isset( $_POST['force'] ) && ! empty( $_POST['force'] ) ) ? true : false;
$service = ( isset( $_POST['service'] ) && 'nvd_nist' === $_POST['service'] ) ? 'nvd_nist' : 'wpvulndb';
$service = ( isset( $_POST[ 'service' ] ) && 'nvd_nist' === $_POST[ 'service' ] ) ? 'nvd_nist' : ( ( isset( $_POST[ 'service' ] ) && 'wordfence' == $_POST[ 'service' ] ) ? 'wordfence' : 'wpvulndb' );

if ( 'wpvulndb' === $service ) {
if ( empty( $_POST['wpvulndb_tk'] ) ) {
Expand All @@ -120,6 +125,88 @@ public function vulner_recheck() {
);
}

/**
* @param $version
* @param $data
* @return bool
*/
function isFixedVersion($version , $data){
if($data['from_version'] === '*' && $data['to_version'] === '*'){
return false;
}

if($data['from_version'] === '*'){
$data['from_version'] = '0';
}

$fromOperator = $data[ 'from_inclusive' ] ? '>=' : '>';
$toOperator = $data[ 'to_inclusive' ] ? '<=' : '<';

if (version_compare ($version, $data['from_version'], $fromOperator) && version_compare ($version, $data['to_version'], $toOperator)) {
return false;
} else {
return true;
}
}

/**
* @param $data
* @param $slug
* @param $version
* @return array
*/
public function get_vuln_wordfence_info($data, $slug, $version){

$data = json_decode( $data, true );
$filtered_data = array();


if ( is_array( $data ) && isset( $data['result'] ) && isset( $data['result']['CVE_Items'] ) ) {
$vulns = array();
$version_missed = true;
$fixed = false;

foreach ( $data['result']['CVE_Items'] as $item ) {
$info = array();
$remediation = '';
foreach($item['software'] as $software) {
foreach ( $software[ 'affected_versions' ] as $affected_version ) {
$fixed = $this->isFixedVersion($version, $affected_version);
$version_missed = false;
if ( $fixed ) {
break;
}
}

$remediation .= " [".ucfirst($software['type']). '->' .$software['name']."] " . $software['remediation'];
}

if ( !$fixed ) {
if ( isset( $item['published'] ) ) {
$info['date'] = $item['published'];
}

if ( isset( $item['description'] ) ) {
$info['detail'] = $item['description'] . $remediation;
}

$customCveId = explode( '-', $item[ 'id' ]);
$info['cve_id'] = $item[ 'cve' ] ?? end($customCveId);
$info['slug'] = $slug;
}
if ( $version_missed ) {
$info['missed_version'] = 1;
}
if ( ! empty( $info ) ) {
$vulns[] = $info;
}
}
$filtered_data[ $slug ]['vulnerabilities'] = $vulns;
}

return $filtered_data;
}

/**
* Check for plugin vulnerabilities.
*
Expand Down Expand Up @@ -151,6 +238,8 @@ public function check_plugins( $force = false, $service = '' ) { //phpcs:ignore
}
// URL Syntax example: https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:a:automattic:akismet:* .
$url = $this->wpvulndb_nvd_api . '?virtualMatchString=cpe:2.3:a:' . $author_name . ':' . $slug . ':*';
} else if ( 'wordfence' === $service ) {
$url = $this->wordfence_api_url . 'production?keyword=' . $string[0];
} else {
$url = $this->wpvulndb_api . 'plugins/' . $string[0];
}
Expand All @@ -161,6 +250,8 @@ public function check_plugins( $force = false, $service = '' ) { //phpcs:ignore
$plug_vuln_filter = array();
if ( 'nvd_nist' === $service ) {
$plug_vuln_filter = $this->get_vuln_nvd_nist_info( $plug_vuln, $string[0], $plugin_version );
} else if('wordfence' == $service) {
$plug_vuln_filter = $this->get_vuln_wordfence_info( $plug_vuln, $string[0], $plugin_version );
} else {
$plug_vuln = json_decode( $plug_vuln, true );
$plug_vuln_filter = $plug_vuln;
Expand Down Expand Up @@ -214,6 +305,8 @@ public function check_wp( $force = false, $service = '' ) {
if ( false === $wp_vuln || $force ) {
if ( 'nvd_nist' === $service ) {
$url = $this->wpvulndb_nvd_api . '?virtualMatchString=cpe:2.3:a:WordPress:WordPress';
} else if ( 'wordfence' == $service ) {
$url = $this->wordfence_api_url . 'production?keyword=wordpress';
} else {
$url = $this->wpvulndb_api . 'wordpresses/' . $number_version;
}
Expand All @@ -223,6 +316,12 @@ public function check_wp( $force = false, $service = '' ) {
$wp_vuln = $this->get_vuln_nvd_nist_info( $wp_vuln, 'wordpress', $wp_version ); //phpcs:ignore -- wordpress.
$wp_vuln = wp_json_encode( $wp_vuln );
}

if ( 'wordfence' == $service ) {
$wp_vuln = $this->get_vuln_wordfence_info( $wp_vuln, 'WordPress', $wp_version );
$wp_vuln = wp_json_encode( $wp_vuln );
}

set_transient( 'mainwp_vulnche_trans_wp_json', $wp_vuln, 1 * DAY_IN_SECONDS );
}
return $wp_vuln;
Expand Down Expand Up @@ -257,6 +356,8 @@ public function check_themes( $force = false, $service = '' ) { // phpcs:ignore

if ( 'nvd_nist' === $service ) {
$url = $this->wpvulndb_nvd_api . '?keywordSearch=' . $th['id'] . '&keywordExactMatch';
}else if ( 'wordfence' === $service ) {
$url = $this->wordfence_api_url . 'production?keyword='. $th['id'];
} else {
$url = $this->wpvulndb_api . 'themes/' . $th['id'];
}
Expand All @@ -268,6 +369,8 @@ public function check_themes( $force = false, $service = '' ) { // phpcs:ignore
if ( $th_vuln ) {
if ( 'nvd_nist' === $service ) {
$th_vuln_filter = $this->get_vuln_nvd_nist_info( $th_vuln, $th['id'], $th['version'] );
}else if( 'wordfence' === $service ){
$th_vuln_filter = $this->get_vuln_wordfence_info( $th_vuln, $th['id'], $th['version'] );
} else {
$th_vuln = json_decode( $th_vuln, true );
$th_vuln_filter = $th_vuln;
Expand Down Expand Up @@ -535,37 +638,79 @@ public function get_vuln_nvd_nist_info( $data, $slug, $version ) { // phpcs:ign
*/
public function vulnche_get_content( $url, $service = '' ) {

$encrypted = get_transient( 'mainwp_child_trans_wpvulndb_tk' );
$wpvulndb_token = MainWP_Child_Keys_Manager::instance()->decrypt_string( $encrypted );

// phpcs:disable WordPress.WP.AlternativeFunctions -- Required to achieve desired results, pull request solutions appreciated.
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
if ( 'nvd_nist' !== $service ) {
if ( empty( $wpvulndb_token ) ) {
if ( 'resource' === gettype( $ch ) ) {
curl_close( $ch );
if ( 'wordfence' === $service ) {

$typeName = explode( '=', $url );
if($this->wordfenceJson == ''){
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_setopt( $ch, CURLOPT_USERAGENT, $this->get_random_user_agent() );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec( $ch );
$this->wordfenceJson = json_decode($response, true);
}
$output = [];
$resultData = [];
foreach($this->wordfenceJson as $feed){
if($typeName[1] == $feed['software'][0]['slug']){
$output[] = $feed;

$resultData[] = [
'CVE_data_type' => isset($feed['cve']) ? 'CVE' : '',
'references' => ['reference_data' => $feed['references']],
'description' => ['description_data' => $feed['description']],
'publishedDate' => $feed['published'],
'lastModifiedDate' => $feed['updated'],
];
}
return false;
}
curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Authorization: Token token=' . $wpvulndb_token ) );
}
curl_setopt( $ch, CURLOPT_USERAGENT, $this->get_random_user_agent() );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );

$output = curl_exec( $ch );
$info = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
$data = [
'resultsPerPage' => count($output),
'startIndex' => 0,
'totalResults' => count($output),
'result' => [
'CVE_Items' => $output
]
];

return json_encode($data);
}else {

$encrypted = get_transient( 'mainwp_child_trans_wpvulndb_tk' );
$wpvulndb_token = MainWP_Child_Keys_Manager::instance()->decrypt_string( $encrypted );

// phpcs:disable WordPress.WP.AlternativeFunctions -- Required to achieve desired results, pull request solutions appreciated.
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
if ( 'nvd_nist' !== $service ) {
if ( empty( $wpvulndb_token ) ) {
if ( 'resource' === gettype( $ch ) ) {
curl_close( $ch );
}
return false;
}
curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Authorization: Token token=' . $wpvulndb_token ) );
}
curl_setopt( $ch, CURLOPT_USERAGENT, $this->get_random_user_agent() );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );

$output = curl_exec( $ch );
$info = curl_getinfo( $ch, CURLINFO_HTTP_CODE );

if ( 'resource' === gettype( $ch ) ) {
curl_close( $ch );
}
// phpcs:enable
if ( 'resource' === gettype( $ch ) ) {
curl_close( $ch );
}
// phpcs:enable

if ( false === $output || 200 !== (int) $info ) {
$output = null;
if ( false === $output || 200 !== (int) $info ) {
$output = null;
}
return $output;
}
return $output;
}

/**
Expand Down

0 comments on commit 9fa5f1d

Please sign in to comment.