Codebase list faraday-plugins / c19a85b faraday_plugins / plugins / repo / fierce / plugin.py
c19a85b

Tree @c19a85b (Download .tar.gz)

plugin.py @c19a85braw · history · blame

"""
Faraday Penetration Test IDE
Copyright (C) 2013  Infobyte LLC (http://www.infobytesec.com/)
See the file 'doc/LICENSE' for the license information

"""
import re

from faraday_plugins.plugins.plugin import PluginBase


__author__ = "Francisco Amato"
__copyright__ = "Copyright (c) 2013, Infobyte LLC"
__credits__ = ["Francisco Amato"]
__license__ = ""
__version__ = "1.0.0"
__maintainer__ = "Francisco Amato"
__email__ = "[email protected]"
__status__ = "Development"

valid_records = ["NS", "CNAME", "A"]


class FierceParser:
    """
    The objective of this class is to parse an shell output generated by
    the fierce tool.

    TODO: Handle errors.
    TODO: Test fierce output version. Handle what happens if the parser
    doesn't support it.
    TODO: Test cases.

    @param fierce_filepath A proper simple report generated by fierce
    """

    def __init__(self, output):
        self.target = None
        self.items = []

        regex = re.search(
            "DNS Servers for ([\\w\\.-]+):\n([^$]+)Trying zone transfer first...",
            output)

        if regex is not None:
            self.target = regex.group(1)
            mstr = re.sub("\t", "", regex.group(2))
            self.dns = list(filter(None, mstr.splitlines()))

        regex = re.search(
            "Now performing [\\d]+ test\\(s\\)...\n([^$]+)\nSubnets found ",
            output)
        if regex is not None:
            hosts_list = regex.group(1).splitlines()
            for i in hosts_list:
                if i != "":
                    mstr = i.split("\t")
                    host = mstr[1]
                    record = "A"
                    ip = mstr[0]
                    self.add_host_info_to_items(ip, host, record)

        self.isZoneVuln = False
        output = output.replace('\\$', '')
        regex = re.search(
            "Whoah, it worked - misconfigured DNS server found:([^$]+)\nThere isn't much point continuing, "
            "you have  everything.", output)

        if regex is not None:
            self.isZoneVuln = True
            dns_list = regex.group(1).splitlines()
            for i in dns_list:
                if i != "":
                    mstr = i.split()
                    if (mstr and mstr[0] != "" and len(mstr) > 3 and mstr[3] in valid_records):
                        host = mstr[0]
                        record = mstr[3]
                        ip = mstr[4]
                        self.add_host_info_to_items(ip, host, record)

    def add_host_info_to_items(self, ip_address, hostname, record):
        data = {}
        exists = False
        for item in self.items:
            if ip_address in item['ip']:
                item['hosts'].append(hostname)
                exists = True

        if not exists:
            data['ip'] = ip_address
            data['hosts'] = [hostname]
            data['record'] = record
            self.items.append(data)


class FiercePlugin(PluginBase):
    """
    Example plugin to parse fierce output.
    """

    def __init__(self, *arg, **kwargs):
        super().__init__(*arg, **kwargs)
        self.id = "Fierce"
        self.name = "Fierce Output Plugin"
        self.plugin_version = "0.0.1"
        self.version = "0.9.9"
        self.options = None
        self._current_output = None
        self._command_regex = re.compile(
            r'^(sudo fierce|fierce|sudo fierce\.pl|fierce\.pl|perl fierce\.pl|\.\/fierce\.pl)\s+.*?')


    def resolveCNAME(self, item, items):
        for i in items:
            if (item['ip'] in i['hosts']):
                item['ip'] = i['ip']
                return item
        try:
            item['ip'] = self.resolve_hostname(item['ip'])
        except:
            pass  # nosec
        return item

    def resolveNS(self, item, items):
        try:
            item['hosts'][0] = item['ip']
            item['ip'] = self.resolve_hostname(item['ip'])
        except:
            pass
        return item

    def parseOutputString(self, output):

        parser = FierceParser(output)
        for item in parser.items:

            item['isResolver'] = False
            item['isZoneVuln'] = False
            if item['record'] == "CNAME":
                self.resolveCNAME(item, parser.items)
            if item['record'] == "NS":
                self.resolveNS(item, parser.items)
                item['isResolver'] = True
                item['isZoneVuln'] = parser.isZoneVuln
                for item2 in parser.items:

                    if item['ip'] == item2['ip'] and item != item2:
                        item2['isResolver'] = item['isResolver']
                        item2['isZoneVuln'] = item['isZoneVuln']
                        item['ip'] = ''

        for item in parser.items:
            if item['ip'] == "127.0.0.1" or item['ip'] == '':
                continue
            h_id = self.createAndAddHost(
                item['ip'],
                hostnames=item['hosts'])

            if item['isResolver']:
                s_id = self.createAndAddServiceToHost(
                    h_id,
                    "domain",
                    "tcp",
                    ports=['53'])

                if item['isZoneVuln']:
                    self.createAndAddVulnToService(
                        h_id,
                        s_id,
                        "Zone transfer",
                        desc="A Dns server allows unrestricted zone transfers",
                        ref=["CVE-1999-0532"])


def createPlugin(*args, **kwargs):
    return FiercePlugin(*args, **kwargs)