338 lines
11 KiB
PHP
338 lines
11 KiB
PHP
<?php
|
|
|
|
/**
|
|
* File: parse_iavm.php
|
|
* Author: Ryan Prather
|
|
* Purpose: To parse IAVM files retrieved from https://iavm.csd.disa.mil
|
|
* Created: Jul 9, 2014
|
|
*
|
|
* Portions Copyright 2016: Cyber Perspectives, All rights reserved
|
|
* Released under the Apache v2.0 License
|
|
*
|
|
* Portions Copyright (c) 2012-2015, Salient Federal Solutions
|
|
* Portions Copyright (c) 2008-2011, Science Applications International Corporation (SAIC)
|
|
* Released under Modified BSD License
|
|
*
|
|
* See license.txt for details
|
|
*
|
|
* Change Log:
|
|
* - Jul 9, 2014 - File created
|
|
* - Sep 1, 2016 - Copyright Updated and converted to constants
|
|
*/
|
|
$cmd = getopt("d:f::", array('debug::', 'help::'));
|
|
|
|
if (!isset($cmd['f']) || !isset($cmd['s']) || isset($cmd['help'])) {
|
|
usage();
|
|
exit;
|
|
}
|
|
|
|
include_once 'config.inc';
|
|
include_once "database.inc";
|
|
include_once 'helper.inc';
|
|
|
|
chdir(DOC_ROOT . "/tmp");
|
|
set_time_limit(0);
|
|
|
|
$sys = new db();
|
|
|
|
$db = new mysqli(DB_SERVER, 'web', db::decrypt_pwd(), 'sagacity');
|
|
if ($db->connect_errno) {
|
|
die($db->connect_error);
|
|
}
|
|
|
|
if (!isset($cmd['d'])) {
|
|
die("Did not include the directory the files are in");
|
|
}
|
|
|
|
chdir($cmd['d']);
|
|
|
|
if (isset($cmd['f'])) {
|
|
$files = array(0 => $cmd['f']);
|
|
}
|
|
else {
|
|
$files = glob("*.xml");
|
|
}
|
|
|
|
foreach ($files as $file) {
|
|
print $file . PHP_EOL;
|
|
$doc = new DOMDocument();
|
|
$doc->load($file);
|
|
|
|
$pi = $doc->createProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="iavm.xsl"');
|
|
$doc->insertBefore($pi, $doc->getElementsByTagName("iavmNotice")->item(0));
|
|
$doc->xmlStandalone = true;
|
|
|
|
$tmp = $doc->saveXML();
|
|
$tmp = str_replace(" xmlns=\"http://iavm.csd.disa.mil/schemas/IavmNoticeSchema/1.2\"", "", $tmp);
|
|
$doc->loadXML($tmp);
|
|
|
|
// root node values (iavm_notice table)
|
|
$id = getValue($doc, '/iavmNotice/@noticeId');
|
|
$xmlurl = getValue($doc, '/iavmNotice/xmlUrl');
|
|
$htmlurl = getValue($doc, '/iavmNotice/htmlUrl');
|
|
$noticeNumber = getValue($doc, '/iavmNotice/iavmNoticeNumber');
|
|
$title = getValue($doc, '/iavmNotice/title');
|
|
$type = getValue($doc, '/iavmNotice/type');
|
|
$state = getValue($doc, '/iavmNotice/state');
|
|
$lastUpdated = getValue($doc, '/iavmNotice/lastUpdated');
|
|
$releaseDate = getValue($doc, '/iavmNotice/releaseDate');
|
|
$supersedes = getValue($doc, '/iavmNotice/supersedes');
|
|
$execSummary = getValue($doc, '/iavmNotice/executiveSummary');
|
|
$fixAction = getValue($doc, '/iavmNotice/fixAction');
|
|
$note = getValue($doc, '/iavmNotice/note');
|
|
$vulnAppsSysAndCntrmsrs = getValue($doc, '/iavmNotice/vulnAppsSysAndCntrmsrs');
|
|
$knownExploits = getValue($doc, '/iavmNotice/knownExploits');
|
|
$stigFindingSeverity = getValue($doc, '/iavmNotice/vms/stigFindingSeverity');
|
|
|
|
// iavm_tech_overview
|
|
$techOverview = getValue($doc, '/iavmNotice/techOverview', null, true);
|
|
|
|
// iavm_references
|
|
$references = getValue($doc, '/iavmNotice/references/reference', null, true);
|
|
|
|
// iavm_bids
|
|
$bids = getValue($doc, '/iavmNotice/deepSightBids/bid', null, true);
|
|
|
|
// iavm_patches
|
|
$patches = getValue($doc, '/iavmNotice/patches/patch', null, true);
|
|
|
|
// iavm_mitigations
|
|
$mitHeader = getValue($doc, '/iavmNotice/tempMitStrat/header');
|
|
$mitBody = getValue($doc, '/iavmNotice/tempMitStrat/body');
|
|
|
|
$doc->formatOutput = true;
|
|
$doc->preserveWhiteSpace = true;
|
|
//print $doc->saveXML();
|
|
|
|
if (is_array($supersedes)) {
|
|
$supersedes = implode(',', $supersedes);
|
|
}
|
|
|
|
$stig = $sys->get_Stig($noticeNumber);
|
|
if (is_array($stig) && count($stig) && isset($stig[0]) && is_a($stig[0], 'stig')) {
|
|
$stig = $stig[0];
|
|
$pdi_id = $stig->get_PDI_ID();
|
|
}
|
|
else {
|
|
$pdi = new pdi(null, $stigFindingSeverity, $lastUpdated);
|
|
$pdi->set_Short_Title($title);
|
|
$pdi->set_Group_Title($title);
|
|
$pdi->set_Description($execSummary);
|
|
// print_r($pdi);
|
|
$pdi_id = $sys->save_PDI($pdi);
|
|
|
|
$stig = new stig($pdi_id, $noticeNumber, $execSummary);
|
|
// print_r($stig);
|
|
$sys->add_Stig($stig);
|
|
}
|
|
|
|
$last_updated_dt = new DateTime($lastUpdated);
|
|
$release_date_dt = new DateTime($releaseDate);
|
|
|
|
$iavm = $sys->get_IAVM($noticeNumber);
|
|
if (is_null($iavm)) {
|
|
$sys->help->insert("sagacity.iavm_notices", [
|
|
'pdi_id' => $pdi_id,
|
|
'noticeId' => $id,
|
|
'xmlUrl' => $xmlurl,
|
|
'htmlUrl' => $htmlurl,
|
|
'file_name' => basename($file),
|
|
'iavmNoticeNumber' => $noticeNumber,
|
|
'title' => $title,
|
|
'type' => $type,
|
|
'state' => $state,
|
|
'lastUpdated' => $last_updated_dt->format(MYSQL_D_FORMAT),
|
|
'releaseDate' => $release_date_dt->format(MYSQL_D_FORMAT),
|
|
'supersedes' => $supersedes,
|
|
'executiveSummary' => $execSummary,
|
|
'fixAction' => $fixAction,
|
|
'note' => $note,
|
|
'vulnAppsSysAndCntrmsrs' => $vulnAppsSysAndCntrmsrs,
|
|
'stigFindingSeverity' => $stigFindingSeverity,
|
|
'knownExploits' => $knownExploits
|
|
], true);
|
|
|
|
if (!$sys->help->execute()) {
|
|
error_log("file: $file" . PHP_EOL . $db->error . PHP_EOL . $ins_sql);
|
|
continue;
|
|
//die;
|
|
}
|
|
}
|
|
|
|
if ($bids->length) {
|
|
foreach ($bids as $bid) {
|
|
if ($res = $db->query(
|
|
"SELECT COUNT(1) as 'cnt' FROM sagacity.iavm_bids WHERE iavm_notice_id = $id AND bid = '" . $bid->textContent .
|
|
"'")) {
|
|
if ($res->num_rows) {
|
|
$row = $res->fetch_array(MYSQLI_ASSOC);
|
|
print "existing bid: $bid->textContent" . PHP_EOL;
|
|
}
|
|
else {
|
|
$sql = "INSERT INTO sagacity.iavm_bids (iavm_notice_id, bid) VALUES ($id, $bid->textContent)";
|
|
$db->real_query($sql);
|
|
print "new bid: $bid->textContent" . PHP_EOL;
|
|
}
|
|
}
|
|
else {
|
|
error_log($db->error);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($references->length) {
|
|
foreach ($references as $ref) {
|
|
$url = getValue($doc, "url", $ref);
|
|
$title = getValue($doc, "title", $ref);
|
|
$type = getValue($doc, "type", $ref);
|
|
|
|
$res = $db->query(
|
|
"SELECT id FROM sagacity.iavm_references WHERE iavm_notice_id = $id AND url='" .
|
|
$db->real_escape_string($url) . "'");
|
|
|
|
if ($res->num_rows) {
|
|
$row = $res->fetch_array(MYSQLI_ASSOC);
|
|
$sql = "UPDATE sagacity.iavm_references SET title = '" . $db->real_escape_string($title) .
|
|
"' WHERE id = " . $row['id'];
|
|
$db->real_query($sql);
|
|
print "existing reference: " . $title . " (" . $row['id'] . ")" . PHP_EOL;
|
|
}
|
|
else {
|
|
$sql = "INSERT INTO sagacity.iavm_references (iavm_notice_id, title, url) VALUES ($id, '" .
|
|
$db->real_escape_string($title) . "','" . $db->real_escape_string($url) . "')";
|
|
$db->real_query($sql);
|
|
// print "db error: ".$db->error.PHP_EOL;
|
|
print "new reference: " . $title . PHP_EOL;
|
|
}
|
|
|
|
$matches = array();
|
|
if (preg_match("/microsoft\.com.*\/([\d]+)/i", $url, $matches) ||
|
|
preg_match("/(MS[\d]+\-[\d]+)/", $title, $matches)) {
|
|
if (is_numeric($matches[1])) {
|
|
$matches[1] = "KB" . $matches[1];
|
|
}
|
|
$adv = new advisory($pdi_id, $matches[1], "", "", $url);
|
|
$sys->save_Advisory(array(
|
|
0 => $adv
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($techOverview->length) {
|
|
foreach ($techOverview as $to) {
|
|
$details = getValue($doc, "details", $to);
|
|
if ($details) {
|
|
$res = $db->query(
|
|
"SELECT id FROM sagacity.iavm_tech_overview WHERE iavm_notice_id = $id AND details='" .
|
|
$db->real_escape_string($details) . "'");
|
|
$row = $res->fetch_array(MYSQLI_ASSOC);
|
|
|
|
if ($row['id']) {
|
|
print "existing overview for $id" . PHP_EOL;
|
|
}
|
|
else {
|
|
$sql = "INSERT INTO sagacity.iavm_tech_overview (iavm_notice_id, details) VALUES ($id, '" .
|
|
$db->real_escape_string($details) . "')";
|
|
$db->real_query($sql);
|
|
print "new overview" . PHP_EOL;
|
|
}
|
|
}
|
|
|
|
$entries = getValue($doc, "entry", $to, true);
|
|
if ($entries->length) {
|
|
foreach ($entries as $entry) {
|
|
$entry_title = getValue($doc, "title", $entry);
|
|
$entry_desc = getValue($doc, "description", $entry);
|
|
|
|
if (substr($entry_title, 0, 3) == 'CVE') {
|
|
print "CVE: $entry_title" . PHP_EOL;
|
|
$sql = "REPLACE INTO sagacity.iavm_to_cve (noticeId, cve_id) VALUES (" . $id . "," . "'" .
|
|
$db->real_escape_string($entry_title) . "')";
|
|
|
|
$db->real_query($sql);
|
|
}
|
|
else {
|
|
Sagacity_Error::err_handler("Entry title: $entry_title in file $file");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($patches->length) {
|
|
foreach ($patches as $patch) {
|
|
$title = getValue($doc, "title", $patch);
|
|
$type = getValue($doc, "type", $patch);
|
|
$url = getValue($doc, "url", $patch);
|
|
|
|
$res = $db->query(
|
|
"SELECT id FROM sagacity.iavm_patches WHERE iavm_notice_id = $id AND url = '" .
|
|
$db->real_escape_string($url) . "'");
|
|
$row = $res->fetch_array(MYSQLI_ASSOC);
|
|
|
|
if ($row['id']) {
|
|
$sql = "UPDATE sagacity.iavm_patches SET `type` = '" . $db->real_escape_string($type) .
|
|
"', `title` = '" . $db->real_escape_string($title) . "' WHERE id = " . $row['id'];
|
|
$db->real_query($sql);
|
|
print "existing patch: $title (" . $row['id'] . ")" . PHP_EOL;
|
|
}
|
|
else {
|
|
$sql = "INSERT INTO sagacity.iavm_patches (iavm_notice_id, `type`, title, url) VALUES ($id, '" .
|
|
$db->real_escape_string($type) . "','" . $db->real_escape_string($title) . "','" .
|
|
$db->real_escape_string($url) . "')";
|
|
$db->real_query($sql);
|
|
print "new patch: $title" . PHP_EOL;
|
|
}
|
|
|
|
$matches = array();
|
|
if (preg_match("/(KB[\d]+)|(MS[\d]+\-[\d]+)/i", $title, $matches)) {
|
|
$adv = new advisory($pdi_id, $matches[1], "", "", $url);
|
|
$sys->save_Advisory(array(
|
|
0 => $adv
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($mitHeader) {
|
|
$res = $db->query(
|
|
"SELECT id FROM sagacity.iavm_mitigations WHERE iavm_notice_id = $id AND header = '" .
|
|
$db->real_escape_string($mitHeader) . "'");
|
|
$row = $res->fetch_array(MYSQLI_ASSOC);
|
|
|
|
if ($row['id']) {
|
|
$sql = "UPDATE sagacity.iavm_mitigations SET body = '" . $db->real_escape_string($mitBody) .
|
|
"' WHERE id = " . $row['id'];
|
|
$db->real_query($sql);
|
|
print "existing mitigation: " . $row['id'] . PHP_EOL;
|
|
}
|
|
else {
|
|
$sql = "INSERT INTO sagacity.iavm_mitigations (iavm_notice_id, header, body) VALUES ($id, '" .
|
|
$db->real_escape_string($mitHeader) . "','" . $db->real_escape_string($mitBody) . "')";
|
|
$db->real_query($sql);
|
|
print "new mitigation: $mitHeader" . PHP_EOL;
|
|
}
|
|
}
|
|
|
|
if (!$doc->save(DOC_ROOT . "/reference/iavms/$file")) {
|
|
print "error saving" . PHP_EOL;
|
|
die;
|
|
}
|
|
}
|
|
|
|
function usage() {
|
|
print <<<EOO
|
|
Purpose: To import an IAVM file and populate/update the database
|
|
|
|
Usage: php parse_iavm.php -d={IAVM Directory} [-f={XCCDF result file}] [--debug] [--help]
|
|
|
|
-d={IAVM directory} The directory to import the files from. This will crawl the directory and import all the IAVMs
|
|
-f={XCCDF file} The IAVM file specifically
|
|
|
|
--debug Debugging output
|
|
--help This screen
|
|
|
|
EOO;
|
|
}
|