diff --git a/nxc/modules/certipy-find.py b/nxc/modules/certipy-find.py new file mode 100644 index 00000000..49d4f6e2 --- /dev/null +++ b/nxc/modules/certipy-find.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +import json +from os import makedirs +from certipy.commands.find import Find +from certipy.lib.target import Target, DnsResolver +from certipy.lib.formatting import pretty_print + +from nxc.paths import NXC_PATH + + +class NXCModule: + """Module made by: @NeffIsBack, @gatariee""" + name = "certipy-find" + description = "" + supported_protocols = ["ldap"] + + def __init__(self, context=None, module_options=None): + self.context = context + self.module_options = module_options + + def options(self, context, module_options): + """ + VULN Show only vulnerable configurations (Default: True) + ENABLED Show only enabled templates + + Export options: + TEXT Export results to a plain text file + CSV Export results to a CSV file + JSON Export results to a JSON file + """ + self.vuln = True + self.enabled = False + self.output_path = f"{NXC_PATH}/modules/certipy-find" + self.json = False + self.csv = False + self.text = False + + if "VULN" in module_options: + self.vuln = module_options["VULN"].lower() in ["true", "1", "yes"] + if "ENABLED" in module_options: + self.enabled = module_options["ENABLED"].lower() in ["true", "1", "yes"] + + # Export options + if "JSON" in module_options: + self.json = module_options["JSON"].lower() in ["true", "1", "yes"] + if "CSV" in module_options: + self.csv = module_options["CSV"].lower() in ["true", "1", "yes"] + if "TEXT" in module_options: + self.text = module_options["TEXT"].lower() in ["true", "1", "yes"] + + def on_login(self, context, connection): + resolv = DnsResolver.create(connection.args.dns_server if connection.args.dns_server else connection.host) + target = Target( + resolver=resolv, + domain=connection.domain, + username=connection.username, + password=connection.password, + lmhash=connection.lmhash, + nthash=connection.nthash, + target_ip=connection.host, + ldap_port=connection.port, + ldap_scheme="ldaps" if connection.port == 636 else "ldap", + ldap_signing=connection.signing_required, + ldap_channel_binding=connection.cbt_status in ["Always", "When Supported"], + ) + + finder = Find( + target=target, + json=self.json, + csv=self.csv, + text=self.text, + output_path=self.output_path, + stdout=True, + vulnerable=self.vuln, + enabled=self.enabled, + ) + + # Get templates and CAs + templates = finder.get_certificate_templates() + cas = finder.get_certificate_authorities() + finder._link_cas_and_templates(cas, templates) + + # Get OIDs + oids = finder.get_issuance_policies() + + # Process information + finder._link_templates_and_policies(templates, oids) + finder._process_ca_properties(cas) + finder._process_template_properties(templates) + + output = finder.get_output_for_text_and_json(templates, cas, oids) + pretty_print(output, print_func=context.log.highlight) + + # Save to disk if any export option specified + if self.json or self.csv or self.text: + makedirs(self.output_path, exist_ok=True) + + if self.json: + with open(f"{self.output_path}/certipy-find.json", "w") as f: + json.dump( + output, + f, + indent=2, + default=str, + ) + if self.csv: + template_output = finder.get_template_output_for_csv(output) + ca_output = finder.get_ca_output_for_csv(output) + with open(f"{self.output_path}/certipy-find-templates.csv", "w") as f: + f.write(template_output) + with open(f"{self.output_path}/certipy-find-cas.csv", "w") as f: + f.write(ca_output) + if self.text: + with open(f"{self.output_path}/certipy-find.txt", "w") as f: + pretty_print(output, print_func=lambda x: f.write(x + "\n"))