Ryan Prather
7f2f6a9046
Some formatting Die if installer.php fails to create password file Update target counts after importing eChecklist and CKL
321 lines
9.4 KiB
PHP
321 lines
9.4 KiB
PHP
<?php
|
|
/**
|
|
* File: parse_stig_viewer.php
|
|
* Author: Ryan Prather
|
|
* Purpose: Read STIG Viewer checklist files
|
|
* Created: Apr 10, 2014
|
|
*
|
|
* Portions Copyright 2016-2017: Cyber Perspectives, LLC, 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:
|
|
* - Apr 10, 2014 - File created
|
|
* - Jun 3, 2015 - Copyright updated, added CWD parameter, and
|
|
* updated function calls after class merger
|
|
* - Mar 4, 2017 - Removed Thread class calls
|
|
* - May 22, 2017 - Migrated to use parse_config.ini file and bug fixed to get working. Added CLI progress report
|
|
* - Jun 3, 2017 - Fixed bug #237
|
|
*/
|
|
$cmd = getopt("f:", ['debug::', 'help::']);
|
|
|
|
if (!isset($cmd['f']) || isset($cmd['help'])) {
|
|
die(usage());
|
|
}
|
|
|
|
if (!file_exists("parse_config.ini")) {
|
|
die("You must create parse_config.ini file with required parameters");
|
|
}
|
|
|
|
$conf = parse_ini_file("parse_config.ini");
|
|
|
|
if (!$conf) {
|
|
die("Could not find parse_config.ini configuration file");
|
|
}
|
|
|
|
chdir($conf['doc_root']);
|
|
|
|
include_once 'config.inc';
|
|
include_once 'helper.inc';
|
|
include_once 'database.inc';
|
|
|
|
check_path(TMP . "/stig_viewer");
|
|
chdir(TMP);
|
|
|
|
$db = new db();
|
|
$base_name = basename($cmd['f']);
|
|
$host_list = [];
|
|
$err = new Sagacity_Error($cmd['f']);
|
|
|
|
if (!file_exists($cmd['f'])) {
|
|
$db->update_Running_Scan($base_name, ['name' => 'status', 'value' => 'ERROR']);
|
|
$err->script_log("File not found", E_ERROR);
|
|
}
|
|
|
|
$db->update_Running_Scan($base_name, ['name' => 'pid', 'value' => getmypid()]);
|
|
|
|
$xml = new DOMDocument();
|
|
$xml->load($cmd['f']);
|
|
|
|
$root = $xml->getElementsByTagName('CHECKLIST')->item(0);
|
|
$xmlns = $xml->createAttribute('xmlns');
|
|
$xmlns->value = "http://www.w3.org/2001/XMLSchema-instance";
|
|
|
|
$root->appendChild($xmlns);
|
|
|
|
$host_name = getValue($xml, '//HOST_NAME');
|
|
$host_ip = getValue($xml, '//HOST_IP');
|
|
$host_mac = getValue($xml, '//HOST_MAC');
|
|
|
|
if (!$host_name) {
|
|
$db->update_Running_Scan($base_name, ['name' => 'status', 'value' => 'TERMINATED']);
|
|
unset($xml);
|
|
|
|
rename($cmd['f'], TMP . "/terminated/{$base_name}");
|
|
$err->script_log("File parsing terminated because host name was absent", E_ERROR);
|
|
die;
|
|
}
|
|
|
|
if ($tgt_id = $db->check_Target($conf['ste'], $host_name)) {
|
|
$tgt = $db->get_Target_Details($conf['ste'], $tgt_id)[0];
|
|
}
|
|
elseif ($tgt_id = $db->check_Target($conf['ste'], $host_ip)) {
|
|
$tgt = $db->get_Target_Details($conf['ste'], $tgt_id)[0];
|
|
}
|
|
else {
|
|
$tgt = new target($host_name);
|
|
$tgt->set_STE_ID($conf['ste']);
|
|
|
|
$sw = $db->get_Software("cpe:/o:generic:generic");
|
|
if (is_array($sw) && count($sw) && isset($sw[0]) && is_a($sw[0], 'software')) {
|
|
$sw = $sw[0];
|
|
|
|
$tgt->set_OS_ID($sw->get_ID());
|
|
$tgt->set_OS_String($sw->get_Shortened_SW_String());
|
|
}
|
|
|
|
$tgt_id = $db->save_Target($tgt);
|
|
$tgt->set_ID($tgt_id);
|
|
}
|
|
|
|
$source = $db->get_Sources('STIG Viewer');
|
|
if (is_array($source) && count($source) && isset($source[0]) && is_a($source[0], 'source')) {
|
|
$source = $source[0];
|
|
}
|
|
else {
|
|
die("Could not find source 'STIG Viewer' in DB");
|
|
}
|
|
$scan = $db->get_ScanData($conf['ste'], $base_name);
|
|
|
|
$vulns = getValue($xml, '//VULN', null, true);
|
|
|
|
if (!count($scan)) {
|
|
$fmt = filemtime($cmd['f']);
|
|
$fdt = DateTime::createFromFormat('U', $fmt);
|
|
$ste = $db->get_STE($conf['ste'])[0];
|
|
$scan = new scan(null, $source, $ste, 1, $base_name, $fdt->format('Y-m-d H:i:s'));
|
|
|
|
$hl = new host_list();
|
|
$hl->setTargetId($tgt->get_ID());
|
|
$hl->setTargetName($tgt->get_Name());
|
|
$hl->setFindingCount($vulns->length);
|
|
|
|
$scan->add_Target_to_Host_List($hl);
|
|
$scan_id = $db->save_Scan($scan);
|
|
$scan->set_ID($scan_id);
|
|
}
|
|
else {
|
|
$scan = $scan[0];
|
|
|
|
$hl = new host_list();
|
|
$hl->setTargetId($tgt->get_ID());
|
|
$hl->setTargetName($tgt->get_Name());
|
|
$hl->setFindingCount($vulns->length);
|
|
|
|
$scan->add_Target_to_Host_List($hl);
|
|
$db->update_Scan_Host_List($scan);
|
|
}
|
|
|
|
$vuln_count = 1;
|
|
|
|
foreach ($vulns as $vul) {
|
|
$stig_data = getValue($xml, "STIG_DATA", $vul, true);
|
|
|
|
$arr = [];
|
|
|
|
foreach ($stig_data as $node) {
|
|
$db->help->select("sagacity.scans", ['status'], [
|
|
[
|
|
'field' => 'id',
|
|
'op' => '=',
|
|
'value' => $scan->get_ID()
|
|
]
|
|
]);
|
|
$thread_status = $db->help->execute();
|
|
if ($thread_status == 'TERMINATED') {
|
|
unset($xml);
|
|
$source = strtolower($scan->get_Source()->get_Name());
|
|
rename(realpath(TMP . "/{$scan->get_File_Name()}"), realpath(TMP . "/scc/{$scan->get_File_Name()}"));
|
|
$err->script_log("File parsing terminated by user");
|
|
die();
|
|
}
|
|
|
|
$attr = getValue($xml, "VULN_ATTRIBUTE", $node);
|
|
$data = getValue($xml, "ATTRIBUTE_DATA", $node);
|
|
|
|
switch ($attr) {
|
|
case 'Vuln_Num':
|
|
$arr['vms_id'] = $data;
|
|
break;
|
|
case 'Severity':
|
|
if ($data == 'high') {
|
|
$arr['cat'] = 1;
|
|
}
|
|
elseif ($data == 'medium') {
|
|
$arr['cat'] = 2;
|
|
}
|
|
elseif ($data == 'low') {
|
|
$arr['cat'] = 3;
|
|
}
|
|
else {
|
|
$arr['cat'] = 2;
|
|
}
|
|
break;
|
|
case 'Rule_ID':
|
|
$arr['sv_rule'] = explode(' ', $data);
|
|
break;
|
|
case 'Rule_Ver':
|
|
$arr['stig_id'] = $data;
|
|
break;
|
|
case 'IA_Controls':
|
|
$arr['ia_controls'] = explode(", ", $data);
|
|
break;
|
|
case 'Check_Content_Ref':
|
|
$arr['ref'] = substr($data, 0, strpos($data, ' :: '));
|
|
break;
|
|
case 'Rule_Title':
|
|
$arr['short_title'] = $data;
|
|
break;
|
|
case 'Vuln_Discuss':
|
|
$arr['desc'] = $data;
|
|
break;
|
|
case 'Check_Content':
|
|
$arr['check_content'] = $data;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isset($arr['stig_id'])) {
|
|
$stig = $db->get_Stig($arr['stig_id']);
|
|
if (is_array($stig) && count($stig) && isset($stig[0]) && is_a($stig[0], 'stig')) {
|
|
$stig = $stig[0];
|
|
}
|
|
else {
|
|
$pdi = new pdi(null, $arr['cat'], null, $arr['short_title'], $arr['desc']);
|
|
$pdi->set_Short_Title($arr['short_title']);
|
|
$pdi->set_Group_Title($arr['short_title']);
|
|
$pdi->set_Description($arr['desc']);
|
|
$pdi_id = $db->save_PDI($pdi);
|
|
|
|
$stig = new stig($pdi_id, $arr['stig_id'], $arr['desc']);
|
|
$db->add_Stig($stig);
|
|
// add stig
|
|
}
|
|
}
|
|
else {
|
|
print_r($arr);
|
|
}
|
|
|
|
$status = getValue($xml, 'STATUS', $vul);
|
|
switch ($status) {
|
|
case "Not_Reviewed":
|
|
$status = "Not Reviewed";
|
|
break;
|
|
case "NotAFinding":
|
|
$status = "Not a Finding";
|
|
break;
|
|
case "Not_Applicable":
|
|
$status = "Not Applicable";
|
|
}
|
|
|
|
$comments = "(STIG Viewer) " . getValue($xml, 'COMMENTS', $vul);
|
|
$vms = $db->get_GoldDisk($arr['vms_id']);
|
|
|
|
if (empty($vms)) {
|
|
$db->save_GoldDisk(new golddisk($stig->get_PDI_ID(), $arr['vms_id'], $arr['short_title']));
|
|
}
|
|
|
|
foreach ($arr['sv_rule'] as $key => $sv_rule) {
|
|
$sv = $db->get_SV_Rule($stig->get_PDI_ID(), $sv_rule);
|
|
if (!count($sv)) {
|
|
$db->save_SV_Rule(array(0 => new sv_rule($stig->get_PDI_ID(), $sv_rule)));
|
|
}
|
|
}
|
|
|
|
if (!$oval = $db->get_Oval($arr['ref']) || $oval->get_PDI_ID() != $stig->get_PDI_ID()) {
|
|
$db->add_Oval($oval = new oval($stig->get_PDI_ID(), $arr['ref'], $arr['short_title'], $arr['desc'], null, null, null));
|
|
}
|
|
|
|
$tmp = [];
|
|
|
|
foreach ($arr['ia_controls'] as $ia) {
|
|
if ($ia) {
|
|
$tmp[] = new ia_control($stig->get_PDI_ID(), substr($ia, 0, 4), substr($ia, 5));
|
|
}
|
|
}
|
|
|
|
if (count($tmp)) {
|
|
$db->save_IA_Control($tmp);
|
|
}
|
|
|
|
if (!$db->add_Finding($scan, $tgt, [
|
|
$arr['stig_id'],
|
|
$arr['vms_id'],
|
|
implode("", array_fill(0, $arr['cat'], 'I')),
|
|
implode(" ", $arr['ia_controls']),
|
|
$arr['short_title'],
|
|
$status,
|
|
$comments,
|
|
$arr['check_content'],
|
|
''
|
|
]
|
|
)) {
|
|
|
|
}
|
|
|
|
if (php_sapi_name() == 'cli') {
|
|
print "\r" . sprintf("%.02f%%", ($vuln_count / $vulns->length) * 100);
|
|
}
|
|
|
|
$db->update_Running_Scan($base_name, ['name' => 'perc_comp', 'value' => ($vuln_count / $vulns->length) * 100]);
|
|
$vuln_count++;
|
|
}
|
|
|
|
$db->update_Target_Counts($tgt->get_ID());
|
|
|
|
unset($xml);
|
|
if (!isset($cmd['debug'])) {
|
|
rename($cmd['f'], TMP . "/stig_viewer/$base_name");
|
|
}
|
|
$db->update_Running_Scan($base_name, ['name' => 'perc_comp', 'value' => 100, 'complete' => 1]);
|
|
|
|
function usage()
|
|
{
|
|
print <<<EOO
|
|
Purpose: To parse a STIG Viewer output result file
|
|
|
|
Usage: php parse_stig_viewer.php -f={STIG Viewer file} [--debug] [--help]
|
|
|
|
-f={STIG Viewer file} The STIG Viewer result file that is being imported
|
|
|
|
--debug Debugging output
|
|
--help This screen
|
|
|
|
EOO;
|
|
}
|