Exemple #1
0
    def nmap_list_scan(self, subnet, arg="-sL"): # requires root
        """
        The list scan is a degenerate form of host discovery that simply lists each host of the network(s)
        specified, without sending any packets to the target hosts.

        NOTE: /usr/bin/nmap  -oX  -  192.168.178.1/24  -sL
        """
        self.host = subnet
        parser  = NmapCommandParser(None)

        command_args = "{host}  {default}".format(host=subnet, default=arg)
        command = self.default_command() + command_args
        dns_brute_shlex = shlex.split(command) # prepare it for popen

        output = self.run_command(dns_brute_shlex)
        xml_root = self.get_xml_et(output)

        host_discovered = parser.parse_nmap_listscan(xml_root)
        return host_discovered
Exemple #2
0
class Nmap(object):
    """
    This nmap class allows us to use the nmap port scanner tool from within python
    by calling nmap3.Nmap()
    """
    def __init__(self, path=None):
        """
        Module initialization

        :param path: Path where nmap is installed on a user system. On linux system it's typically on /usr/bin/nmap.
        """

        self.nmaptool = path if path else get_nmap_path()
        self.default_args = "{nmap}  {outarg}  -  "
        self.maxport = 65389
        self.target = ""
        self.top_ports = dict()
        self.parser  = NmapCommandParser(None)
        self.raw_ouput = None
        self.as_root = False

    def require_root(self, required=True):
        """
        Call this method to add "sudo" in front of nmap call
        """
        self.as_root = required
        
    def default_command(self):
        """
        Returns the default nmap command
        that will be chained with all others
        eg nmap -oX -
        """
        if self.as_root:
            return self.default_command_privileged()

        return self.default_args.format(nmap=self.nmaptool, outarg="-oX")
    
    def default_command_privileged(self):
        """
        Commands that require root privileges
        """
        if OS_TYPE == 'win32':
            # Elevate privileges and return nmap command
            # For windows now is not fully supported so just return the default
            return self.default_command() 
        else:
            return self.default_args.format(nmap="sudo "+self.nmaptool, outarg="-oX")

    def nmap_version(self):
        """
        Returns nmap version and build details
        """
        # nmap version output is not available in XML format (eg. -oX -)
        output = self.run_command([self.nmaptool, '--version'])
        version_data = {}
        for line in output.splitlines():
            if line.startswith('Nmap version '):
                version_string = line.split(' ')[2]
                version_data['nmap'] = tuple([int(_) for _ in version_string.split('.')])
            elif line.startswith('Compiled with:'):
                compiled_with = line.split(':')[1].strip()
                version_data['compiled_with'] = tuple(compiled_with.split(' '))
            elif line.startswith('Compiled without:'):
                compiled_without = line.split(':')[1].strip()
                version_data['compiled_without'] = tuple(compiled_without.split(' '))
            elif line.startswith('Available nsock engines:'):
                nsock_engines = line.split(':')[1].strip()
                version_data['nsock_engines'] = tuple(nsock_engines.split(' '))
        return version_data

    # Unique method for repetitive tasks - Use of 'target' variable instead of 'host' or 'subnet' - no need to make difference between 2 strings that are used for the same purpose
    def scan_command(self, target, arg, args):
        self.target == target
        
        command_args = "{target}  {default}".format(target=target, default=arg)
        scan_command = self.default_command() + command_args
        if(args):
            scan_command += " {0}".format(args)

        scan_shlex = shlex.split(scan_command)

        output = self.run_command(scan_shlex)
        xml_root = self.get_xml_et(output)

        return xml_root


    def scan_top_ports(self, target, default=10, args=None):
        """
        Perform nmap's top ports scan

        :param: target can be IP or domain
        :param: default is the default top port

        This top port requires root previledges
        """
        if(default > self.maxport):
            raise ValueError("Port can not be greater than default 65389")
        self.target = target

        if(args):
            assert(isinstance(args, str)), "Expected string got {0} instead".format(type(args))

        top_port_args = " {target} --top-ports {default}".format(target=target, default=default)
        scan_command = self.default_command() + top_port_args
        if(args):
            scan_command += " {0}".format(args)
        scan_shlex = shlex.split(scan_command)

        # Run the command and get the output
        output = self.run_command(scan_shlex)
        if not output:
            # Probaby and error was raise
            raise ValueError("Unable to perform requested command")

        # Begin parsing the xml response
        xml_root = self.get_xml_et(output)
        self.top_ports = self.parser.filter_top_ports(xml_root)
        return self.top_ports

    def nmap_dns_brute_script(self, target, dns_brute="--script dns-brute.nse"):
        """
        Perform nmap scan using the dns-brute script

        :param: target can be IP or domain
        :param: default is the default top port

        nmap -oX - nmmapper.com --script dns-brute.nse
        """
        self.target = target

        dns_brute_args = "{target}  {default}".format(target=target, default=dns_brute)

        dns_brute_command = self.default_command() + dns_brute_args
        dns_brute_shlex = shlex.split(dns_brute_command) # prepare it for popen

        # Run the command and get the output
        output = self.run_command(dns_brute_shlex)

        # Begin parsing the xml response
        xml_root = self.get_xml_et(output)
        subdomains = self.parser.filter_subdomains(xml_root)
        return subdomains

    def nmap_version_detection(self, target, arg="-sV", args=None):
        """
        Perform nmap scan using the dns-brute script

        :param: target can be IP or domain

        nmap -oX - nmmapper.com --script dns-brute.nse
        """
        xml_root = self.scan_command(target=target, arg=arg, args=args)

        services = self.parser.version_parser(xml_root)
        return services

    # Using of basic options for stealth scan

    def nmap_stealth_scan(self, target, arg="-Pn -sZ", args=None):
        """
        nmap -oX - nmmapper.com -Pn -sZ
        """
        xml_root = self.scan_command(target=target, arg=arg, args=args)
        self.top_ports = self.parser.filter_stealth_scan(xml_root)
        return self.top_ports
        
    def nmap_detect_firewall(self, target, arg="-sA", args=None): # requires root
        """
        nmap -oX - nmmapper.com -sA
        @ TODO
        """
        xml_root = self.scan_command(target=target, arg=arg, args=args)

        # TODO

    def nmap_os_detection(self, target, arg="-O", args=None): # requires root
        """
        nmap -oX - nmmapper.com -O
        NOTE: Requires root
        """
        xml_root = self.scan_command(target=target, arg=arg, args=args)
        os_identified = self.parser.os_identifier_parser(xml_root)
        return os_identified

    def nmap_subnet_scan(self, target, arg="-p-", args=None): # requires root
        """
        nmap -oX - nmmapper.com -p-
        NOTE: Requires root
        """

        xml_root = self.scan_command(target=target, arg=arg, args=args)
        subnet_discovered = self.parser.parse_nmap_subnetscan(xml_root)
        return subnet_discovered

    def nmap_list_scan(self, target, arg="-sL", args=None): # requires root
        """
        The list scan is a degenerate form of target discovery that simply lists each target of the network(s)
        specified, without sending any packets to the target targets.

        NOTE: /usr/bin/nmap  -oX  -  192.168.178.1/24  -sL
        """
        self.target = target
        xml_root = self.scan_command(target=target, arg=arg, args=args)

        hosts_discovered = self.parser.parse_nmap_listscan(xml_root)
        return hosts_discovered

    def run_command(self, cmd):
        """
        Runs the nmap command using popen

        @param: cmd--> the command we want run eg /usr/bin/nmap -oX -  nmmapper.com --top-ports 10
        """
        if (os.path.exists(self.nmaptool)):
            sub_proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            try:
                output, errs = sub_proc.communicate()
            except Exception as e:
                sub_proc.kill()
                raise (e)
            else:
                if 0 != sub_proc.returncode:
                    raise NmapExecutionError('Error during command: "' + ' '.join(cmd) + '"\n\n' + errs.decode('utf8'))

                # Response is bytes so decode the output and return
                return output.decode('utf8').strip()
        else:
            raise NmapNotInstalledError()

    def get_xml_et(self, command_output):
        """
        @ return xml ET
        """
        try:
            self.raw_ouput = command_output
            return ET.fromstring(command_output)
        except ParseError:
            raise NmapXMLParserError()
