From ca89e02c4e6300fb471189ed3c09ba706ce80ad7 Mon Sep 17 00:00:00 2001 From: Ryan Prather Date: Thu, 8 Nov 2018 17:26:27 -0500 Subject: [PATCH] host_list.inc - Added method to increase finding count system.inc - fixed typo parse_excel_echecklist.php - added functionality to assign OS and checklists based on worksheet contents database.inc - Added a couple methods to support changes for #25 export.php - Minor change to OS listing and added add_cell_comment method to migrate scanner notes to a comment instead of the main note (separating the scanner and anaylst comments) --- classes/host_list.inc | 11 ++++++ classes/system.inc | 6 +-- exec/parse_excel_echecklist.php | 58 +++++++++++++++++++++++++-- inc/database.inc | 69 +++++++++++++++++++++++++++++++-- ste/export.php | 28 ++++++++++++- 5 files changed, 160 insertions(+), 12 deletions(-) diff --git a/classes/host_list.inc b/classes/host_list.inc index 6e1f39c..24f44de 100644 --- a/classes/host_list.inc +++ b/classes/host_list.inc @@ -14,6 +14,7 @@ * - Jan 16, 2018 - File created * - Feb 6, 2018 - Added getter/setter methods * - Nov 6, 2018 - Deleted unused constructor + * - Nov 8, 2018 - Added method to increase finding count */ /** @@ -145,6 +146,16 @@ class host_list { $this->_findingCount = $intFindingCount; } + + /** + * Method to add findings to the count + * + * @param int $intFindingCount + */ + public function addFindingCount($intFindingCount) + { + $this->_findingCount += $intFindingCount; + } /** * Getter function for _scanError diff --git a/classes/system.inc b/classes/system.inc index e5cab1c..8d9f036 100644 --- a/classes/system.inc +++ b/classes/system.inc @@ -110,7 +110,7 @@ class system { /** * System diagram * - * @var binary + * @var mixed */ protected $diagram = null; @@ -294,7 +294,7 @@ class system { /** * Getter function for system diagram * - * @return binary + * @return mixed */ public function get_Diagram() { return $this->diagram; @@ -303,7 +303,7 @@ class system { /** * Setter function for system diagram * - * @param binary $bin_diag_in + * @param mixed $bin_diag_in */ public function set_Diagram($bin_diag_in) { $this->diagram = $bin_diag_in; diff --git a/exec/parse_excel_echecklist.php b/exec/parse_excel_echecklist.php index ed4cc13..fb8e91e 100644 --- a/exec/parse_excel_echecklist.php +++ b/exec/parse_excel_echecklist.php @@ -26,6 +26,7 @@ * - Jan 15, 2018 - Formatting, reorganized use statements, and cleaned up * - May 24, 2018 - Attempt to fix bug #413 * - Nov 6, 2018 - performance improvements, ensure duplicate findings are not created, make eChecklist true status, update for removing findings.id + * - Nov 8, 2018 - added functionality to assign OS and checklists based on worksheet contents */ $cmd = getopt("f:", ['debug::', 'help::']); set_time_limit(0); @@ -112,6 +113,7 @@ else { $scan->set_ID($scan_id); } +/** @var software $gen_os */ $gen_os = $db->get_Software("cpe:/o:generic:generic:-", true); if (is_array($gen_os) && count($gen_os) && isset($gen_os[0]) && is_a($gen_os[0], 'software')) { $gen_os = $gen_os[0]; @@ -139,6 +141,11 @@ foreach ($objSS->getWorksheetIterator() as $wksht) { $log->warning("Invalid headers in {$wksht->getTitle()}"); continue; } + + $chk_arr = explode(', ', $wksht->getCell("B9")->getValue()); + $checklists = $db->get_Checklist_By_Name($chk_arr); + $os_str = $wksht->getCell("G4")->getValue(); + $os = $db->get_Software_By_String($os_str); $idx = [ 'stig_id' => 1, @@ -173,22 +180,59 @@ foreach ($objSS->getWorksheetIterator() as $wksht) { if ($tgt_id = $db->check_Target($conf['ste'], $cell->getValue())) { $log->debug("Found host for {$cell->getValue()}"); + /** @var target $tgt */ $tgt = $db->get_Target_Details($conf['ste'], $tgt_id); if (is_array($tgt) && count($tgt) && isset($tgt[0]) && is_a($tgt[0], 'target')) { $tgt = $tgt[0]; + if($tgt->get_OS_ID() == $gen_os->get_ID() && is_a($os, 'software')) { + $log->debug("Assigning operating system to {$tgt->get_Name()}", [$os]); + $tgt->set_OS_ID($os->get_ID()); + $tgt->set_OS_String($os->get_Shortened_SW_String()); + } } else { $log->error("Could not find host {$cell->getValue()}"); } + + if(is_a($checklists, 'checklist')) { + if(!isset($tgt->checklists[$checklists->get_ID()])) { + $log->debug("Assigning checklists to {$tgt->get_Name()}", [$checklists]); + $tgt->checklists[$checklists->get_ID()] = $checklists; + } + } elseif(is_array($checklists) && count($checklists)) { + $log->debug("Assigning checklists to {$tgt->get_Name()}", $checklists); + foreach($checklists as $c) { + /** @var checklist $c */ + if(!isset($tgt->checklists[$c->get_ID()])) { + $tgt->checklists[$c->get_ID()] = $c; + } + } + } + + $db->save_Target($tgt); } else { $log->debug("Creating new target {$cell->getValue()}"); $tgt = new target($cell->getValue()); - $tgt->set_OS_ID($gen_os->get_ID()); + $tgt->set_OS_ID((is_a($os, 'software') ? $os->get_ID() : $gen_os->get_ID())); + $tgt->set_OS_String((is_a($os, 'software') ? $os->get_Shortened_SW_String() : $gen_os->get_Shortened_SW_String())); $tgt->set_STE_ID($conf['ste']); $tgt->set_Location($conf['location']); $tgt->set_Notes('New Target'); - + + if(is_a($checklists, 'checklist')) { + if(!isset($tgt->checklists[$checklists->get_ID()])) { + $tgt->checklists[$checklists->get_ID()] = $checklists; + } + } elseif(is_array($checklists) && count($checklists)) { + foreach($checklists as $c) { + /** @var checklist $c */ + if(!isset($tgt->checklists[$c->get_ID()])) { + $tgt->checklists[$c->get_ID()] = $c; + } + } + } + if (preg_match('/((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}/', $cell->getValue())) { $ip = $cell->getValue(); $int = new interfaces(null, null, null, $ip, null, null, null, null); @@ -218,9 +262,16 @@ foreach ($objSS->getWorksheetIterator() as $wksht) { $hl->setTargetIp($ip); } - $scan->add_Target_to_Host_List($hl); + if(!isset($scan->get_Host_List()[$tgt->get_ID()])) { + $scan->add_Target_to_Host_List($hl); + } else { + $existingFindingCount = $scan->get_Host_List()[$tgt->get_ID()]->getFindingCount(); + $hl->addFindingCount($existingFindingCount); + $scan->add_Target_to_Host_List($hl); + } } + $db->update_Scan_Host_List($scan); $tgt_findings[$tgt->get_ID()] = $db->get_Finding($tgt); if (preg_match('/overall/i', $cell->getValue())) { @@ -347,7 +398,6 @@ foreach($scan->get_Host_List() as $h) { } unset($objSS); -$db->update_Scan_Host_List($scan, $host_list); if (!isset($cmd['debug'])) { rename($cmd['f'], TMP . "/echecklist/$base_name"); } diff --git a/inc/database.inc b/inc/database.inc index a615e34..951ae34 100644 --- a/inc/database.inc +++ b/inc/database.inc @@ -75,6 +75,7 @@ * - Jun 5, 2018 - Changed set_Setting_Array method to use SQL update instead of replace * - Sep 5, 2018 - Fix for #8 * - Nov 3, 2018 - Fix for fix #62, commented out last INSERT in post_Processing, jao + * - Nov 8, 2018 - Added a couple methods to support changes for #25 */ include_once 'base.inc'; include_once 'software.inc'; @@ -2775,6 +2776,36 @@ class db return $ret; } + + /** + * Function to get the checklists by the checklist name in an eChecklist file + * + * @param array:string $chk_arr + * + * @return array:checklist + */ + public function get_Checklist_By_Name($chk_arr) + { + $ret = []; + $this->help->select("checklist", null, [ + [ + 'field' => "CONCAT(`name`, ' V', `ver`, 'R', `release`, ' (', `type`, ')')", + 'op' => IN, + 'value' => $chk_arr, + 'backticks' => false + ] + ]); + $rows = $this->help->execute(); + if(is_array($rows) && count($rows) && isset($rows[0])) { + foreach($rows as $row) { + $ret[] = new checklist($row['id'], $row['checklist_id'], $row['name'], $row['description'], new DateTime($row['date']), $row['file_name'], $row['ver'], $row['release'], $row['type'], $row['icon']); + } + } elseif(is_array($rows) && count($rows) && isset($rows['id'])) { + $ret = new checklist($rows['id'], $rows['checklist_id'], $rows['name'], $rows['description'], new DateTime($rows['date']), $rows['file_name'], $rows['ver'], $rows['release'], $rows['type'], $rows['icon']); + } + + return $ret; + } /** * Function to get the checklist based on the checklist filename @@ -3202,10 +3233,11 @@ class db if (is_array($chks) && count($chks) && isset($chks[0])) { foreach ($chks as $row) { + /** @var checklist $checklist */ $checklist = $this->get_Checklist($row['id'])[0]; $checklist->set_Classification($row['class']); - $chk[] = $checklist; + $chk[$checklist->get_ID()] = $checklist; } } @@ -9369,6 +9401,37 @@ EOQ; return $ret; } + + /** + * Function to retrieve a software item by using the software string + * + * @param string $sw_string + * + * @return software|NULL + */ + public function get_Software_By_String($sw_string) + { + $ret = null; + $this->help->select("software", null, [ + [ + 'field' => 'sw_string', + 'op' => '=', + 'value' => $sw_string + ] + ], [ + 'limit' => 1 + ]); + $row = $this->help->execute(); + + if(is_array($row) && count($row) && isset($row['id'])) { + $ret = new software($row['cpe'], $row['cpe23']); + $ret->set_ID($row['id']); + $ret->set_SW_String($row['sw_string']); + $ret->set_Shortened_SW_String($row['short_sw_string']); + } + + return $ret; + } /** * Function to retrieve a software item by using the CPE or CPE v2.3 @@ -11683,9 +11746,6 @@ EOQ; Sagacity_Error::err_handler("Failure retrieving the target that was just saved {$tgt->get_Name()}", E_ERROR); } } else { - /* - * @todo get current target and check for OS ID > 2 - */ $exist_tgt = $this->get_Target_Details($tgt->get_STE_ID(), $tgt->get_ID()); if (is_array($exist_tgt) && count($exist_tgt) && isset($exist_tgt[0]) && is_a($exist_tgt[0], 'target')) { $exist_tgt = $exist_tgt[0]; @@ -11837,6 +11897,7 @@ EOQ; ]); $this->help->execute(); + /** @var checklist $chk */ $chk_arr = []; if (is_array($checklists) && count($checklists) && isset($checklists[0]) && is_a($checklists[0], 'checklist')) { foreach ($checklists as $chk) { diff --git a/ste/export.php b/ste/export.php index f8b40a0..f90828d 100644 --- a/ste/export.php +++ b/ste/export.php @@ -29,6 +29,7 @@ * fixed invalid function call to stringFromColumnIndex as it was moved to a different class and changed to 1-based instead of 0-based, * syntax updates, updated PDF writer to Tcpdf class, added die if constant ECHECKLIST_FORMAT is not set as expected * - Jan 15, 2018 - Formatting, updated use statements, not seeing behavior explained in #373 + * - Nov 8, 2018 - Minor change to OS listing and added add_cell_comment method to migrate scanner notes to a comment instead of the main note (separating the scanner and anaylst comments) */ include_once 'config.inc'; include_once 'database.inc'; @@ -377,9 +378,10 @@ function updateHostHeader($sheet, $tgts, &$db) { foreach ($tgts as $tgt_name => $col_id) { $log->notice("tgt_name: $tgt_name\tcol_id: $col_id"); $tgt = $db->get_Target_Details($ste_id, $tgt_name)[0]; + /** @var software $os */ $os = $db->get_Software($tgt->get_OS_ID())[0]; - $oses[] = "{$os->man} {$os->name} {$os->ver}"; + $oses[] = $os->get_SW_String(); $host_names[] = $tgt->get_Name(); if (is_array($tgt->interfaces) && count($tgt->interfaces)) { @@ -505,3 +507,27 @@ function deduplicateString($str) return $ret; } + +/** + * Method to add a comment to a particular cell + * + * @param PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $sheet + * @param string $cell + * @param string $note + */ +function add_cell_comment(&$sheet, $cell, $note) +{ + $sheet->getActiveSheet() + ->getComment($cell) + ->setAuthor(CREATOR); + $commentRichText = $sheet->getActiveSheet() + ->getComment($cell) + ->getText()->createTextRun('Scanner Notes:'); + $commentRichText->getFont()->setBold(true); + $sheet->getActiveSheet() + ->getComment($cell) + ->getText()->createTextRun("\r\n"); + $sheet->getActiveSheet() + ->getComment($cell) + ->getText()->createTextRun($note); +}