Ejemplo n.º 1
0
    def __init_with_ip(self):
        """
        Initialize with an IP address or a hostname.
        This method updates: Hostname, IP

        :raises TargetException: Exception raised if DNS lookup fails
        """
        if NetUtils.is_valid_ip(self.service.host.ip):
            self.service.host.hostname = str(self.service.host.ip)
            # updated in smart_check
        else:
            # host.ip actually stores a hostname at this point, a DNS lookup is needed
            self.service.host.hostname = self.service.host.ip
            self.service.host.ip = NetUtils.dns_lookup(
                self.service.host.hostname)
            if self.service.host.ip:
                logger.info('DNS lookup on {hostname} -> IP: {ip}'.format(
                    hostname=self.service.host.hostname,
                    ip=self.service.host.ip))
            else:
                raise TargetException('Unable to resolve {}'.format(
                    self.service.host.hostname))

        # Forge URL for http services
        if self.service.name == 'http':
            if self.get_specific_option_value('https'):
                proto = 'https'
            else:
                proto = 'http'

            self.service.url = '{proto}://{ip}:{port}'.format(
                proto=proto, ip=self.service.host.ip, port=self.service.port)
Ejemplo n.º 2
0
    def __init_with_url(self):
        """
        Initialize with an URL (when targeting HTTP).
        This method updates: URL, Hostname, IP, Port

        :raises TargetException: Exception raised if DNS lookup fails
        """
        self.service.url = WebUtils.add_prefix_http(self.service.url)
        self.service.url = WebUtils.remove_ending_slash(self.service.url)
        url = urlparse(self.service.url)

        if NetUtils.is_valid_ip(url.hostname):
            self.service.host.ip = url.hostname
            self.service.host.hostname = url.hostname  # updated in smart_check

        else:
            self.service.host.ip = NetUtils.dns_lookup(url.hostname)
            if not self.service.host.ip:
                raise TargetException('Unable to resolve {}'.format(
                    url.hostname))
            self.service.host.hostname = url.hostname

        if not self.service.port:
            self.service.port = WebUtils.get_port_from_url(self.service.url)
            if not NetUtils.is_valid_port(self.service.port):
                raise TargetException('Invalid port number {}'.format(
                    self.service.port))
Ejemplo n.º 3
0
    def check_arg_ip_port(self, ip_port):
        ip, port = ip_port.split(':', maxsplit=1)
        if not NetUtils.is_valid_port(port):
            raise argparse.ArgumentTypeError('Invalid port number')
        if not NetUtils.is_valid_ip(ip):
            raise argparse.ArgumentTypeError('Invalid IP address')

        return ip, port
 def __init_with_ip(self):
     """
     """
     if NetUtils.is_valid_ip(self.service.host.ip):
         self.service.host.hostname = NetUtils.reverse_dns_lookup(str(self.service.host.ip))
     else:
         # host.ip actually stores a hostname at this point
         self.service.host.ip = NetUtils.dns_lookup(str(self.service.host.ip)) 
         self.service.host.hostname = self.service.host.ip
Ejemplo n.º 5
0
    def __init_with_ip_port(self, ip, port, ssl):
        if not NetUtils.is_valid_ip(ip):
            raise TargetException('Invalid IP address')
        if not NetUtils.is_valid_port(port):
            raise TargetException('Invalid port number {}'.format(port))

        self.ip = ip
        self.port = port
        self.url = 'http{s}://{ip}:{port}'.format(s='s' if self.ssl else '',
                                                  ip=self.ip,
                                                  port=self.port)
Ejemplo n.º 6
0
 def __translate_ip(self, value):
     """
     Translate IP address or IP range into Sqlalchemy filter.
     Range must be in CIDR format, e.g. 1.1.1.1/24
     """
     if NetUtils.is_valid_ip(value):
         return (Host.ip == value)
     elif NetUtils.is_valid_ip_range(value):
         return (Host.is_in_ip_range(value))
     else:
         raise FilterException(
             '{value} invalid IP/range'.format(value=value))
