#!/usr/bin/env python
import json
import argparse
from termcolor import colored
from tabulate import tabulate

"""
Script to extract the information, about the WEB Attack Surface identified,
from the JSON output of a NUCLEI scan.

Output flags: -json-export -output scan.json

Sources:
    https://github.com/projectdiscovery/nuclei

Dependencies:
    pip install tabulate colorama termcolor
"""


def load_findings(nuclei_file):
    with open(nuclei_file, mode="r", encoding="latin") as f:
        findings = json.loads(f.read())
    return findings


def summarize_attack_surface(findings):
    as_categories = []
    metrics = {}
    as_category_other_key = "Other"

    for finding in findings:
        tpl_id = finding["template-id"].lower()
        tpl_tags = finding["info"]["tags"]

        if "misconfig" in tpl_tags:
            as_type = "Insecure configuration in place"
        elif "cve" in tpl_tags or "cnvd" in tpl_tags:
            as_type = "Public vulnerabilities (CVE/CNVD)"
        elif "default-login" in tpl_tags:
            as_type = "Default credentials in place"
        elif "panel" in tpl_tags:
            as_type = "Login panel/interface"
        elif ("exposure" in tpl_tags and (tpl_id.endswith("api") or tpl_id.endswith("swagger"))) or tpl_id.startswith("graphql-"):
            as_type = "Web API available"
        elif "exposure" in tpl_tags and "backup" in tpl_tags:
            as_type = "Data exposure via backup files"
        elif "exposure" in tpl_tags and (tpl_id.split("-")[-1] in ["key", "token", "password"] or tpl_id == "credentials-disclosure"):
            as_type = "Credentials exposure"
        elif "honeypot" in tpl_tags:
            as_type = "Honeypots exposed"
        elif "iot" in tpl_tags:
            as_type = "IOT devices exposed"
        elif "tech" in tpl_tags and tpl_id.startswith("default-"):
            as_type = "Default installation in place"
        elif "tech" in tpl_tags and (tpl_id.endswith("-bucket-service") or tpl_id == "s3-detect"):
            as_type = "Cloud bucket storage"
        elif "upload" in tpl_tags:
            as_type = "Upload form exposed"
        elif "exposure" in tpl_tags or "info" in tpl_tags or "tech" in tpl_tags:
            as_type = "Technical information disclosure"
        else:
            as_type = as_category_other_key

        if as_type not in metrics:
            metrics[as_type] = 0
        metrics[as_type] = metrics[as_type] + 1

    for key in metrics:
        if key != as_category_other_key:
            as_categories.append([key.capitalize(), metrics[key]])

    if as_category_other_key in metrics:
        as_categories.append([as_category_other_key, metrics[as_category_other_key]])

    return as_categories


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Script to extract the information, about the WEB Attack Surface identified, from the JSON output of a NUCLEI scan.")
    parser.add_argument("-f", action="store", dest="nuclei_file", help="JSON file coming from the NUCLEI scan", required=True)
    args = parser.parse_args()
    nuclei_file = args.nuclei_file
    findings = load_findings(args.nuclei_file)
    print(colored(f"[+] Total of findings:", "yellow"))
    print(len(findings))
    print(colored(f"[+] Web attack surface identified:", "yellow"))
    affected = summarize_attack_surface(findings)
    print(tabulate(affected, headers=["Vector type", "Occurence"]))
