Newer
Older
DirtyScripts / ReportToolz / repgen.php
root on 18 Nov 2022 18 KB minior changes
  1. #!/usr/bin/php
  2. <?php
  3. //error_reporting(0);
  4. include('config.php');
  5.  
  6. /***
  7. * Main program - Don't edit below
  8. */
  9. echo "_____ _____ _____ Gen\n||_// ||== ||_// \n|| \\ ||___ || \n\n";
  10.  
  11. foreach (glob("classes/*.php") as $filename)
  12. include $filename;
  13.  
  14. $definitions = new \Clapp\CommandLineArgumentDefinition(
  15. array(
  16. "help|h" => "Shows help message",
  17. "path|p=s" => "/path/to/configs/", // should contain config.json and all vuln.json files
  18. )
  19. );
  20.  
  21. $filter = new \Clapp\CommandArgumentFilter($definitions, $argv);
  22.  
  23. if ($filter->getParam('h') === true || $argc < 2) {
  24. fwrite(STDERR, $definitions->getUsage());
  25. exit(0);
  26. }
  27.  
  28. // see if doc exists
  29. if ($filter->getParam("path") == false)
  30. die("[-] no path set\n");
  31.  
  32. echo "[!] path: ".$filter->getParam("path")."\n";
  33. if(!is_dir($filter->getParam("path")))
  34. die("[-] no such folder! \n");
  35.  
  36. //get config file
  37. $config = json_decode(file_get_contents($filter->getParam("path")."config.conf"));
  38. $riskRatings = array("Serious","High","Medium","Low","Info");
  39.  
  40. //create owasp top 10 placeholders
  41. for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"A".$padNo} = 0; }
  42. for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"M".$padNo} = 0; }
  43. for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"API".$padNo} = 0; }
  44.  
  45. //create owasp top 10 table placeholders
  46. for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"A".$padNo."_table"} = ""; }
  47. for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"M".$padNo."_table"} = ""; }
  48. for ($i=1; $i <= 10 ; $i++) { $padNo = sprintf("%02d", $i); ${"API".$padNo."_table"} = ""; }
  49.  
  50. // extract doc and get contents
  51. $rand = uniqid();
  52. mkdir("/tmp/$rand");
  53. if(unzipFolder($template, "/tmp/$rand/")) {
  54. $source = file_get_contents("/tmp/$rand/content.xml");
  55. echo "[+] doc extracted\n";
  56. } else {
  57. die("[-] unable to extract doc\n");
  58. }
  59. $source = file_get_contents("/tmp/$rand/content.xml");
  60. // add CHECK section into report if needed
  61. if(isset($config->checkRef) && trim($config->checkRef) <> ""){
  62. $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">
  63. <draw:image xlink:href="Pictures/10000000000004A3000001C98E2CC6AE1D6F811E.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" loext:mime-type="image/jpeg"/>
  64. </draw:frame>';
  65. $check_section = '<text:p text:style-name="P26"/>
  66. <text:p text:style-name="P26"/>
  67. <text:p text:style-name="P26"/>
  68. <text:p text:style-name="P26"/>
  69. <text:p text:style-name="P26">
  70. CHECK Ref: {checkRef}
  71. </text:p>';
  72. $source = str_replace('{check_img}', $check_img, $source);
  73. $source = str_replace('{check_section}', $check_section, $source);
  74. echo "[+] Added CHECK section\n";
  75. }else{
  76. $check_section = '<text:p text:style-name="P26">
  77. <text:bookmark-start text:name="__RefHeading___Toc72207_536000782"/>
  78. <text:bookmark-end text:name="__RefHeading___Toc72207_536000782"/>
  79. </text:p>';
  80. $source = str_replace('{check_img}', "", $source);
  81. $source = str_replace('{check_section}', $check_section, $source);
  82. }
  83.  
  84. // add config into template
  85. foreach ($config as $key => $value) {
  86. $source = str_replace('{'.$key.'}', $value, $source);
  87. }
  88. file_put_contents("/tmp/$rand/content.xml", $source);
  89. echo "[+] added config values\n";
  90.  
  91. // get all vulns
  92. $vuln = array();
  93. $files = glob($filter->getParam("path")."*.json");
  94. foreach($files as $finding){
  95. $vuln[] = $found = json_decode(file_get_contents($finding), true);
  96. }
  97.  
  98. echo "[+] sorting vulns by CVSS\n";
  99. usort($vuln, 'order_by_cvss');
  100. function order_by_cvss($a, $b) {
  101. return $b['cvss_score'] > $a['cvss_score'] ? 1 : -1;
  102. }
  103.  
  104. if(empty($vuln))
  105. echo "[-] no vulns found!\n";
  106.  
  107. // create vulns for odf
  108. $templateOrig = file_get_contents($vulnTemplate);
  109. $Serious = $High = $Medium = $Low = $Info = "";
  110. $Count_Serious = $Count_High = $Count_Medium = $Count_Low = $Count_Info = 0;
  111. $Summary_Serious = $Summary_High = $Summary_Medium = $Summary_Low = $Summary_Info = array();
  112. foreach ($vuln as $singlevuln) {
  113. $templateSource = $templateOrig;
  114. $togo = $singlevuln['risk'];
  115. foreach ($singlevuln as $key => $value){
  116. $value = str_replace("<", "&lt;", $value);
  117. $value = str_replace(">", "&gt;", $value);
  118. $value = str_replace("\n", "</text:p><text:p text:style-name=\"Text_20_body\">", $value);
  119. $templateSource = str_replace('{'.$key.'}', $value, $templateSource);
  120. if($key == "risk"){
  121. switch ($togo) {
  122. case 'Serious':
  123. $templateSource = str_replace('{risk_img}', '100000000000001C0000001C2B2344F988E3C014.png', $templateSource);
  124. break;
  125. case 'High':
  126. $templateSource = str_replace('{risk_img}', '100000000000001C0000001C478E326DAB1B0673.gif', $templateSource);
  127. break;
  128. case 'Medium':
  129. $templateSource = str_replace('{risk_img}', '100000000000001C0000001C08AD11DB0A5D02CD.png', $templateSource);
  130. break;
  131. case 'Low':
  132. $templateSource = str_replace('{risk_img}', '100000000000001C0000001C6CC3BB57AA64608B.gif', $templateSource);
  133. break;
  134. case 'Info':
  135. $templateSource = str_replace('{risk_img}', '100000000000001C0000001C7365C375D1750C0F.gif', $templateSource);
  136. break;
  137. }
  138. }
  139. }
  140. if(isset($singlevuln['hosts']) && $singlevuln['hosts'] <> ""){
  141. $templateSource = str_replace('{hosts}', $singlevuln['hosts'], $templateSource);
  142. }else{
  143. $templateSource = str_replace('{hosts}', "N/A", $templateSource);
  144. }
  145. $$togo .= $templateSource;
  146. ${"Count_$togo"} += 1;
  147. echo "[+] added $togo: ".$singlevuln['title']."\n";
  148.  
  149. // fixing summary tables
  150. $descExpl = explode(".", $singlevuln['description']);
  151. $fixExpl = explode(".", $singlevuln['solution']);
  152. $descFinal = $descExpl[0].".";
  153. $fixFinal = $fixExpl[0].".";
  154. // if small summaries exist use them!
  155. if(isset($singlevuln['summary_issue']) && $singlevuln['summary_issue'] <> ""){
  156. // DEBUG: echo "[+] summary description found for: ".$singlevuln['title']."\n";
  157. $descFinal = $singlevuln['summary_issue'];
  158. }
  159. if(isset($singlevuln['summary_solution']) && $singlevuln['summary_solution'] <> ""){
  160. // DEBUG: echo "[+] summary solution found for: ".$singlevuln['title']."\n";
  161. $fixFinal = $singlevuln['summary_solution'];
  162. }
  163.  
  164. // set OWASP counts
  165. $issueOwasp = explode(":", $singlevuln['owasp']);
  166. if($issueOwasp[0] !== "N/A")
  167. ${$issueOwasp[0]}++;
  168.  
  169. $hostSummary = (isset($singlevuln['hosts']) && $singlevuln['hosts'] <> "") ? $singlevuln['hosts'] : "N/A";
  170. // populate arrays for small vuln tables
  171. // key = title, 0 = desc, 1 = fix, 2 = hosts, 3 = owasp, 4, page ref
  172. ${"Summary_$togo"}[$singlevuln['title']] = array($descFinal, $fixFinal, $hostSummary, $issueOwasp[0]);
  173. }
  174.  
  175. // add page ref to each issue
  176. $placeA = 1;
  177. foreach ($riskRatings as $riskKey => $riskVal) {
  178. $placeB = 1;
  179. if(!empty( ${"Summary_$riskVal"} )){
  180. foreach (${"Summary_$riskVal"} as $sumKey => $sumVal) {
  181. array_push(${"Summary_$riskVal"}[$sumKey], "5.".$placeA.".".$placeB);
  182. $placeB++;
  183. }
  184. $placeA++;
  185. }
  186. }
  187.  
  188. // create sumaries tables
  189. $Summary_Serious_Final = $Summary_High_Final = $Summary_Medium_Final = $Summary_Low_Final = $Summary_Info_Final = "";
  190. $placeA = 1;
  191. foreach ($riskRatings as $riskKey => $riskVal) {
  192. $placeB = 1;
  193. if(empty( ${"Summary_$riskVal"} )){
  194. ${"Summary_".$riskVal."_Final"} = '
  195. <table:table-row table:style-name="Table11.1">
  196. <table:table-cell table:style-name="Table11.A2" office:value-type="string">
  197. <text:p text:style-name="P189">None Identified</text:p>
  198. </table:table-cell>
  199. <table:table-cell table:style-name="Table11.A2" office:value-type="string">
  200. <text:p text:style-name="P170"/>
  201. </table:table-cell>
  202. <table:table-cell table:style-name="Table11.C2" office:value-type="string">
  203. <text:p text:style-name="P171"/>
  204. </table:table-cell>
  205. <table:table-cell table:style-name="Table11.C2" office:value-type="string">
  206. <text:p text:style-name="P172"/>
  207. </table:table-cell>
  208. </table:table-row>
  209. ';
  210. }else{
  211. foreach (${"Summary_$riskVal"} as $sumKey => $sumVal) {
  212. // DEBUG: echo "[i] $sumKey:\n".$sumVal[0]."\n".$sumVal[1]."\n\n";
  213. ${"Summary_".$riskVal."_Final"} .= '
  214. <table:table-row table:style-name="Table11.1">
  215. <table:table-cell table:style-name="Table11.A2" office:value-type="string">
  216. <text:p text:style-name="P189">'.$sumKey.'</text:p>
  217. <text:p text:style-name="P170">'.$sumVal[0].'</text:p>
  218. </table:table-cell>
  219. <table:table-cell table:style-name="Table11.A2" office:value-type="string">
  220. <text:p text:style-name="P170">'.$sumVal[1].'</text:p>
  221. </table:table-cell>
  222. <table:table-cell table:style-name="Table11.C2" office:value-type="string">
  223. <text:p text:style-name="P171">'.$sumVal[4].'</text:p>
  224. </table:table-cell>
  225. <table:table-cell table:style-name="Table11.C2" office:value-type="string">
  226. <text:p text:style-name="P172">'.$sumVal[2].'</text:p>
  227. </table:table-cell>
  228. </table:table-row>
  229. ';
  230. }
  231. }
  232.  
  233. }
  234.  
  235. //populate owasp findings tables
  236. foreach ($riskRatings as $riskKey => $riskVal) {
  237. if(!empty( ${"Summary_$riskVal"} )){
  238. foreach (${"Summary_$riskVal"} as $sumKey => $sumVal) {
  239. if($sumVal[3] == "N/A")
  240. break; // no N/A owasp table!
  241. if( ${$sumVal[3]."_table"} == ""){ // if is first entry
  242. ${$sumVal[3]."_table"} = '
  243. <table:table table:name="Table8" table:style-name="Table8">
  244. <table:table-column table:style-name="Table8.C"/>
  245. <table:table-column table:style-name="Table8.D"/>
  246. <table:table-header-rows>
  247. <table:table-row table:style-name="Table8.1">
  248. <table:table-cell table:style-name="Table8.A1" office:value-type="string">
  249. <text:p text:style-name="P71">Vulnerabilities in This Category</text:p>
  250. </table:table-cell>
  251. <table:table-cell table:style-name="Table8.B1" office:value-type="string">
  252. <text:p text:style-name="P72">Document Reference</text:p>
  253. </table:table-cell>
  254. </table:table-row>
  255. </table:table-header-rows>
  256. <table:table-row>
  257. <table:table-cell table:style-name="Table8.A10" office:value-type="string">
  258. <text:p text:style-name="P40">'.$sumKey.'</text:p>
  259. </table:table-cell>
  260. <table:table-cell table:style-name="Table8.B2" office:value-type="string">
  261. <text:p text:style-name="P44">'.$sumVal[4].'</text:p>
  262. </table:table-cell>
  263. </table:table-row>
  264. ';
  265. }else{ // not first entry, append new line
  266. ${$sumVal[3]."_table"} = str_replace("</table:table>", "", ${$sumVal[3]."_table"});
  267. ${$sumVal[3]."_table"} .= '
  268. <table:table-row>
  269. <table:table-cell table:style-name="Table8.A10" office:value-type="string">
  270. <text:p text:style-name="P40">'.$sumKey.'</text:p>
  271. </table:table-cell>
  272. <table:table-cell table:style-name="Table8.B2" office:value-type="string">
  273. <text:p text:style-name="P44">'.$sumVal[4].'</text:p>
  274. </table:table-cell>
  275. </table:table-row>
  276. ';
  277. }
  278. // close the table
  279. ${$sumVal[3]."_table"} .= '</table:table>';
  280. }
  281. }
  282. }
  283.  
  284. // squash vulns into one big xml
  285. $value = "";
  286. if(!empty($Serious)){
  287. $value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
  288. <text:list-item>
  289. <text:list>
  290. <text:list-item>
  291. <text:h text:outline-level="2">Serious Risk Vulnerabilities</text:h>
  292. </text:list-item>
  293. </text:list>
  294. </text:list-item>
  295. </text:list>';
  296. $value .= $Serious;
  297. }
  298.  
  299. if(!empty($High)){
  300. $value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
  301. <text:list-item>
  302. <text:list>
  303. <text:list-item>
  304. <text:h text:outline-level="2">High Risk Vulnerabilities</text:h>
  305. </text:list-item>
  306. </text:list>
  307. </text:list-item>
  308. </text:list>';
  309. $value .= $High;
  310. }
  311. if(!empty($Medium)){
  312. $value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
  313. <text:list-item>
  314. <text:list>
  315. <text:list-item>
  316. <text:h text:outline-level="2">Medium Risk Vulnerabilities</text:h>
  317. </text:list-item>
  318. </text:list>
  319. </text:list-item>
  320. </text:list>';
  321. $value .= $Medium;
  322. }
  323. if(!empty($Low)){
  324. $value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
  325. <text:list-item>
  326. <text:list>
  327. <text:list-item>
  328. <text:h text:outline-level="2">Low Risk Vulnerabilities</text:h>
  329. </text:list-item>
  330. </text:list>
  331. </text:list-item>
  332. </text:list>';
  333. $value .= $Low;
  334. }
  335. if(!empty($Info)){
  336. $value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
  337. <text:list-item>
  338. <text:list>
  339. <text:list-item>
  340. <text:h text:outline-level="2">Informational Risk Vulnerabilities</text:h>
  341. </text:list-item>
  342. </text:list>
  343. </text:list-item>
  344. </text:list>';
  345. $value .= $Info;
  346. }
  347. // add to template
  348. $source = file_get_contents("/tmp/$rand/content.xml");
  349. $source = str_replace('{vuln}', $value, $source);
  350.  
  351. //update total counts in exec summary table
  352. $source = str_replace('{count_serious}', $Count_Serious, $source);
  353. $source = str_replace('{count_high}', $Count_High, $source);
  354. $source = str_replace('{count_medium}', $Count_Medium, $source);
  355. $source = str_replace('{count_low}', $Count_Low, $source);
  356. echo "[+] added exec summary counts: $Count_Serious, $Count_High, $Count_Medium, $Count_Low\n";
  357.  
  358. //update issues summary tables
  359. $source = str_replace('{summary_table_serious}', $Summary_Serious_Final, $source);
  360. $source = str_replace('{summary_table_high}', $Summary_High_Final, $source);
  361. $source = str_replace('{summary_table_medium}', $Summary_Medium_Final, $source);
  362. $source = str_replace('{summary_table_low}', $Summary_Low_Final, $source);
  363. $source = str_replace('{summary_table_info}', $Summary_Info_Final, $source);
  364. echo "[+] added findings summary tables\n";
  365.  
  366. //update owasp count tables
  367. for ($i=1; $i <= 10 ; $i++) {
  368. $padNo = sprintf("%02d", $i);
  369. $source = str_replace('{A'.$padNo.'}', ${"A".$padNo}, $source);
  370. }
  371. for ($i=1; $i <= 10 ; $i++) {
  372. $padNo = sprintf("%02d", $i);
  373. $source = str_replace('{M'.$padNo.'}', ${"M".$padNo}, $source);
  374. }
  375. for ($i=1; $i <= 10 ; $i++) {
  376. $padNo = sprintf("%02d", $i);
  377. $source = str_replace('{API'.$padNo.'}', ${"API".$padNo}, $source);
  378. }
  379. echo "[+] updated OWASP count tables\n";
  380.  
  381. //update owasp findings tables
  382. for ($i=1; $i <= 10 ; $i++) {
  383. $padNo = sprintf("%02d", $i);
  384. $source = str_replace('{A'.$padNo.'_table}', ${"A".$padNo."_table"}, $source);
  385. }
  386. for ($i=1; $i <= 10 ; $i++) {
  387. $padNo = sprintf("%02d", $i);
  388. $source = str_replace('{M'.$padNo.'_table}', ${"M".$padNo."_table"}, $source);
  389. }
  390. for ($i=1; $i <= 10 ; $i++) {
  391. $padNo = sprintf("%02d", $i);
  392. $source = str_replace('{API'.$padNo.'_table}', ${"API".$padNo."_table"}, $source);
  393. }
  394. echo "[+] updated OWASP findings tables\n";
  395.  
  396. // save to file
  397. echo "[!] writing to /tmp content.xml\n";
  398. file_put_contents("/tmp/$rand/content.xml", $source);
  399.  
  400. // create report and tidying
  401. $repOutName = $config->ref.".3 ".$config->client ." ". $config->title1;
  402. zipFolder("/tmp/$rand", $filter->getParam("path").$repOutName.".odt");
  403. echo "[=] generated report: ".$filter->getParam("path").$repOutName.".odt\n";
  404. delTree("/tmp/$rand");
  405. echo "[+] temp files removed\n";
  406.  
  407. function unzipFolder($zipInputFile, $outputFolder) {
  408. $zip = new ZipArchive;
  409. $res = $zip->open($zipInputFile);
  410. if ($res === true) {
  411. $zip->extractTo($outputFolder);
  412. $zip->close();
  413. return true;
  414. }
  415. else {
  416. return false;
  417. }
  418. }
  419.  
  420. function XML2Array(SimpleXMLElement $parent){
  421. $array = array();
  422.  
  423. foreach ($parent as $name => $element) {
  424. ($node = & $array[$name])
  425. && (1 === count($node) ? $node = array($node) : 1)
  426. && $node = & $node[];
  427.  
  428. $node = $element->count() ? XML2Array($element) : trim($element);
  429. }
  430.  
  431. return $array;
  432. }
  433.  
  434. function delTree($dir){
  435. $files = array_diff(scandir($dir), array('.', '..'));
  436.  
  437. foreach ($files as $file) {
  438. (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
  439. }
  440.  
  441. return rmdir($dir);
  442. }
  443.  
  444. function zipFolder($inputFolder, $zipOutputFile) {
  445. if (!extension_loaded('zip') || !file_exists($inputFolder)) {
  446. return false;
  447. }
  448.  
  449. $zip = new ZipArchive();
  450. if (!$zip->open($zipOutputFile, ZIPARCHIVE::CREATE)) {
  451. return false;
  452. }
  453.  
  454. $inputFolder = str_replace('\\', "/", realpath($inputFolder));
  455.  
  456. if (is_dir($inputFolder) === true) {
  457. $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($inputFolder), RecursiveIteratorIterator::SELF_FIRST);
  458.  
  459. foreach ($files as $file) {
  460. $file = str_replace('\\', "/", $file);
  461.  
  462. if (in_array(substr($file, strrpos($file, '/')+1), array('.', '..'))) {
  463. continue;
  464. }
  465.  
  466. $file = realpath($file);
  467.  
  468. if (is_dir($file) === true) {
  469. $dirName = str_replace($inputFolder."/", '', $file."/");
  470. $zip->addEmptyDir($dirName);
  471. }
  472. else if (is_file($file) === true) {
  473. $fileName = str_replace($inputFolder."/", '', $file);
  474. $zip->addFromString($fileName, file_get_contents($file));
  475. }
  476. }
  477. }
  478. else if (is_file($inputFolder) === true) {
  479. $zip->addFromString(basename($inputFolder), file_get_contents($inputFolder));
  480. }
  481.  
  482. return $zip->close();
  483. }
  484.  
  485. ?>
Buy Me A Coffee