- #!/usr/bin/php
- <?php
- //error_reporting(0);
-
- /***
- * Configuration options
- */
- $sub1 = 5; // header no in doc e.g. "5 Discovered Vulnerabilities"
-
- /***
- * Main program - Don't edit below
- */
- echo "_____ _____ _____ 2\n||_// ||== ||_// \n|| \\ ||___ || \n\n";
-
- foreach (glob("classes/*.php") as $filename)
- include $filename;
-
- $definitions = new \Clapp\CommandLineArgumentDefinition(
- array(
- "help|h" => "Shows help message",
- "doc|d=s" => "/path/to/doc.odt to use",
- )
- );
-
- $filter = new \Clapp\CommandArgumentFilter($definitions, $argv);
-
- if ($filter->getParam('h') === true || $argc < 2) {
- fwrite(STDERR, $definitions->getUsage());
- exit(0);
- }
-
- // see if doc exists
- if ($filter->getParam("doc") == false)
- die("[-] no doc set\n");
-
- echo "[!] doc: ".$filter->getParam("doc")."\n";
- if(!file_exists($filter->getParam("doc")))
- die("[-] no such file! \n");
-
- // extract doc and get contents
- $rand = uniqid();
- mkdir("/tmp/$rand");
- if(unzipFolder($filter->getParam("doc"), "/tmp/$rand/")) {
- $source = file_get_contents("/tmp/$rand/content.xml");
- echo "[+] doc extracted\n";
- } else {
- die("[-] unable to extract doc\n");
- }
-
- // Parse Doc's XML
- $line = array();
- $reader = new XMLReader();
- if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n");
-
- // font checker
- /***
- * FUTURE FEATURE PERHAPS
- */
- $fonts = array();
- while ($reader->read()){
- //print_r($reader->name);
- if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'style:font-face')) {
- //if(!empty($reader->name)){
- //echo "here2\n";
- //$line[] = $reader->expand()->textContent; // Put the text into array in correct order...
- $fonts[] = $reader->getAttribute("style:name");
- //echo $font;echo "\n"; // DEBUG
- //}
- }
- }
- $reader->close();
- //die();
- echo "[=] fonts found: ".sizeof($fonts)."\n";
-
- // get template version used
- $reader = new XMLReader();
- if (!$reader->open("/tmp/$rand/meta.xml")) die("[-] Failed to open 'meta.xml'\n");
- $templateVer = 0.0;
- while ($reader->read()) {
- if($reader->name == "dc:version"){
- $reader->read();
- $templateVer = number_format(floatval($reader->value), 2);
- break;
- }
- }
-
- // step through text:h and text:p elements to put them into an array
- $reader = new XMLReader();
- if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n");
- while ($reader->read()){
- if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'text:h' || $reader->name === 'text:p' || $reader->name === 'text:bookmark')) {
- if(!empty($reader->expand()->textContent))
- $line[] = $reader->expand()->textContent; // Put the text into array in correct order...
- //echo $reader->expand()->textContent;echo "\n"; // DEBUG
- }
- }
- $reader->close();
-
- // find the content we want
- $start = 0; $end = 0;
- foreach($line as $key => $val){
- //if(strpos($val, "Discovered Vulnerabilities") === 0){ $start = $key; }
- if(preg_match('/Discovered *\w* Vulnerabilities/', $val, $matches) === true){ $start = $key; }
- //if(strpos($val, "This section provides a quick guide to plan your remediation for the vulnerabilities discovered during the test.") === 0){ $end = $key-2; }
- if(strpos($val, "Observed Hosts and Services") === 0){ $end = $key-2; }
- $line[$key] = trim($val);
- }
-
- // add to sexy array's
- $vuln = array();
- $vulnPlace = 0;
- $switch = 0;
- $sub2 = 0;
- $sub3 = 1;
- if(number_format($templateVer, 2) >= number_format(1.0, 2)){
- echo "[=] Template $templateVer used\n";
- for ($i=$start; $i <= $end ; $i++) {
- // change state (action to take)
- /***
- * ~states~
- * 0 = do nothing
- * 1 = next is title
- * 2 = next is description
- * 3 = next is solution
- * 4 = next is remediation
- * 5 = next is cvss no
- * 6 = next is risk level
- * 7 = next is hosts
- * 8 = next possibly title
- */
-
- switch ($line[$i]) {
- case (preg_match('/Discovered *\w* Vulnerabilities/', $val, $matches) === true):
- $switch = 0;
- break;
- case 'Serious Risk Vulnerabilities':
- $sub2++; $sub3 = 1;
- $switch = 1;
- break;
- case 'High Risk Vulnerabilities':
- $sub2++; $sub3 = 1;
- $switch = 1;
- break;
- case 'Medium Risk Vulnerabilities':
- $sub2++; $sub3 = 1;
- $switch = 1;
- break;
- case 'Low Risk Vulnerabilities':
- $sub2++; $sub3 = 1;
- $switch = 1;
- break;
- case 'Informational Risk Vulnerabilities':
- $sub2++; $sub3 = 1;
- $switch = 1;
- break;
- case 'Description':
- $switch = 2;
- break;
- case 'Solution':
- $switch = 3;
- break;
- case 'Remediation':
- $switch = 4;
- break;
- case 'CVSS Base Score':
- $switch = 5;
- break;
- case 'Risk Analysis':
- $switch = 6;
- break;
- case 'Vulnerabilities Exist On':
- $switch = 7;
- break;
- case 'Potential Impact':
- $switch = 9;
- break;
- default:
- # code...
- break;
- }
-
- //take action
- switch ($switch) {
- case 1:
- $i++;
- $vuln[$vulnPlace]['title'] = $line[$i];
- $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3";
- $sub3++;
- $switch = 0;
- break;
- case 2:
- @$vuln[$vulnPlace]['desc'] .= $line[$i];
- break;
- case 3:
- @$vuln[$vulnPlace]['fix'] .= $line[$i];
- break;
- case 4:
- $i++;
- //$vuln[$vulnPlace]['rem'] = trim(strtok($line[$i], " "));
- $switch = 0;
- break;
- case 5:
- $i++;
- $vuln[$vulnPlace]['cvss'] = $line[$i];
- $switch = 0;
- break;
- case 6:
- $i++;
- $line[$i+3] = str_replace("Vulnerability Img", "", $line[$i+3]);
- $vuln[$vulnPlace]['risk'] = strstr(trim($line[$i+3]), ":", true);
- $vuln[$vulnPlace]['owasp'] = trim(substr($line[$i+3], strpos($line[$i+3], ":") + 1));
- $vuln[$vulnPlace]['impact'] = trim(strtok($line[$i+4], " "));
- $vuln[$vulnPlace]['rem'] = trim(strtok($line[$i+5], " "));
- $switch = 0;
- break;
- case 7:
- $i++;
- $vuln[$vulnPlace]['hosts'] = $line[$i];
- $switch = 8;
- $vulnPlace++;
- break;
- case 8:
- $vuln[$vulnPlace]['title'] = trim($line[$i]);
- $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3";
- $sub3++;
- $switch = 0;
- break;
- case 9:
- @$vuln[$vulnPlace]['impact'] .= $line[$i];
- break;
- default:
- # code...
- break;
- }
-
- //echo $line[$i]."\n"; // DEBUG
- }
- $first_desc = explode("Description", $vuln[0]['desc']);
-
- $vuln[0]['desc'] = $first_desc[sizeof($first_desc)-1];
- }else{ // old template or Dave's format
- for ($i=$start; $i <= $end ; $i++) {
- // change state (action to take)
- /***
- * ~states~
- * 0 = do nothing
- * 1 = next is title
- * 2 = next is description
- * 3 = next is solution
- * 4 = next is remediation
- * 5 = next is cvss no
- * 6 = next is risk level
- * 7 = next is hosts
- * 8 = next possibly title
- */
- echo $line[$i]."\n";
- switch ($line[$i]) {
- case 'Discovered Vulnerabilities':
- $switch = 0;
- break;
- case 'Serious Risk Vulnerabilities':
- $sub2++; $sub3 = 1;
- $switch = 1;
- break;
- case 'High Risk Vulnerabilities':
- $sub2++; $sub3 = 1;
- $switch = 1;
- break;
- case 'Medium Risk Vulnerabilities':
- $sub2++; $sub3 = 1;
- $switch = 1;
- break;
- case 'Low Risk Vulnerabilities':
- $sub2++; $sub3 = 1;
- $switch = 1;
- break;
- case 'Informational Risk Vulnerabilities':
- $sub2++; $sub3 = 1;
- $switch = 1;
- break;
- case 'Description':
- $switch = 2;
- break;
- case 'Solution':
- $switch = 3;
- break;
- case 'Remediation':
- $switch = 4;
- break;
- case 'CVSS Base Score':
- $switch = 5;
- break;
- case 'Risk Level':
- $switch = 6;
- break;
- case 'Vulnerabilities Exist On':
- $switch = 7;
- break;
- case 'Potential Impact':
- $switch = 9;
- break;
- default:
- # code...
- break;
- }
-
- //take action
- switch ($switch) {
- case 1:
- $i++;
- $vuln[$vulnPlace]['title'] = $line[$i];
- $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3";
- $sub3++;
- $switch = 0;
- break;
- case 2:
- @$vuln[$vulnPlace]['desc'] .= $line[$i];
- break;
- case 3:
- @$vuln[$vulnPlace]['fix'] .= $line[$i];
- break;
- case 4:
- $i++;
- $vuln[$vulnPlace]['rem'] = trim(strtok($line[$i], " "));
- $switch = 0;
- break;
- case 5:
- $i++;
- $vuln[$vulnPlace]['cvss'] = $line[$i];
- $switch = 0;
- break;
- case 6:
- $i++;
- $vuln[$vulnPlace]['risk'] = trim(strtok($line[$i], " "));
- $vuln[$vulnPlace]['owasp'] = trim(substr($line[$i], strpos($line[$i], ":") + 1));
- $switch = 0;
- break;
- case 7:
- $i++;
- $vuln[$vulnPlace]['hosts'] = $line[$i];
- $switch = 8;
- $vulnPlace++;
- break;
- case 8:
- $vuln[$vulnPlace]['title'] = trim($line[$i]);
- $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3";
- $sub3++;
- $switch = 0;
- break;
- case 9:
- @$vuln[$vulnPlace]['impact'] .= $line[$i];
- break;
- default:
- # code...
- break;
- }
-
- //echo $line[$i]."\n"; // DEBUG
- }
- }
-
- // get all vulns.json if there are any
- $currentPath = dirname($filter->getParam("doc"));
- $jsonVuln = array();
- $jsonFiles = glob($currentPath."/*.json");
- foreach($jsonFiles as $finding){
- $placeholder = json_decode(file_get_contents($finding), true);
- if(isset($placeholder['title'])) // is a vuln and not config file
- $jsonVuln[] = $placeholder;
- }
-
- // minor tidying of arrays
- for ($i=0; $i < sizeof($vuln) ; $i++) {
- if (strpos($vuln[$i]['desc'], "Description") === 0) $vuln[$i]['desc'] = substr($vuln[$i]['desc'], strlen("Description"));
- if (strpos($vuln[$i]['fix'], "Solution") === 0) $vuln[$i]['fix'] = substr($vuln[$i]['fix'], strlen("Solution"));
- $vuln[$i]['risk'] = rtrim($vuln[$i]['risk'], ":");
- // remove html encoding
- foreach($vuln[$i] as $key => $val){
- $vuln[$i][$key] = mb_convert_encoding($val, "UTF-8", 'UTF-8');
- }
-
- // fixing summary tables
- $descExpl = explode(".", $vuln[$i]['desc']);
- $fixExpl = explode(".", $vuln[$i]['fix']);
- $vuln[$i]['desc'] = $descExpl[0].".";
- $vuln[$i]['fix'] = $fixExpl[0].".";
- foreach($jsonVuln as $id => $jsonIssue){
- if($jsonIssue['title'] == $vuln[$i]['title']){
-
- if((isset($jsonIssue['summary_issue']) && $jsonIssue['summary_issue'] <> "") || (isset($jsonIssue['summary_solution']) && $jsonIssue['summary_solution'] <> "")){
- echo "[+] summary found for: ".$vuln[$i]['title']."\n";
- $vuln[$i]['desc'] = $jsonIssue['summary_issue'];
- $vuln[$i]['fix'] = $jsonIssue['summary_solution'];
- }
- }
- }
-
-
- }
-
- //print_r($vuln); // DEBUG
- echo "[+] vulnerabilities identified\n";
-
- delTree("/tmp/$rand");
- echo "[+] temp files removed\n";
-
- $resultsFolder = substr($filter->getParam("doc"), 0, strrpos( $filter->getParam("doc"), '/') )."/rep2";
- if(!file_exists($resultsFolder."/")){
- mkdir($resultsFolder."/");
- echo "[+] created directory $resultsFolder/\n";
- }else{
- $i = 1;
- while (file_exists($resultsFolder."_$i/"))
- $i++;
- mkdir($resultsFolder."_$i/");
- $resultsFolder .= "_$i";
- echo "[+] created directory $resultsFolder/\n";
- }
-
- if(writeIssueTable($vuln, "Serious", $resultsFolder."/findings_serious.csv"))
- echo "[+] serious issues: $resultsFolder/findings_serious.csv\n";
- if(writeIssueTable($vuln, "High", $resultsFolder."/findings_high.csv"))
- echo "[+] high issues: $resultsFolder/findings_high.csv\n";
- if(writeIssueTable($vuln, "Medium", $resultsFolder."/findings_medium.csv"))
- echo "[+] medium issues: $resultsFolder/findings_medium.csv\n";
- if(writeIssueTable($vuln, "Low", $resultsFolder."/findings_low.csv"))
- echo "[+] low issues: $resultsFolder/findings_low.csv\n";
- if(writeIssueTable($vuln, "Info", $resultsFolder."/findings_info.csv"))
- echo "[+] info issues: $resultsFolder/findings_info.csv\n";
-
- $order = array('title', 'ref', 'desc', 'fix','rem','cvss','risk','impact','owasp','hosts');
- $orderedArray = array();
- foreach($vuln as $vn_no =>$vn){
- foreach ($order as $key) {
- //echo $key."\n";
- $orderedArray[$vn_no][$key] = $vuln[$vn_no][$key];
- }
- }
- if(writeAllTable($orderedArray, $resultsFolder."/findings_all.csv"))
- echo "[+] all issues: $resultsFolder/findings_all.csv\n";
-
- if(writeRemediationTable($vuln, $resultsFolder."/remediation.csv"))
- echo "[+] remediation table: $resultsFolder/remediation.csv\n";
-
- if(writeOWASPTable($vuln, $resultsFolder."/owasp.csv"))
- echo "[+] OWASP table: $resultsFolder/owasp.csv\n";
-
- viewVulns($vuln);
-
- function unzipFolder($zipInputFile, $outputFolder) {
- $zip = new ZipArchive;
- $res = $zip->open($zipInputFile);
- if ($res === true) {
- $zip->extractTo($outputFolder);
- $zip->close();
- return true;
- }
- else {
- return false;
- }
- }
-
- function XML2Array(SimpleXMLElement $parent){
- $array = array();
-
- foreach ($parent as $name => $element) {
- ($node = & $array[$name])
- && (1 === count($node) ? $node = array($node) : 1)
- && $node = & $node[];
-
- $node = $element->count() ? XML2Array($element) : trim($element);
- }
-
- return $array;
- }
-
- function delTree($dir){
- $files = array_diff(scandir($dir), array('.', '..'));
-
- foreach ($files as $file) {
- (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
- }
-
- return rmdir($dir);
- }
-
- function viewVulns($vuln){
- $s = $h = $m = $l = $i = 0 ;
- for ($j=0; $j < sizeof($vuln) ; $j++) {
- switch ($vuln[$j]['risk']) {
- case 'Serious':
- $s++;
- break;
- case 'High':
- $h++;
- break;
- case 'Medium':
- $m++;
- break;
- case 'Low':
- $l++;
- break;
- case 'Info':
- $i++;
- break;
- }
- }
- echo "[=] Serious = $s, High = $h, Medium = $m, Low = $l, Info = $i\n";
-
- echo"
- Ref | Title | Risk | CVSS | Remediation | OWASP
- -------|-----------------------------------|--------|--------|---------------|------------------------------\n";
- for ($i=0; $i < sizeof($vuln) ; $i++) {
- $ref = str_pad($vuln[$i]['ref'], 7);
- $title = str_pad($vuln[$i]['title'], 35);
- $risk = str_pad($vuln[$i]['risk'], 8);
- $cvs1 = explode("-", $vuln[$i]['cvss']);
- $cvss = str_pad($cvs1[0], 8);
- $rem = str_pad($vuln[$i]['rem'], 15);
- $owasp = str_pad($vuln[$i]['owasp'], 30);
-
- echo substr($ref, 0, 7); echo "|";
- echo substr($title, 0, 35); echo "|";
- echo substr($risk, 0, 8); echo "|";
- echo substr($cvss, 0, 8); echo "|";
- echo substr($rem, 0, 15); echo "|";
- echo substr($owasp, 0, 30); echo "\n";
- }
- }
-
- function writeIssueTable($vuln, $issue, $path){
- $towrite = array();
- for ($i=0; $i < sizeof($vuln) ; $i++) {
- if($vuln[$i]['risk'] == $issue){
- $towrite[$i]['desc'] = $vuln[$i]['title']." - ".$vuln[$i]['desc'];
- $towrite[$i]['fix'] = $vuln[$i]['fix'];
- $towrite[$i]['ref'] = $vuln[$i]['ref'];
- $towrite[$i]['hosts'] = $vuln[$i]['hosts'];
- }
- }
- if(sizeof($towrite) > 0){
- $fp = fopen($path, 'w');
- fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
- foreach ($towrite as $fields) {
- fputcsv($fp, $fields);
- }
- fclose($fp);
- return true;
- }else{
- return false;
- }
- }
-
- function writeAllTable($vuln, $path){
- if(sizeof($vuln) > 0){
- $fp = fopen($path, 'w');
- fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
- fputcsv($fp, array("Title", "Ref", "Description", "Solution", "Remediation", "CVSS", "Risk","Impact", "OWASP", "Affected"));
-
- //print_r($orderedArray);
- foreach ($vuln as $fields) {
- fputcsv($fp, $fields);
- }
- fclose($fp);
- return true;
- }else{
- return false;
- }
- }
-
- function writeRemediationTable($vuln, $path){
- $towrite = array();
- for ($i=0; $i < sizeof($vuln) ; $i++) {
- $towrite[$i]['hosts'] = $vuln[$i]['hosts'];
- $towrite[$i]['ref'] = $vuln[$i]['ref'];
- $towrite[$i]['p'] = " ";
- $towrite[$i]['c'] = " ";
- $towrite[$i]['d'] = " ";
- $towrite[$i]['u'] = " ";
- switch ($vuln[$i]['rem']) {
- case 'Patch':
- $towrite[$i]['p'] = $vuln[$i]['risk'][0];
- break;
- case 'Configuration':
- $towrite[$i]['c'] = $vuln[$i]['risk'][0];
- break;
- case 'Development':
- $towrite[$i]['d'] = $vuln[$i]['risk'][0];
- break;
- case 'Upgrade':
- $towrite[$i]['u'] = $vuln[$i]['risk'][0];
- break;
- }
- }
- if(sizeof($towrite) > 0){
- $fp = fopen($path, 'w');
- fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
- fputcsv($fp, array("Host", "Ref", "P", "C", "D", "U"));
- foreach ($towrite as $fields) {
- fputcsv($fp, $fields);
- }
- fclose($fp);
- return true;
- }else{
- return false;
- }
- }
-
- function writeOWASPTable($vuln, $path){
- $towrite = array();
- for ($i=0; $i < sizeof($vuln) ; $i++) {
- if(in_array($vuln[$i]['owasp'], array_column($towrite, 'owaspId'))){
- $towrite[$vuln[$i]['owasp']]['no']++;
- }else{
- $towrite[$vuln[$i]['owasp']]['owaspId'] = $vuln[$i]['owasp'];
- $towrite[$vuln[$i]['owasp']]['no'] = 1;
- }
- }
- if(sizeof($towrite) > 0){
- $fp = fopen($path, 'w');
- fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
- foreach ($towrite as $fields) {
- fputcsv($fp, $fields);
- }
- fclose($fp);
- return true;
- }else{
- return false;
- }
- }
-
- ?>