def smart_check(self, grab_banner_nmap=False):
        """
        Check if the target is reachable and update target info
        :return: Boolean indicating status
        """
        # If no IP, means that DNS lookup has failed
        if not self.service.host.ip: 
            return False

        # For HTTP: Check URL availability, grab headers, grab HTML title
        if self.service.url: 
            is_reachable, status, resp_headers = WebUtils.is_url_reachable(self.service.url)
            self.service.up = is_reachable
            if resp_headers:
                self.service.http_headers = '\n'.join("{}: {}".format(key,val) for (key,val) in resp_headers.items())
            else:
                self.service.http_headers = ''

            self.service.comment = WebUtils.grab_html_title(self.service.url)
        # For any other service: Simple port check
        elif self.service.protocol == Protocol.TCP:
            self.service.up = NetUtils.is_tcp_port_open(str(self.service.host.ip), self.service.port)
        else:
            self.service.up = NetUtils.is_udp_port_open(str(self.service.host.ip), self.service.port)

        # Banner grabbing via Nmap (for TCP only) only if there is no banner already stored in db
        if grab_banner_nmap and self.service.up  and self.service.protocol == Protocol.TCP and not self.service.banner:
            self.service.banner = NetUtils.grab_banner_nmap(str(self.service.host.ip), self.service.port)

        return self.service.up
    def add_service(self, ip, hostname, port, protocol, service):
        protocol = {
            'tcp': Protocol.TCP,
            'udp': Protocol.UDP
        }.get(protocol, Protocol.TCP)
        matching_service = self.sqlsess.query(Service).join(Host).join(Mission)\
                                       .filter(Mission.name == self.current_mission)\
                                       .filter(Host.ip == ip)\
                                       .filter(Service.port == int(port))\
                                       .filter(Service.protocol == protocol).first()
        if protocol == Protocol.TCP:
            up = NetUtils.is_tcp_port_open(ip, port)
        else:
            up = NetUtils.is_udp_port_open(ip, port)

        if matching_service:
            logger.warning('Service already present into database')
        else:
            if up:
                logger.info(
                    'Grabbing banner from {ip}:{port} with Nmap...'.format(
                        ip=ip, port=port))
                banner = NetUtils.grab_banner_nmap(ip, port)
                logger.info('Banner: {}'.format(banner or 'None'))
                os = NetUtils.os_from_nmap_banner(banner)
                if os:
                    logger.info('Detected Host OS: {}'.format(os))
            else:
                logger.warning('Port seems to be closed !')

            # Add service in db (and host if not existing)
            service = Service(name=service,
                              port=int(port),
                              protocol=protocol,
                              up=up,
                              banner=banner)

            matching_host = self.sqlsess.query(Host).join(Mission)\
                                        .filter(Mission.name == self.current_mission)\
                                        .filter(Host.ip == ip).first()
            new_host = Host(ip=ip, hostname=hostname, os=os)
            if matching_host:
                matching_host.merge(new_host)
                self.sqlsess.commit()
                service.host = matching_host
            else:
                mission = self.sqlsess.query(Mission).filter(
                    Mission.name == self.current_mission).first()
                new_host.mission = mission
                service.host = new_host
                self.sqlsess.add(new_host)

            self.sqlsess.add(service)
            self.sqlsess.commit()

            logger.success('Service added')
Esempio n. 3
0
    def __availability_check(self):
        """
        Check if TCP/UDP port is open

        Updated in this method:
            - self.service.up
        """
        if self.service.protocol == Protocol.TCP:
            # For TCP: simple port check
            self.service.up = NetUtils.is_tcp_port_open(
                str(self.service.host.ip), self.service.port)

        else:
            # For UDP: simple port check
            self.service.up = NetUtils.is_udp_port_open(
                str(self.service.host.ip), self.service.port)
Esempio n. 4
0
    def smart_check(self,
                    reverse_dns=True,
                    availability_check=True,
                    grab_banner_nmap=False,
                    web_technos_detection=True):
        """
        Check if the target is reachable and update target information

        :param bool reverse_dns: Set to True to attempt performing reverse DNS lookup 
            when no hostname is specified (only IP)
        :param bool availability_check: Set to True to check for availability of the
            target, and also grab headers and HTML title for HTTP services
        :param bool grab_banner_nmap: Set to True to grab the Nmap banner (for TCP)
        :param bool web_technos_detection: Set to True to run WebTechnoDetector if 
            target service is HTTP
        :return: Result of check
        :rtype: bool
        """

        # If no IP, means that DNS lookup has failed
        if not self.service.host.ip:
            return False

        # Perform reverse DNS lookup if hostname not defined
        # Note: If lookup fails, it fallbacks to IP
        if reverse_dns:
            if self.service.host.hostname == self.service.host.ip:
                logger.info('Reverse DNS lookup for {ip}...'.format(
                    ip=str(self.service.host.ip)))
                hostname = NetUtils.reverse_dns_lookup(self.service.host.ip)

                if hostname != self.service.host.ip:
                    logger.info('{ip} -> {hostname}'.format(
                        ip=self.service.host.ip, hostname=hostname))
                else:
                    logger.info('No DNS name found for IP')

                self.service.host.hostname = hostname

        # Perform availability check
        if availability_check:
            logger.info('Check if service is reachable...')

            # For HTTP: Check URL availability, grab headers, grab HTML title
            if self.service.url:
                is_reachable, status, resp_headers = WebUtils.is_url_reachable(
                    self.service.url)
                self.service.up = is_reachable

                if is_reachable:
                    if resp_headers:
                        self.service.http_headers = '\n'.join('{}: {}'.format(key,val) \
                            for (key,val) in resp_headers.items())
                    else:
                        self.service.http_headers = ''

                    if not self.service.html_title:
                        self.service.html_title = WebUtils.grab_html_title(
                            self.service.url)

            # For any other service: Simple port check
            elif self.service.protocol == Protocol.TCP:
                self.service.up = NetUtils.is_tcp_port_open(
                    str(self.service.host.ip), self.service.port)
            else:
                self.service.up = NetUtils.is_udp_port_open(
                    str(self.service.host.ip), self.service.port)

            if not self.service.up:
                return False

        else:
            self.service.up = True  # consider it as up anyway

        # Banner grabbing via Nmap (for TCP only) only if there is no banner
        # already stored in db
        if grab_banner_nmap \
           and self.service.up  \
           and self.service.protocol == Protocol.TCP \
           and not self.service.banner:

            logger.info(
                'Grab banner for [{service}] via Nmap...'.format(service=self))
            self.service.banner = NetUtils.clean_nmap_banner(
                NetUtils.grab_banner_nmap(str(self.service.host.ip),
                                          self.service.port))
            logger.info('Banner: {banner}'.format(banner=self.service.banner))

            # Try to deduce OS from banner if possible
            if not self.service.host.os:
                detected_os = NetUtils.os_from_nmap_banner(self.service.banner)
                if detected_os:
                    self.service.host.os = detected_os
                    logger.info('Detected OS from banner = {os}'.format(
                        os=detected_os))

        # Web technologies detection for HTTP
        if self.service.name == 'http' and web_technos_detection:
            logger.info('Web technologies detection using Wappalyzer...')
            detector = WebTechnoDetector(self.service.url)
            technos = detector.detect()
            self.service.web_technos = str(technos)
            detector.print_technos()

            # Try to deduce OS from detected web technologies
            if not detected_os:
                detected_os = detector.get_os()
                if detected_os:
                    self.service.host.os = detected_os
                    logger.info(
                        'Detected OS from web technologies = {os}'.format(
                            os=detected_os))

        return self.service.up