285 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			285 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| /**
 | |
|  * File: parse_mbsa.php
 | |
|  * Author: Ryan Prather
 | |
|  * Purpose: Background script to parse MBSA files
 | |
|  * Created: July 3, 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:
 | |
|  *  - July 3, 2014 - File created
 | |
|  *  - Sep 1, 2016 - Copyright Updated, added CWD parameter, and updated functions after class merger
 | |
|  *  - Mar 4, 2017 - Removed Thread class calls
 | |
|  *  - Jun 3, 2017 - Changed to check thread status and die if changed to TERMINATED
 | |
|  */
 | |
| $cmd = getopt("f:s:d:", array('debug::', 'help::'));
 | |
| 
 | |
| if (!isset($cmd['f']) || !isset($cmd['s']) || isset($cmd['help'])) {
 | |
|   usage();
 | |
|   exit;
 | |
| }
 | |
| 
 | |
| include_once 'config.inc';
 | |
| include_once 'helper.inc';
 | |
| include_once 'database.inc';
 | |
| 
 | |
| check_path(TMP . "/mbsa");
 | |
| chdir(TMP);
 | |
| 
 | |
| set_time_limit(0);
 | |
| 
 | |
| $err = new Sagacity_Error($cmd['f']);
 | |
| 
 | |
| if (!file_exists($cmd['f'])) {
 | |
|   $db->update_Running_Scan(basename($cmd['f']), array('name' => 'status', 'value' => 'ERROR'));
 | |
|   $err->script_log("File not found", E_ERROR);
 | |
| }
 | |
| 
 | |
| $db = new db();
 | |
| $base_name = basename($cmd['f']);
 | |
| $host_list = array();
 | |
| 
 | |
| $db->update_Running_Scan($base_name, array('name' => 'pid', 'value' => getmypid()));
 | |
| 
 | |
| $src = $db->get_Sources("MBSA");
 | |
| 
 | |
| $existing_scan = $db->get_ScanData($cmd['s'], $base_name);
 | |
| 
 | |
| if (is_array($existing_scan) && count($existing_scan)) {
 | |
|   $scan = $existing_scan[0];
 | |
| }
 | |
| else {
 | |
|   $dt = new DateTime();
 | |
|   $ste = $db->get_STE($cmd['s'])[0];
 | |
|   $scan = new scan(null, $src, $ste, 0, $base_name, $dt->format("Y-m-d"));
 | |
|   $scan_id = $db->save_Scan($scan);
 | |
| 
 | |
|   $scan->set_ID($scan_id);
 | |
| }
 | |
| 
 | |