Ejemplo n.º 7
0
 def __translate_ip(self, value):
     """
     value can be:
         - Single IP
         - IP range - format: 1.1.1.1/24
     """
     if NetUtils.is_valid_ip(value):
         return (Host.ip == value)
     elif NetUtils.is_valid_ip_range(value):
         return (Host.is_in_ip_range(value))
     else:
         raise FilterException(
             '{value} invalid IP/range'.format(value=value))
    def __init_with_url(self):
        """
        """
        self.service.url = WebUtils.add_prefix_http(self.service.url)
        url = urlparse(self.service.url)

        if NetUtils.is_valid_ip(url.hostname):
            self.service.host.ip = url.hostname
            self.service.host.hostname = NetUtils.reverse_dns_lookup(url.hostname)
        else:
            self.service.host.ip = NetUtils.dns_lookup(url.hostname)
            self.service.host.hostname = url.hostname

        if not self.service.port:
            self.service.port = WebUtils.get_port_from_url(self.service.url)
Ejemplo n.º 9
0
    def __init_with_url(self, url):
        p = urlparse(url)
        if NetUtils.is_valid_ip(p.hostname):
            self.ip = p.hostname
        else:
            self.ip = NetUtils.dns_lookup(p.hostname)
        if not self.ip:
            raise TargetException('Unable to resolve {}'.format(p.hostname))

        self.port = NetUtils.get_port_from_url(url)
        if not NetUtils.is_valid_port(self.port):
            raise TargetException('Invalid port number {}'.format(self.port))

        if url.lower().startswith('https://'):
            self.ssl = True
    def do_hosts(self, args):
        """Hosts in the current mission scope"""
        print()
        req = HostsRequester(self.sqlsess)
        req.select_mission(self.current_mission)

        # Logical AND is applied between all specified filtering options
        filter_ = Filter(FilterOperator.AND)
        if args.addrs:
            for addr in args.addrs:
                if NetUtils.is_valid_ip(addr) or NetUtils.is_valid_ip_range(addr):
                    filter_.add_condition(Condition(addr, FilterData.IP))
                else:
                    filter_.add_condition(Condition(addr, FilterData.HOST))
        if args.search:
            filter_search = Filter(FilterOperator.OR)
            filter_search.add_condition(Condition(args.search, FilterData.HOST))
            filter_search.add_condition(Condition(args.search, FilterData.OS))
            filter_search.add_condition(Condition(args.search, FilterData.COMMENT_HOST))
            filter_.add_condition(filter_search)
        if args.order:
            req.order_by(args.order)

        try:
            req.add_filter(filter_)
        except FilterException as e:
            logger.error(e)
            return

        # Operations
        if args.comment:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to edit comment for ALL hosts in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.edit_comment(args.comment)
        elif args.delete:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to delete ALL hosts and related services in current mission', default=False):
                    logger.info('Canceled')
                    return
            req.delete()
        else:
            req.show()

        print()
    def add_url(self, url):
        matching_service = self.sqlsess.query(Service).join(Host).join(Mission)\
                                       .filter(Mission.name == self.current_mission)\
                                       .filter(Service.url == url).first()
        if matching_service:
            logger.warning('URL already present into database')
        else:

            # Parse URL: Get IP, hostname, port
            parsed = urlparse(url)
            if NetUtils.is_valid_ip(parsed.hostname):
                ip = parsed.hostname
                hostname = NetUtils.reverse_dns_lookup(parsed.hostname)
            else:
                ip = NetUtils.dns_lookup(parsed.hostname)
                if not ip:
                    logger.error('Host cannot be resolved')
                    return
                hostname = parsed.hostname
            port = WebUtils.get_port_from_url(url)

            # Check URL, grab headers, html title
            is_reachable, status, resp_headers = WebUtils.is_url_reachable(url)
            if is_reachable:
                comment = WebUtils.grab_html_title(url)
                if resp_headers:
                    http_headers = '\n'.join("{}: {}".format(key, val)
                                             for (key,
                                                  val) in resp_headers.items())

                logger.info('HTTP Headers:')
                print(http_headers)
                logger.info('Title: {}'.format(comment))
                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:
                comment = 'Not reachable'
                banner = http_headers = ''
                logger.warning('URL seems not to be reachable')

            # Add service in db (and host if not existing)
            service = Service(name='http',
                              port=port,
                              protocol=Protocol.TCP,
                              url=url,
                              up=is_reachable,
                              http_headers=http_headers,
                              banner=banner,
                              comment=comment)

            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/URL added')
    def do_services(self, args):
        """Services in the current mission scope"""
        print()
        req = ServicesRequester(self.sqlsess)
        req.select_mission(self.current_mission)

        # Logical AND is applied between all specified filtering options
        filter_ = Filter(FilterOperator.AND)
        if args.names:
            for n in args.names:
                if not self.settings.services.is_service_supported(n, multi=False):
                    logger.error('Service {name} is not valid/supported'.format(name=n.lower()))
                    return
            filter_.add_condition(Condition(args.names, FilterData.SERVICE_EXACT))

        if args.order:
            req.order_by(args.order)

        if args.hostname:
            # OR between submitted hostnames
            filter_.add_condition(Condition(args.hostname.split(','), FilterData.HOST))
        if args.ip:
            # OR between submitted ips/ranges
            filter_.add_condition(Condition(args.ip.split(','), FilterData.IP))
        if args.port:
            # OR between ports/port-ranges
            filter_.add_condition(Condition(args.port.split(','), FilterData.PORT))
        if args.proto:
            filter_.add_condition(Condition(args.proto, FilterData.PROTOCOL))
        if args.up:
            filter_.add_condition(Condition(args.up, FilterData.UP))
        if args.search:
            filter_search = Filter(FilterOperator.OR)
            filter_search.add_condition(Condition(args.search, FilterData.HOST))
            filter_search.add_condition(Condition(args.search, FilterData.BANNER))
            filter_search.add_condition(Condition(args.search, FilterData.URL))
            filter_search.add_condition(Condition(args.search, FilterData.COMMENT_SERVICE))
            filter_.add_condition(filter_search)

        try:
            req.add_filter(filter_)
        except FilterException as e:
            logger.error(e)
            return

        # Operations
        if args.add:
            host, port, service = args.add
            if NetUtils.is_valid_ip(host):
                ip = host
                hostname = NetUtils.reverse_dns_lookup(ip) 
                logger.info('Reverse DNS lookup on IP {ip}: {hostname}'.format(ip=ip, hostname=hostname))
            else:
                ip = NetUtils.dns_lookup(host)
                if not ip:
                    logger.error('Cannot resolve hostname')
                    return
                hostname = host
                logger.info('DNS lookup on {hostname}: IP {ip}'.format(hostname=host, ip=ip))

            if not NetUtils.is_valid_port(port):
                logger.error('Port is invalid, not in range [0-65535]')
            elif not self.settings.services.is_service_supported(service, multi=False):
                logger.error('Service {name} is not valid/supported'.format(name=service.lower()))
            else:
                req.add_service(ip, hostname, port, self.settings.services.get_protocol(service), service)
        elif args.url:
            args.url = WebUtils.add_prefix_http(args.url)
            if not WebUtils.is_valid_url(args.url):
                logger.error('URL is invalid')
            else:
                req.add_url(args.url)
        elif args.delete:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to delete ALL services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.delete()
        elif args.comment:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to edit comment for ALL services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.edit_comment(args.comment)
        elif args.https:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to apply switch for ALL URLs in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.switch_https()         
        elif args.addcred:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to add same creds for ALL services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.add_cred(args.addcred[0], args.addcred[1], None) 
        elif args.addcred_http:
            if not req.are_only_http_services_selected():
                logger.warning('Some non-HTTP services are selected. Use --addcred instead for non-HTTP services')
                return
            if not self.settings.services.is_valid_authentication_type(args.addcred_http[2]):
                logger.warning('Invalid HTTP authentication type')
                logger.info('List of supported authentication types: ')
                for auth_type in self.settings.services.get_authentication_types('http'):
                    logger.info('- {type}'.format(type=auth_type))
                return
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to add same creds for ALL HTTP services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.add_cred(args.addcred_http[0], args.addcred_http[1], args.addcred_http[2]) 
        elif args.adduser:
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to add same username for ALL services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.add_cred(args.adduser[0], None, None)
        elif args.adduser_http:
            if not req.are_only_http_services_selected():
                logger.warning('Some non-HTTP services are selected. Use --adduser instead for non-HTTP services')
                return
            if not self.settings.services.is_valid_authentication_type(args.adduser_http[1]):
                logger.warning('Invalid HTTP authentication type')
                logger.info('List of supported authentication types: ')
                for auth_type in self.settings.services.get_authentication_types('http'):
                    logger.info('- {type}'.format(type=auth_type))
                return
            if not req.filter_applied:
                if not Output.prompt_confirm('No filter applied. Are you sure you want to add same username for ALL HTTP services in current mission ?', default=False):
                    logger.info('Canceled')
                    return
            req.add_cred(args.adduser_http[0], None, args.adduser_http[1]) 
        else:
            req.show()                      

        print()