From cc1a1266fc9b5e2b89cf4ce2b4810b6375b1b9a3 Mon Sep 17 00:00:00 2001 From: Ugo Meguerditchian Date: Mon, 11 Sep 2023 14:34:44 +0200 Subject: [PATCH] debug resume mode and better args --- lib/configuration.py | 2 +- main.py | 80 +++++++++++++++++------------------ manifest.json | 2 +- tools/AS_scan/brute_subs.py | 18 ++++++-- tools/after_AS_scan/nuclei.py | 10 ++++- 5 files changed, 63 insertions(+), 49 deletions(-) diff --git a/lib/configuration.py b/lib/configuration.py index 707c3fd..922e792 100644 --- a/lib/configuration.py +++ b/lib/configuration.py @@ -106,7 +106,7 @@ def load(self): logger.info("[*] Info: Proxy activated") # logger.info("[*] Testing proxy...") for link, type in self.config["Proxy"]["links"].items(): - try : + try: for line in requests.get(link).text.splitlines(): if type == "http": self.http_proxy.append(line) diff --git a/main.py b/main.py index 0cd8b0b..9ae81d0 100644 --- a/main.py +++ b/main.py @@ -85,28 +85,36 @@ def main(): exit() # Set the input type and name based on the user's input + + if not args.resume: + logger.info("[*] Starting tools to run before AS scan") + if args.domain: name = args.domain res.metadata["input"] = name res.metadata["input_type"] = "domain" + AS_scan.main(config, res, name) + fqdn_scanner(args.domain, config, res, args.recursive) elif args.ip: name = args.ip res.metadata["input"] = name res.metadata["input_type"] = "ip" + AS_scan.main(config, res, name) + ip_scanner(args.ip, config, res, args.recursive) elif args.network: name = args.network res.metadata["input"] = name name = name.replace("/", "_") + AS_scan.main(config, res, name) + logger.info("[*] Scanning network") + this_network = ip_lib.network(args.network) + this_network.get_ip_from_network() + for ip in this_network.ips: + ip_scanner(ip, config, res, args.recursive) elif args.resume: - name = res.metadata["input"] - - logger.info("[*] Starting tools to run before AS scan") - - # Check if the user wants to resume a previous scan - if args.resume: if ":" in args.resume: # if more than one : in the resume argument if args.resume.count(":") > 1: @@ -116,18 +124,8 @@ def main(): else: tool = args.resume.split(":")[1] resume_file = args.resume.split(":")[0] - if not ":" in args.resume: + else: resume_file = args.resume - if "last_tool" in res.metadata: - tool = res.metadata["last_tool"] - else: - logger.error(f"[*] Error: no tool specified") - exit(1) - - # Check if the specified tool exists - if tool != "export" and not os.path.exists(f"tools/{tool}.py"): - logger.error(f"[*] Error: tool {tool} does not exist") - exit(1) # Check if the specified export file exists if not os.path.exists(resume_file): @@ -151,7 +149,19 @@ def main(): # Move the metadata from the data dictionary to the result metadata res.metadata = data.pop("metadata") - + name = res.metadata["input"] + if not ":" in args.resume: + resume_file = args.resume + if "last_tool" in res.metadata: + tool = res.metadata["last_tool"] + else: + logger.error(f"[*] Error: no tool specified") + exit(1) + + # Check if the specified tool exists + if tool != "export" and not os.path.exists(f"tools/{tool}.py"): + logger.error(f"[*] Error: tool {tool} does not exist") + exit(1) # Convert the IP addresses to IP objects for ip in data: new[ip_lib.ip(ip, config)] = data[ip] @@ -179,40 +189,26 @@ def main(): fqdn_scanner(res.metadata["input"], config, res, args.recursive) elif res.metadata["input_type"] == "ip": ip_scanner(res.metadata["input"], config, res, args.recursive) + elif res.metadata["input_type"] == "network": + logger.info("[*] Scanning network") + this_network = ip_lib.network(args.network) + this_network.get_ip_from_network() + for ip in this_network.ips: + ip_scanner(ip, config, res, args.recursive) else: - resume = False - - logger.info("[*]") - - # If the user provided a domain, scan it - elif args.domain: - AS_scan.main(config, res, name) - fqdn_scanner(args.domain, config, res, args.recursive) - - # If the user provided an IP address, scan it - elif args.ip: - AS_scan.main(config, res, name) - ip_scanner(args.ip, config, res, args.recursive) - - # If the user provided a network, scan it - elif args.network: - AS_scan.main(config, res, name) - logger.info("[*] Scanning network") - this_network = ip_lib.network(args.network) - this_network.get_ip_from_network() - for ip in this_network.ips: - ip_scanner(ip, config, res, args.recursive) + logger.info("[*] Resuming scan but after AS scan") # Print the result status and scan completion message res.status() - logger.info("[*] Attack Surface scan finished") res.printer() # If we're not resuming a scan, run the after scan tools if not resume: + logger.info("[*] Attack Surface scan finished") after_AS_scan.main(config, res, name) - else: + elif resume: if resume == "export": + logger.info("[*] Resuming scan from export") pass else: after_AS_scan.main(config, res, name, resume) diff --git a/manifest.json b/manifest.json index 381d047..ed4cc3c 100644 --- a/manifest.json +++ b/manifest.json @@ -1,4 +1,4 @@ { - "version": "V3.1.3", + "version": "V3.1.4", "configuration_file_version": "2.0.1" } \ No newline at end of file diff --git a/tools/AS_scan/brute_subs.py b/tools/AS_scan/brute_subs.py index b720458..7bc682e 100644 --- a/tools/AS_scan/brute_subs.py +++ b/tools/AS_scan/brute_subs.py @@ -7,9 +7,12 @@ import lib.custom_logger as custom_logger import time import uuid + logger = custom_logger.logger ips = set() + + def is_wildcard(fqdn: str) -> bool: """ Checks if the fqdn is a wildcard. @@ -30,9 +33,11 @@ def is_wildcard(fqdn: str) -> bool: return True else: return False - + except: return False + + def resolve_and_store( resolver: dns.resolver.Resolver, subdomain: str, @@ -92,7 +97,7 @@ def main(config: gen.configuration, res: result, name: str) -> result: if is_wildcard(name): logger.info(f"[*] {name} is a wildcard") wildcard = True - + # get wordlist inside tools/worldlists wordlist = f"tools/wordlists/{this_tool_config['wordlist_name']}" # get resolver inside tools/resolvers @@ -112,7 +117,14 @@ def main(config: gen.configuration, res: result, name: str) -> result: with tqdm(total=len(subdomains), leave=False) as pbar: futures = [ executor.submit( - resolve_and_store, resolver, subdomain, fqdn, config, res, pbar, wildcard + resolve_and_store, + resolver, + subdomain, + fqdn, + config, + res, + pbar, + wildcard, ) for subdomain in subdomains ] diff --git a/tools/after_AS_scan/nuclei.py b/tools/after_AS_scan/nuclei.py index bae7206..c6f5993 100644 --- a/tools/after_AS_scan/nuclei.py +++ b/tools/after_AS_scan/nuclei.py @@ -63,12 +63,18 @@ def nuclei_scan(hosts: list, domain: str, vulnconf: str, headless=False) -> dict # Update Nuclei logger.info("Updating Nuclei") subprocess.run( - ["nuclei", "-update"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True + ["nuclei", "-update"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True, ) # Update Nuclei templates logger.info("Updating Nuclei templates") subprocess.run( - ["nuclei", "-ut"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True + ["nuclei", "-ut"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True, ) # Run Nuclei and save the results in a JSON file