| if (substr($base_name, -3) == 'xml') {
 | |
|   $match = array();
 | |
|   if (preg_match('/([^\\\\]+)\-mbsa\.xml/i', $cmd['f'], $match)) {
 | |
|     $tgt_id = get_a_tgt_id($db, $cmd['s'], $match[1], $match[1]);
 | |
|     $tgt = $db->get_Target_Details($cmd['s'], $tgt_id)[0];
 | |
|   }
 | |
|   else {
 | |
|     $err->script_log("File name is not the correct format (hostname)-mbsa.xml required! (" . $base_name . ")", E_ERROR);
 | |
|   }
 | |
| 
 | |
|   $host_list = array(
 | |
|     'target' => $tgt,
 | |
|     'count'  => 0
 | |
|   );
 | |
| 
 | |
|   $xml = new DOMDocument();
 | |
|   $xml->load($cmd['f']);
 | |
| 
 | |
|   $checks = getValue($xml, "/x:XMLOut/x:Check/x:Detail/x:UpdateData", null, true);
 | |
|   foreach ($checks as $check) {
 | |
|     $db->help->select("sagacity.scans", array('status'), array(
 | |
|       array(
 | |
|         'field' => 'id',
 | |
|         'op'    => '=',
 | |
|         'value' => $scan->get_ID()
 | |
|       )
 | |
|     ));
 | |
|     $thread_status = $db->help->execute();
 | |
|     if ($thread_status['status'] == 'TERMINATED') {
 | |
|       unset($xml);
 | |
|       rename(realpath(TMP . "/{$scan->get_File_Name()}"), TMP . "/terminated/{$scan->get_File_Name()}");
 | |
|       $err->script_log("File parsing terminated by user");
 | |
|       die();
 | |
|     }
 | |
| 
 | |
|     $ms = getValue($xml, "@BulletinID", $check);
 | |
|     $kb = getValue($xml, "@KBID", $check) ? "KB" . getValue($xml, "@KBID", $check) : "";
 | |
|     $installed = (getValue($xml, "@IsInstalled", $check) == 'true' ? true : false);
 | |
| 
 | |
|     if ($ms) {
 | |
|       $adv = $db->get_Advisory($ms);
 | |
|       $iavm = $db->get_IAVM_From_External($ms);
 | |
| 
 | |
|       if (is_null($iavm) && $kb) {
 | |
|         $iavm = $db->get_IAVM_From_External($kb);
 | |
|       }
 | |
|     }
 | |
|     elseif ($kb) {
 | |
|       $adv = $db->get_Advisory($kb);
 | |
|       $iavm = $db->get_IAVM_From_External($kb);
 | |
|     }
 | |
|     else {
 | |
|       $adv = null;
 | |
|       $iavm = null;
 | |
|     }
 | |
| 
 | |
|     $err->script_log("$ms/$kb");
 | |
| 
 | |
|     if (is_array($adv) && count($adv)) {
 | |
|       $adv = $adv[0];
 | |
|     }
 | |
| 
 | |
|     if ($iavm && $iavm->get_PDI_ID()) {
 | |
|       $status = 'Open';
 | |
|       if ($installed) {
 | |
|         $status = 'Not a Finding';
 | |
|       }
 | |
| 
 | |
|       $stig = $db->get_Stig($iavm->get_Notice_Number());
 | |
|       if (is_array($stig) && count($stig) && isset($stig[0]) && is_a($stig[0], 'stig')) {
 | |
|         $stig = $stig[0];
 | |
|       }
 | |
| 
 | |
|       $err->script_log("pdi\t=\t" . $stig->get_PDI_ID() . "\tstig\t=\t" . $stig->get_ID());
 | |
| 
 | |
|       $pdi = $db->get_PDI($stig->get_PDI_ID());
 | |
|       $vms = $db->get_GoldDisk_By_PDI($pdi->get_ID());
 | |
|       $ias = $db->get_IA_Controls_By_PDI($pdi->get_ID());
 | |
| 
 | |
|       if (is_array($vms) && count($vms) && isset($vms[0]) && is_a($vms[0], 'stig')) {
 | |
|         $vms = $vms[0];
 | |
|       }
 | |
|       else {
 | |
|         $vms = '';
 | |
|       }
 | |
| 
 | |
|       $finding = $db->get_Finding($tgt, $iavm, $scan);
 | |
| 
 | |
|       if (!count($finding)) {
 | |
|         $ia_str = '';
 | |
|         foreach ($ias as $key => $ia):$ia_str .= $ia->get_Type() . "-" . $ia->get_Type_ID() . " ";
 | |
|         endforeach;
 | |
| 
 | |
|         $finding = array(
 | |
|           0 => $stig->get_ID(),
 | |
|           1 => (is_a($vms, 'golddisk') ? $vms->get_ID() : $vms),
 | |
|           2 => $pdi->get_Category_Level_String(),
 | |
|           3 => $ia_str,
 | |
|           4 => $pdi->get_Short_Title(),
 | |
|           5 => $status,
 | |
|           6 => '(MBSA)',
 | |
|           7 => $pdi->get_Check_Contents(),
 | |
|           8 => ''
 | |
|         );
 | |
| 
 | |
|         $host_list['count'] ++;
 | |
| 
 | |
|         if (!$db->add_Finding($scan, $tgt, $finding)) {
 | |
|           $err->script_log("add finding failure");
 | |
|         }/**/
 | |
|       }
 | |
|       else {
 | |
|         // need to code update for MBSA
 | |
|       }
 | |
|     }
 | |
|     else {
 | |
|       $err->script_log("don't have iavm");
 | |
|       $cves = getValue($xml, "x:OtherIDs/x:OtherID[@Type='CVE']", $check, true);
 | |
| 
 | |
|       if ($cves->length) {
 | |
|         foreach ($cves as $cve) {
 | |
|           $db_cve = $db->get_CVE($cve->textContent);
 | |
| 
 | |
|           if ($db_cve) {
 | |
|             if (count($db_cve->get_IAVM())) {
 | |
|               $iavm = $db->get_IAVM($db_cve->get_IAVM()[0]);
 | |
|             }
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         if ($iavm && $iavm->get_PDI_ID()) {
 | |
|           $err->script_log("found one");
 | |
|           $status = 'Open';
 | |
|           if ($installed) {
 | |
|             $status = 'Not a Finding';
 | |
|           }
 | |
| 
 | |
|           $pdi = $db->get_PDI($iavm->get_PDI_ID());
 | |
|           $vms = $db->get_GoldDisk_By_PDI($pdi->get_ID());
 | |
|           $ias = $db->get_IA_Controls_By_PDI($pdi->get_ID());
 | |
| 
 | |
|           if (is_array($vms) && count($vms)) {
 | |
|             $vms = $vms[0];
 | |
|           }
 | |
|           else {
 | |
|             $vms = '';
 | |
|           }
 | |
| 
 | |
|           $finding = $db->get_Finding($tgt, $iavm, $scan);
 | |
| 
 | |
|           if (!count($finding)) {
 | |
|             $ia_str = '';
 | |
|             foreach ($ias as $key => $ia):$ia_str .= $ia->get_Type() . "-" . $ia->get_Type_ID() . " ";
 | |
|             endforeach;
 | |
| 
 | |
|             $finding = array(
 | |
|               0 => $iavm->get_Notice_Number(),
 | |
|               1 => (is_a($vms, 'golddisk') ? $vms->get_ID() : $vms),
 | |
|               2 => $pdi->get_Category_Level_String(),
 | |
|               3 => $ia_str,
 | |
|               4 => $pdi->get_Short_Title(),
 | |
|               5 => $status,
 | |
|               6 => '',
 | |
|               7 => $pdi->get_Check_Contents(),
 | |
|               8 => ''
 | |
|             );
 | |
| 
 | |
|             $host_list['count'] ++;
 | |
| 
 | |
|             if (!$db->add_Finding($scan, $tgt, $finding)) {
 | |
|               $err->script_log("add finding failure");
 | |
|             }/**/
 | |
|           }
 | |
|           else {
 | |
| 
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       else {
 | |
|         $cve = $db->get_CVE_From_External(substr($kb, 2));
 | |
|         if ($cve && $cve->get_PDI_ID()) {
 | |
|           $err->script_log("found one");
 | |
|           $err->script_log("pdi: " . $cve->get_PDI_ID());
 | |
|         }
 | |
|         else {
 | |
|           $err->script_log("still don't have it");
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| elseif (substr($base_name, -3) == 'txt') {
 | |
| 
 | |
| }
 | |
| 
 | |
| $db->update_Scan_Host_List($scan, array(0 => $host_list));
 | |
| if (!isset($cmd['debug'])) {
 | |
|   rename($cmd['f'], DOC_ROOT . "/tmp/mbsa/$base_name");
 | |
| }
 | |
| $db->update_Running_Scan($base_name, array('name' => 'perc_comp', 'value' => 100, 'complete' => 1));
 | |
| 
 | |
| function usage() {
 | |
|   print <<<EOO
 | |
| Purpose: To import an MBSA result file
 | |
| 
 | |
| Usage: php parse_mbsa.php -s={ST&E ID} -f={result file} [--debug] [--help]
 | |
| 
 | |
|  -s={ST&E ID}       The ST&E ID this result file is being imported for
 | |
|  -f={result file}   The result file to import
 | |
| 
 | |
|  --debug            Debugging output
 | |
|  --help             This screen
 | |
| 
 | |
| EOO;
 | |
| }
 |