sagacity/exec/parse_nvd_json_cve.php
Ryan Prather 21082c7513 checklist.inc - deleted duplicate BIND 9 checklist icon entry
finding.inc - removed ID property to prevent duplicate findings from being added to the table
host_list.inc - deleted unused constructor
import.inc - formatting
db_schema.json - removed sagacity.findings.id field (making tgt_id and pdi_id new primary keys), and updated references
Database_Baseline.zip - updated routines for above change
background_results.php - fixed bug #19
export-ckl.php - performance adjustments
parse_excel_echecklist.php - performance improvements, ensure duplicate findings are not created, make eChecklist true status, update for removing findings.id field
parse_nvd_json_cve.php - convert reading json to array instead of object for reading CPEs (which were updated to CPE 2.3 instead of 2.2)
parse_* - remove findings.id field
database.inc - formatting, and update for removing findings.id field
index.php - ensure user can't import a host list without uploading a host list file

Fixed:
#65, #51, #28, #27, #10
2018-11-06 15:36:48 -05:00

203 lines
5.5 KiB
PHP

<?php
/**
* File: parse_nvd_json_cve
* Author: Ryan Prather <ryan.prather@cyberperspectives.com>
* Purpose:
* Created: Apr 29, 2018
*
* Copyright 2018: Cyber Perspective, LLC, All rights reserved
* Released under the Apache v2.0 License
*
* See license.txt for details
*
* Change Log:
* - Apr 29, 2018 - File created
* - May 10, 2018 - Formatting and fixed performance issue on Windows (bug #403)
* - Jun 5, 2018 - Fix for bug #425
*/
include_once 'config.inc';
include_once 'helper.inc';
include_once 'database.inc';
include_once 'vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\LineFormatter;
ini_set('memory_limit', '2G');
$cmd = getopt("f:");
if (!isset($cmd['f']) || isset($cmd['h'])) {
die(usage());
}
$log_level = Logger::ERROR;
switch (LOG_LEVEL) {
case E_WARNING:
$log_level = Logger::WARNING;
break;
case E_NOTICE:
$log_level = Logger::NOTICE;
break;
case E_DEBUG:
$log_level = Logger::DEBUG;
break;
}
$log = new Logger("nvd_cve");
$log->pushHandler(new StreamHandler(LOG_PATH . "/nvd_cve.log", $log_level));
$db = new db();
$json = json_decode(file_get_contents($cmd['f']), true);
$existing_cves = [];
$db->help->select("cve_db", ['cve_id']);
$cves = $db->help->execute();
if (is_array($cves) && count($cves)) {
foreach ($cves as $cve) {
$existing_cves["{$cve['cve_id']}"] = 1;
}
}
print "Currently " . count($existing_cves) . " in DB" . PHP_EOL . "Parsing: " . count($json['CVE_Items']) . " items" . PHP_EOL;
$db_cpes = [];
$db_cpes23 = [];
$new_cves = [];
$new_cve_refs = [];
$sw_rows = [];
$new = 0;
$existing = 0;
$db->help->select("software", ['id', 'cpe', 'cpe23']);
$rows = $db->help->execute();
foreach ($rows as $row) {
$db_cpes["{$row['cpe']}"] = $row['id'];
$db_cpes23["{$row['cpe23']}"] = $row['id'];
}
$cve_fields = [
'cve_id', 'seq', 'status', 'phase', 'phase_date', 'desc'
];
$ref_fields = [
'cve_seq', 'source', 'url', 'val'
];
foreach ($json['CVE_Items'] as $cve) {
if (!isset($existing_cves["{$cve['cve']['CVE_data_meta']['ID']}"])) {
$log->debug("Adding {$cve['cve']['CVE_data_meta']['ID']}");
$new++;
$desc = [];
$status = null;
$phase = null;
$cpes = [];
$name = $cve['cve']['CVE_data_meta']['ID'];
$seq = $cve['cve']['CVE_data_meta']['ID'];
$pd = new DateTime($cve['publishedDate']);
if (is_array($cve['cve']['description']['description_data']) && count($cve['cve']['description']['description_data'])) {
foreach ($cve['cve']['description']['description_data'] as $d) {
$desc[] = $d['value'];
}
}
$new_cves[] = [
$name, $seq, $status, $phase, $pd, implode(PHP_EOL, $desc)
];
if (is_array($cve['cve']['references']['reference_data']) && count($cve['cve']['references']['reference_data'])) {
foreach ($cve['cve']['references']['reference_data'] as $ref) {
$log->debug("Adding reference {$ref['url']}");
$new_cve_refs[] = [
$name, null, $ref['url'], null
];
}
}
if(is_array($cve['configurations']['nodes']) && count($cve['configurations']['nodes'])) {
foreach($cve['configurations']['nodes'] as $n) {
if(isset($n['cpe_match']) && is_array($n['cpe_match']) && count($n['cpe_match'])) {
foreach($n['cpe_match'] as $c) {
if($c['vulnerable'] && $c['cpe23Uri']) {
$cpes[] = $c['cpe23Uri'];
}
}
}
}
}
if (count($cpes)) {
foreach ($cpes as $cpe) {
if (isset($db_cpes["{$cpe}"])) {
$sw_rows[] = [$name, $db_cpes["{$cpe}"]];
} elseif (isset($db_cpes23["{$cpe}"])) {
$sw_rows[] = [$name, $db_cpes23["{$cpe}"]];
}
}
}
print "*";
}
else {
$existing++;
print ".";
}
if (($new + $existing) % 100 == 0) {
if (count($new_cves)) {
$db->help->extended_insert("cve_db", $cve_fields, $new_cves, true);
$db->help->execute();
}
if (count($new_cve_refs)) {
$db->help->extended_insert("cve_references", $ref_fields, $new_cve_refs, true);
$db->help->execute();
}
if (count($sw_rows)) {
$db->help->extended_insert("cve_sw_lookup", ['cve_id', 'sw_id'], $sw_rows, true);
$db->help->execute();
}
$new_cves = [];
$new_cve_refs = [];
$sw_rows = [];
print "\t" . ($existing + $new) . " completed" . PHP_EOL;
}
}
if (count($new_cves)) {
$db->help->extended_insert("cve_db", $cve_fields, $new_cves, true);
$db->help->execute();
}
if (count($new_cve_refs)) {
$db->help->extended_insert("cve_references", $ref_fields, $new_cve_refs, true);
$db->help->execute();
}
if (count($sw_rows)) {
$db->help->extended_insert("cve_sw_lookup", ['cve_id', 'sw_id'], $sw_rows, true);
$db->help->execute();
}
//unlink($cmd['f']);
print PHP_EOL;
function usage()
{
print <<<EOF
Purpose: To import the National Vulnerability Database (NVD) CVE JSON files
Usage: php parse_nvd_json_cve.php -f={JSON file} [-h]
-f={JSON file} The CVE file to import
-h This screen
EOF;
}