#!/usr/bin/php
<?php
//error_reporting(0);
include('config.php');
/***
* Main program - Don't edit below
*/
echo "_____ _____ _____ Gen\n||_// ||== ||_// \n|| \\ ||___ || \n\n";
foreach (glob("classes/*.php") as $filename)
include $filename;
$definitions = new \Clapp\CommandLineArgumentDefinition(
array(
"help|h" => "Shows help message",
"path|p=s" => "/path/to/configs/", // should contain config.json and all vuln.json files
)
);
$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("path") == false)
die("[-] no path set\n");
echo "[!] path: ".$filter->getParam("path")."\n";
if(!is_dir($filter->getParam("path")))
die("[-] no such folder! \n");
//get config file
$config = json_decode(file_get_contents($filter->getParam("path")."config.conf"));
$riskRatings = array("Serious","High","Medium","Low");
//create owasp top 10 placeholders
for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"A".$padNo} = 0; }
for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"M".$padNo} = 0; }
for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"API".$padNo} = 0; }
//create owasp top 10 table placeholders
for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"A".$padNo."_table"} = ""; }
for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"M".$padNo."_table"} = ""; }
for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"API".$padNo."_table"} = ""; }
// extract doc and get contents
$rand = uniqid();
mkdir("/tmp/$rand");
if(unzipFolder($template, "/tmp/$rand/")) {
$source = file_get_contents("/tmp/$rand/content.xml");
echo "[+] doc extracted\n";
} else {
die("[-] unable to extract doc\n");
}
$source = file_get_contents("/tmp/$rand/content.xml");
// add CHECK section into report if needed
if(isset($config->checkRef) && trim($config->checkRef) <> ""){
$check_img = '<draw:frame draw:style-name="fr9" draw:name="FPCheckLogo" text:anchor-type="frame" svg:x="0cm" svg:y="5.879cm" svg:width="6.83cm" svg:height="2.628cm" draw:z-index="40">
<draw:image xlink:href="Pictures/10000000000004A3000001C98E2CC6AE1D6F811E.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" loext:mime-type="image/jpeg"/>
</draw:frame>';
$check_section = '<text:p text:style-name="P26"/>
<text:p text:style-name="P26"/>
<text:p text:style-name="P26"/>
<text:p text:style-name="P26"/>
<text:p text:style-name="P26">
CHECK Ref: {checkRef}
</text:p>';
$source = str_replace('{check_img}', $check_img, $source);
$source = str_replace('{check_section}', $check_section, $source);
echo "[+] Added CHECK section\n";
}else{
$check_section = '<text:p text:style-name="P26">
<text:bookmark-start text:name="__RefHeading___Toc72207_536000782"/>
<text:bookmark-end text:name="__RefHeading___Toc72207_536000782"/>
</text:p>';
$source = str_replace('{check_img}', "", $source);
$source = str_replace('{check_section}', $check_section, $source);
}
// add config into template
foreach ($config as $key => $value) {
$source = str_replace('{'.$key.'}', $value, $source);
}
file_put_contents("/tmp/$rand/content.xml", $source);
echo "[+] added config values\n";
// get all vulns
$vuln = array();
$files = glob($filter->getParam("path")."*.json");
foreach($files as $finding){
$vuln[] = $found = json_decode(file_get_contents($finding), true);
}
echo "[+] sorting vulns by CVSS\n";
usort($vuln, 'order_by_cvss');
function order_by_cvss($a, $b) {
return $b['cvss_score'] > $a['cvss_score'] ? 1 : -1;
}
if(empty($vuln))
echo "[-] no vulns found!\n";
// create vulns for odf
$templateOrig = file_get_contents($vulnTemplate);
$Serious = $High = $Medium = $Low = $Info = "";
$Count_Serious = $Count_High = $Count_Medium = $Count_Low = $Count_Info = 0;
$Summary_Serious = $Summary_High = $Summary_Medium = $Summary_Low = $Summary_Info = array();
foreach ($vuln as $singlevuln) {
$templateSource = $templateOrig;
$togo = $singlevuln['risk'];
foreach ($singlevuln as $key => $value){
$value = str_replace("<", "<", $value);
$value = str_replace(">", ">", $value);
$value = str_replace("\n", "</text:p><text:p text:style-name=\"Text_20_body\">", $value);
$templateSource = str_replace('{'.$key.'}', $value, $templateSource);
if($key == "risk"){
switch ($togo) {
case 'Serious':
$templateSource = str_replace('{risk_img}', '100000000000001C0000001C2B2344F988E3C014.png', $templateSource);
break;
case 'High':
$templateSource = str_replace('{risk_img}', '100000000000001C0000001C478E326DAB1B0673.gif', $templateSource);
break;
case 'Medium':
$templateSource = str_replace('{risk_img}', '100000000000001C0000001C08AD11DB0A5D02CD.png', $templateSource);
break;
case 'Low':
$templateSource = str_replace('{risk_img}', '100000000000001C0000001C6CC3BB57AA64608B.gif', $templateSource);
break;
case 'Info':
$templateSource = str_replace('{risk_img}', '100000000000001C0000001C7365C375D1750C0F.gif', $templateSource);
break;
}
}
}
if(isset($singlevuln['hosts']) && $singlevuln['hosts'] <> ""){
$templateSource = str_replace('{hosts}', $singlevuln['hosts'], $templateSource);
}else{
$templateSource = str_replace('{hosts}', "N/A", $templateSource);
}
$$togo .= $templateSource;
${"Count_$togo"} += 1;
echo "[+] added $togo: ".$singlevuln['title']."\n";
// fixing summary tables
$descExpl = explode(".", $singlevuln['description']);
$fixExpl = explode(".", $singlevuln['solution']);
$descFinal = $descExpl[0].".";
$fixFinal = $fixExpl[0].".";
// if small summaries exist use them!
if(isset($singlevuln['summary_issue']) && $singlevuln['summary_issue'] <> ""){
// DEBUG: echo "[+] summary description found for: ".$singlevuln['title']."\n";
$descFinal = $singlevuln['summary_issue'];
}
if(isset($singlevuln['summary_solution']) && $singlevuln['summary_solution'] <> ""){
// DEBUG: echo "[+] summary solution found for: ".$singlevuln['title']."\n";
$fixFinal = $singlevuln['summary_solution'];
}
// set OWASP counts
$issueOwasp = explode(":", $singlevuln['owasp']);
if($issueOwasp[0] !== "N/A")
${$issueOwasp[0]}++;
$hostSummary = (isset($singlevuln['hosts']) && $singlevuln['hosts'] <> "") ? $singlevuln['hosts'] : "N/A";
// populate arrays for small vuln tables
// key = title, 0 = desc, 1 = fix, 2 = hosts, 3 = owasp, 4, page ref
${"Summary_$togo"}[$singlevuln['title']] = array($descFinal, $fixFinal, $hostSummary, $issueOwasp[0]);
}
// add page ref to each issue
$placeA = 1;
foreach ($riskRatings as $riskKey => $riskVal) {
$placeB = 1;
if(!empty( ${"Summary_$riskVal"} )){
foreach (${"Summary_$riskVal"} as $sumKey => $sumVal) {
array_push(${"Summary_$riskVal"}[$sumKey], "5.".$placeA.".".$placeB);
$placeB++;
}
$placeA++;
}
}
// create sumaries tables
$Summary_Serious_Final = $Summary_High_Final = $Summary_Medium_Final = $Summary_Low_Final = "";
$placeA = 1;
foreach ($riskRatings as $riskKey => $riskVal) {
$placeB = 1;
if(empty( ${"Summary_$riskVal"} )){
${"Summary_".$riskVal."_Final"} = '
<table:table-row table:style-name="Table11.1">
<table:table-cell table:style-name="Table11.A2" office:value-type="string">
<text:p text:style-name="P189">None Identified</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table11.A2" office:value-type="string">
<text:p text:style-name="P170"/>
</table:table-cell>
<table:table-cell table:style-name="Table11.C2" office:value-type="string">
<text:p text:style-name="P171"/>
</table:table-cell>
<table:table-cell table:style-name="Table11.C2" office:value-type="string">
<text:p text:style-name="P172"/>
</table:table-cell>
</table:table-row>
';
}else{
foreach (${"Summary_$riskVal"} as $sumKey => $sumVal) {
// DEBUG: echo "[i] $sumKey:\n".$sumVal[0]."\n".$sumVal[1]."\n\n";
${"Summary_".$riskVal."_Final"} .= '
<table:table-row table:style-name="Table11.1">
<table:table-cell table:style-name="Table11.A2" office:value-type="string">
<text:p text:style-name="P189">'.$sumKey.'</text:p>
<text:p text:style-name="P170">'.$sumVal[0].'</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table11.A2" office:value-type="string">
<text:p text:style-name="P170">'.$sumVal[1].'</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table11.C2" office:value-type="string">
<text:p text:style-name="P171">'.$sumVal[4].'</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table11.C2" office:value-type="string">
<text:p text:style-name="P172">'.$sumVal[2].'</text:p>
</table:table-cell>
</table:table-row>
';
}
}
}
//populate owasp findings tables
foreach ($riskRatings as $riskKey => $riskVal) {
if(!empty( ${"Summary_$riskVal"} )){
foreach (${"Summary_$riskVal"} as $sumKey => $sumVal) {
if($sumVal[3] == "N/A")
break; // no N/A owasp table!
if( ${$sumVal[3]."_table"} == ""){ // if is first entry
${$sumVal[3]."_table"} = '
<table:table table:name="Table8" table:style-name="Table8">
<table:table-column table:style-name="Table8.C"/>
<table:table-column table:style-name="Table8.D"/>
<table:table-header-rows>
<table:table-row table:style-name="Table8.1">
<table:table-cell table:style-name="Table8.A1" office:value-type="string">
<text:p text:style-name="P71">Vulnerabilities in This Category</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table8.B1" office:value-type="string">
<text:p text:style-name="P72">Document Reference</text:p>
</table:table-cell>
</table:table-row>
</table:table-header-rows>
<table:table-row>
<table:table-cell table:style-name="Table8.A10" office:value-type="string">
<text:p text:style-name="P40">'.$sumKey.'</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table8.B2" office:value-type="string">
<text:p text:style-name="P44">'.$sumVal[4].'</text:p>
</table:table-cell>
</table:table-row>
';
}else{ // not first entry, append new line
${$sumVal[3]."_table"} = str_replace("</table:table>", "", ${$sumVal[3]."_table"});
${$sumVal[3]."_table"} .= '
<table:table-row>
<table:table-cell table:style-name="Table8.A10" office:value-type="string">
<text:p text:style-name="P40">'.$sumKey.'</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table8.B2" office:value-type="string">
<text:p text:style-name="P44">'.$sumVal[4].'</text:p>
</table:table-cell>
</table:table-row>
';
}
// close the table
${$sumVal[3]."_table"} .= '</table:table>';
}
}
}
// squash vulns into one big xml
$value = "";
if(!empty($Serious)){
$value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
<text:list-item>
<text:list>
<text:list-item>
<text:h text:outline-level="2">Serious Risk Vulnerabilities</text:h>
</text:list-item>
</text:list>
</text:list-item>
</text:list>';
$value .= $Serious;
}
if(!empty($High)){
$value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
<text:list-item>
<text:list>
<text:list-item>
<text:h text:outline-level="2">High Risk Vulnerabilities</text:h>
</text:list-item>
</text:list>
</text:list-item>
</text:list>';
$value .= $High;
}
if(!empty($Medium)){
$value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
<text:list-item>
<text:list>
<text:list-item>
<text:h text:outline-level="2">Medium Risk Vulnerabilities</text:h>
</text:list-item>
</text:list>
</text:list-item>
</text:list>';
$value .= $Medium;
}
if(!empty($Low)){
$value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
<text:list-item>
<text:list>
<text:list-item>
<text:h text:outline-level="2">Low Risk Vulnerabilities</text:h>
</text:list-item>
</text:list>
</text:list-item>
</text:list>';
$value .= $Low;
}
if(!empty($Info)){
$value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
<text:list-item>
<text:list>
<text:list-item>
<text:h text:outline-level="2">Informational Risk Vulnerabilities</text:h>
</text:list-item>
</text:list>
</text:list-item>
</text:list>';
$value .= $Info;
}
// add to template
$source = file_get_contents("/tmp/$rand/content.xml");
$source = str_replace('{vuln}', $value, $source);
//update total counts in exec summary table
$source = str_replace('{count_serious}', $Count_Serious, $source);
$source = str_replace('{count_high}', $Count_High, $source);
$source = str_replace('{count_medium}', $Count_Medium, $source);
$source = str_replace('{count_low}', $Count_Low, $source);
echo "[+] added exec summary counts: $Count_Serious, $Count_High, $Count_Medium, $Count_Low\n";
//update issues summary tables
$source = str_replace('{summary_table_serious}', $Summary_Serious_Final, $source);
$source = str_replace('{summary_table_high}', $Summary_High_Final, $source);
$source = str_replace('{summary_table_medium}', $Summary_Medium_Final, $source);
$source = str_replace('{summary_table_low}', $Summary_Low_Final, $source);
echo "[+] added findings summary tables\n";
//update owasp count tables
for ($i=1; $i <= 10 ; $i++) {
$padNo = sprintf("%02d", $i);
$source = str_replace('{A'.$padNo.'}', ${"A".$padNo}, $source);
}
for ($i=1; $i <= 10 ; $i++) {
$padNo = sprintf("%02d", $i);
$source = str_replace('{M'.$padNo.'}', ${"M".$padNo}, $source);
}
for ($i=1; $i <= 10 ; $i++) {
$padNo = sprintf("%02d", $i);
$source = str_replace('{API'.$padNo.'}', ${"API".$padNo}, $source);
}
echo "[+] updated OWASP count tables\n";
//update owasp findings tables
for ($i=1; $i <= 10 ; $i++) {
$padNo = sprintf("%02d", $i);
$source = str_replace('{A'.$padNo.'_table}', ${"A".$padNo."_table"}, $source);
}
for ($i=1; $i <= 10 ; $i++) {
$padNo = sprintf("%02d", $i);
$source = str_replace('{M'.$padNo.'_table}', ${"M".$padNo."_table"}, $source);
}
for ($i=1; $i <= 10 ; $i++) {
$padNo = sprintf("%02d", $i);
$source = str_replace('{API'.$padNo.'_table}', ${"API".$padNo."_table"}, $source);
}
echo "[+] updated OWASP findings tables\n";
// save to file
echo "[!] writing to /tmp content.xml\n";
file_put_contents("/tmp/$rand/content.xml", $source);
// create report and tidying
$repOutName = $config->ref.".3 ".$config->client ." ". $config->title1;
zipFolder("/tmp/$rand", $filter->getParam("path").$repOutName.".odt");
echo "[=] generated report: ".$filter->getParam("path").$repOutName.".odt\n";
delTree("/tmp/$rand");
echo "[+] temp files removed\n";
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 zipFolder($inputFolder, $zipOutputFile) {
if (!extension_loaded('zip') || !file_exists($inputFolder)) {
return false;
}
$zip = new ZipArchive();
if (!$zip->open($zipOutputFile, ZIPARCHIVE::CREATE)) {
return false;
}
$inputFolder = str_replace('\\', "/", realpath($inputFolder));
if (is_dir($inputFolder) === true) {
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($inputFolder), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file) {
$file = str_replace('\\', "/", $file);
if (in_array(substr($file, strrpos($file, '/')+1), array('.', '..'))) {
continue;
}
$file = realpath($file);
if (is_dir($file) === true) {
$dirName = str_replace($inputFolder."/", '', $file."/");
$zip->addEmptyDir($dirName);
}
else if (is_file($file) === true) {
$fileName = str_replace($inputFolder."/", '', $file);
$zip->addFromString($fileName, file_get_contents($file));
}
}
}
else if (is_file($inputFolder) === true) {
$zip->addFromString(basename($inputFolder), file_get_contents($inputFolder));
}
return $zip->close();
}
?>