Exemple #3
0
class Nmap(object):
    """
    This nmap class allows us to use the nmap port scanner tool from within python
    by calling nmap3.Nmap()
    """
    def __init__(self, path=None):
        """
        Module initialization

        :param path: Path where nmap is installed on a user system. On linux system it's typically on /usr/bin/nmap.
        """

        self.nmaptool = path if path else get_nmap_path()
        self.default_args = "{nmap}  {outarg}  -  "
        self.maxport = 65389
        self.target = ""
        self.top_ports = dict()
        self.parser = NmapCommandParser(None)

    def default_command(self):
        """
        Returns the default nmap command
        that will be chained with all others
        eg nmap -oX -
        """
        return self.default_args.format(nmap=self.nmaptool, outarg="-oX")


# Unique method for repetitive tasks - Use of 'target' variable instead of 'host' or 'subnet' - no need to make difference between 2 strings that are used for the same purpose

    def scan_command(self, target, arg, args):
        self.target == target

        command_args = "{target}  {default}".format(target=target, default=arg)
        scan_command = self.default_command() + command_args
        if (args):
            scan_command += " {0}".format(args)

        scan_shlex = shlex.split(scan_command)

        output = self.run_command(scan_shlex)
        xml_root = self.get_xml_et(output)

        return xml_root

    def scan_top_ports(self, target, default=10, args=None):
        """
        Perform nmap's top ports scan

        :param: target can be IP or domain
        :param: default is the default top port

        This top port requires root previledges
        """
        parser = NmapCommandParser(None)

        if (default > self.maxport):
            raise ValueError("Port can not be greater than default 65389")
        self.target = target

        if (args):
            assert (isinstance(args,
                               str)), "Expected string got {0} instead".format(
                                   type(args))

        top_port_args = " {target} --top-ports {default}".format(
            target=target, default=default)
        scan_command = self.default_command() + top_port_args
        if (args):
            scan_command += " {0}".format(args)
        scan_shlex = shlex.split(scan_command)

        # Run the command and get the output
        output = self.run_command(scan_shlex)
        if not output:
            # Probaby and error was raise
            raise ValueError("Unable to perform requested command")

        # Begin parsing the xml response
        xml_root = self.get_xml_et(output)
        self.top_ports = parser.filter_top_ports(xml_root)
        return self.top_ports

    def nmap_dns_brute_script(self,
                              target,
                              dns_brute="--script dns-brute.nse"):
        """
        Perform nmap scan using the dns-brute script

        :param: target can be IP or domain
        :param: default is the default top port

        nmap -oX - nmmapper.com --script dns-brute.nse
        """
        self.target = target
        parser = NmapCommandParser(None)

        dns_brute_args = "{target}  {default}".format(target=target,
                                                      default=dns_brute)

        dns_brute_command = self.default_command() + dns_brute_args
        dns_brute_shlex = shlex.split(
            dns_brute_command)  # prepare it for popen

        # Run the command and get the output
        output = self.run_command(dns_brute_shlex)

        # Begin parsing the xml response
        xml_root = self.get_xml_et(output)
        subdomains = parser.filter_subdomains(xml_root)
        return subdomains

    def nmap_version_detection(self, target, arg="-sV", args=None):
        """
        Perform nmap scan using the dns-brute script

        :param: target can be IP or domain

        nmap -oX - nmmapper.com --script dns-brute.nse
        """
        xml_root = self.scan_command(target=target, arg=arg, args=args)

        services = self.parser.version_parser(xml_root)
        return services

    # Using of basic options for stealth scan

    def nmap_stealth_scan(self, target, arg="-Pn -sZ", args=None):
        """
        nmap -oX - nmmapper.com -Pn -sZ
        """
        xml_root = self.scan_command(target=target, arg=arg, args=args)
        self.top_ports = self.parser.filter_stealth_scan(xml_root)
        return self.top_ports

    def nmap_detect_firewall(self,
                             target,
                             arg="-sA",
                             args=None):  # requires root
        """
        nmap -oX - nmmapper.com -sA
        @ TODO
        """

        xml_root = self.scan_command(target=target, arg=arg, args=args)

        # TODO

    def nmap_os_detection(self, target, arg="-O", args=None):  # requires root
        """
        nmap -oX - nmmapper.com -O
        NOTE: Requires root
        """

        xml_root = self.scan_command(target=target, arg=arg, args=args)

        os_identified = self.parser.os_identifier_parser(xml_root)
        return os_identified

    def nmap_subnet_scan(self, target, arg="-p-", args=None):  # requires root
        """
        nmap -oX - nmmapper.com -p-
        NOTE: Requires root
        """

        xml_root = self.scan_command(target=target, arg=arg, args=args)

        subnet_discovered = self.parser.parse_nmap_subnetscan(xml_root)
        return subnet_discovered

    def nmap_list_scan(self, target, arg="-sL", args=None):  # requires root
        """
        The list scan is a degenerate form of target discovery that simply lists each target of the network(s)
        specified, without sending any packets to the target targets.

        NOTE: /usr/bin/nmap  -oX  -  192.168.178.1/24  -sL
        """
        self.target = target

        xml_root = self.scan_command(target=target, arg=arg, args=args)

        hosts_discovered = self.parser.parse_nmap_listscan(xml_root)
        return hosts_discovered

    def run_command(self, cmd):
        """
        Runs the nmap command using popen

        @param: cmd--> the command we want run eg /usr/bin/nmap -oX -  nmmapper.com --top-ports 10
        """
        if (os.path.exists(self.nmaptool)):
            sub_proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
            try:
                output, errs = sub_proc.communicate()
            except Exception as e:
                sub_proc.kill()
                raise (e)
            else:
                # Response is bytes so decode the output and return
                return output.decode('utf8').strip()
        else:
            raise NmapNotInstalledError()

    def get_xml_et(self, command_output):
        """
        @ return xml ET
        """
        try:
            return ET.fromstring(command_output)
        except xml.etree.ElementTree.ParseError:
            raise NmapXMLParserError()