Example #1
0
 def test_sync_service_from_host_name_to_host(self):
     self.init_db()
     workspace_str = "unittest"
     # Set up database
     with self._engine.session_scope() as session:
         host1 = self.create_host(session=session, workspace_str=workspace_str, address="192.168.1.1")
         host2 = self.create_host(session=session, workspace_str=workspace_str, address="::1")
         host_name1 = self.create_hostname(session=session,
                                           workspace_str=workspace_str,
                                           host_name="www.test1.com", scope=ScopeType.all)
         host_name2 = self.create_hostname(session=session,
                                           workspace_str=workspace_str,
                                           host_name="www.test.com", scope=ScopeType.all)
         session.add(Service(host_name=host_name1, protocol=ProtocolType.tcp, port=80, state=ServiceState.Open))
         session.add(Service(host_name=host_name2, protocol=ProtocolType.tcp, port=80, state=ServiceState.Open))
         self._domain_utils.add_host_host_name_mapping(session=session,
                                                       host=host1,
                                                       host_name=host_name1,
                                                       mapping_type=DnsResourceRecordType.a | DnsResourceRecordType.ns)
         self._domain_utils.add_host_host_name_mapping(session=session,
                                                       host=host2,
                                                       host_name=host_name2,
                                                       mapping_type=DnsResourceRecordType.aaaa | DnsResourceRecordType.ptr)
     with self._engine.session_scope() as session:
         result = session.query(Host).filter_by(address="192.168.1.1").one()
         self.assertEqual(1, len(result.services))
         self.assertEqual(ProtocolType.tcp, result.services[0].protocol)
         self.assertEqual(80, result.services[0].port)
         result = session.query(Host).filter_by(address="::1").one()
         self.assertEqual(1, len(result.services))
         self.assertEqual(ProtocolType.tcp, result.services[0].protocol)
         self.assertEqual(80, result.services[0].port)
Example #2
0
 def _get_commands(self,
                   session: Session,
                   service: Service,
                   collector_name: CollectorName,
                   command: str,
                   user: str = None,
                   password: str = None) -> List[BaseCollector]:
     """Returns a list of commands based on the provided information."""
     collectors = []
     url = service.get_urlparse()
     if url:
         os_command = [
             command, '--color=never', '-v', '-a', '4', '--no-errors'
         ]
         if self._user_agent:
             os_command.extend(['--user-agent', self._user_agent])
         else:
             os_command.extend(
                 ['--user-agent', self._default_user_agent_string])
         if self._cookies:
             os_command.extend(['--cookie', self._cookies[0]])
         if self._http_proxy:
             os_command.extend(['--proxy', self.http_proxy.geturl()])
         if user:
             password = password if password else ""
             os_command.append('-u={}:{}'.format(user, password))
         os_command.append(service.get_urlparse().geturl())
         collector = self._get_or_create_command(session,
                                                 os_command,
                                                 collector_name,
                                                 service=service)
         collectors.append(collector)
     return collectors
Example #3
0
 def _get_commands(self,
                   session: Session,
                   service: Service,
                   collector_name: CollectorName,
                   command: str,
                   has_move: bool,
                   user: str = None,
                   password: str = None) -> List[BaseCollector]:
     """Returns a list of commands based on the provided information."""
     collectors = []
     address = service.address
     if address:
         os_command = [command, '-cleanup']
         if has_move:
             os_command.append("-move")
         if user:
             password = password if password else ""
             os_command.extend(["-auth", "{}:{}".format(user, password)])
         os_command.extend(['-url', service.get_urlparse().geturl()])
         collector = self._get_or_create_command(session,
                                                 os_command,
                                                 collector_name,
                                                 service=service)
         collectors.append(collector)
     return collectors
Example #4
0
    def create_service_commands(
            self, session: Session, service: Service,
            collector_name: CollectorName) -> List[BaseCollector]:
        """This method creates and returns a list of commands based on the given service.

        This method determines whether the command exists already in the database. If it does, then it does nothing,
        else, it creates a new Collector entry in the database for each new command as well as it creates a corresponding
        operating system command and attaches it to the respective newly created Collector class.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param service: The service based on which commands shall be created.
        :param collector_name: The name of the collector as specified in table collector_name
        :return: List of Collector instances that shall be processed.
        """
        result = []
        if self.match_nmap_service_name(service):
            json_file = self.create_json_file_path(service=service)
            result = self._create_commands(
                session=session,
                service=service,
                collector_name=collector_name,
                protocol=ChangeProtocol.http,
                json_file=json_file,
                target=service.get_urlparse().geturl())
        return result
 def _extract_rpc_info(self, port_tag) -> None:
     """This method determines additional services disclosed by rpcinfo"""
     script = port_tag.findall("*/[@id='{}']".format(
         RpcInfoExtraInfoExtraction.RPC_INFO))
     if len(script) > 0:
         tmp = XmlUtils.get_xml_attribute("output", script[0].attrib).split(
             os.linesep)
         for item in tmp:
             match = self._re_process.match(item)
             if match:
                 port = match.group("port")
                 protocol = match.group("protocol")
                 protocol = Service.get_protocol_type(protocol)
                 service_name = match.group("service")
                 service = self._domain_utils.add_service(
                     session=self._session,
                     port=port,
                     protocol_type=protocol,
                     host=self._service.host,
                     state=ServiceState.Internal,
                     source=self._source_rpc_info,
                     report_item=self._report_item)
                 if service:
                     service.nmap_service_name = service_name if not service.nmap_service_name \
                         else service.nmap_service_name
                     service.state = ServiceState.Internal if service.state != ServiceState.Open else service.state
Example #6
0
 def _get_commands(
         self,
         session: Session,
         service: Service,
         collector_name: CollectorName,
         command: str,
         wordlists: List[str],
         user: str = None,
         password: str = None,
         additional_arguments: List[str] = []) -> List[BaseCollector]:
     """Returns a list of commands based on the provided information."""
     collectors = []
     url = service.get_urlparse()
     number_threads = 1 if self._delay.sleep_active() else 10
     if url:
         for wordlist in wordlists:
             if not os.path.isfile(wordlist):
                 raise FileNotFoundError(
                     "word list '{}' does not exist!".format(wordlist))
             os_command = [
                 command, self._mode, '-z', '-t', number_threads, '-w',
                 wordlist
             ]
             os_command += additional_arguments
             # Add additional settings, if available
             if self._user_agent:
                 os_command.extend(['-a', '{}'.format(self._user_agent)])
             else:
                 os_command.extend(
                     ['-a', '{}'.format(self._default_user_agent_string)])
             if self._cookies:
                 os_command.extend(['-c', "; ".join(self._cookies)])
             else:
                 os_command.append("-k")
             if self._http_proxy:
                 os_command.extend(['-p', self.http_proxy.geturl()])
             if user:
                 os_command.extend(['-U', user])
             if password:
                 os_command.extend(['-P', password])
             os_command += ['-u', service.get_urlparse().geturl()]
             collector = self._get_or_create_command(session,
                                                     os_command,
                                                     collector_name,
                                                     service=service)
             collectors.append(collector)
     return collectors
Example #7
0
 def _create_test_data(self,
                       session: Session,
                       workspace_str: str = "unittest") -> Host:
     source = self.create_source(session=session, source_str="dnshost")
     self.create_network(session=session,
                         network="192.168.1.0/24",
                         scope=ScopeType.all,
                         workspace_str=workspace_str)
     host1 = self.create_host(session=session,
                              workspace_str=workspace_str,
                              address="192.168.1.1")
     host2 = self.create_host(session=session,
                              workspace_str=workspace_str,
                              address="192.168.1.2")
     session.add(
         Service(host=host1,
                 protocol=ProtocolType.tcp,
                 port=80,
                 state=ServiceState.Open))
     session.add(
         Service(host=host2,
                 protocol=ProtocolType.tcp,
                 port=80,
                 state=ServiceState.Open))
     # self.create_service(session=session, workspace_str=workspace_str, address="192.168.1.1", port=80)
     host_name1 = self.create_hostname(session=session,
                                       workspace_str=workspace_str,
                                       host_name="www.test1.com",
                                       scope=ScopeType.all)
     host_name2 = self.create_hostname(session=session,
                                       workspace_str=workspace_str,
                                       host_name="www.test.com",
                                       scope=ScopeType.all)
     self._domain_utils.add_host_host_name_mapping(
         session=session,
         host=host1,
         host_name=host_name1,
         source=source,
         mapping_type=DnsResourceRecordType.a | DnsResourceRecordType.ns)
     self._domain_utils.add_host_host_name_mapping(
         session=session,
         host=host2,
         host_name=host_name2,
         source=source,
         mapping_type=DnsResourceRecordType.ptr)
Example #8
0
 def test_delete_service(self):
     self.init_db()
     workspace_str = "unittest"
     # Set up database
     with self._engine.session_scope() as session:
         host1 = self.create_host(session=session, workspace_str=workspace_str, address="192.168.1.1")
         host2 = self.create_host(session=session, workspace_str=workspace_str, address="::1")
         self.create_service(session=session, workspace_str=workspace_str, address="10.0.0.1", port=443)
         host_name1 = self.create_hostname(session=session,
                                           workspace_str=workspace_str,
                                           host_name="www.test1.com", scope=ScopeType.all)
         host_name2 = self.create_hostname(session=session,
                                           workspace_str=workspace_str,
                                           host_name="www.test.com", scope=ScopeType.all)
         session.add(Service(host_name=host_name1, protocol=ProtocolType.tcp, port=80, state=ServiceState.Open))
         session.add(Service(host=host2, protocol=ProtocolType.tcp, port=8080, state=ServiceState.Open))
         self._domain_utils.add_host_host_name_mapping(session=session,
                                                       host=host1,
                                                       host_name=host_name1,
                                                       mapping_type=DnsResourceRecordType.a | DnsResourceRecordType.ns)
         self._domain_utils.add_host_host_name_mapping(session=session,
                                                       host=host2,
                                                       host_name=host_name2,
                                                       mapping_type=DnsResourceRecordType.aaaa | DnsResourceRecordType.ptr)
     # Delete services
     with self._engine.session_scope() as session:
         result = session.query(Service) \
             .join(Host) \
             .filter(Host.address == "192.168.1.1").one()
         session.delete(result)
         result = session.query(Service) \
             .join((HostName, Service.host_name)) \
             .join((DomainName, HostName.domain_name)) \
             .filter(HostName.name == "www").filter(DomainName.name == "test.com").filter(Service.port == 8080).one()
         session.delete(result)
     # Check database
     with self._engine.session_scope() as session:
         result = session.query(Service).all()
         self.assertEqual(1, len(result))
         self.assertEqual(443, result[0].port)
         self.assertIsNotNone(result[0].host)
         self.assertEqual("10.0.0.1", result[0].host.address)
 def test_service_primary_key_update(self):
     self.init_db()
     # Setup database
     with self._engine.session_scope() as session:
         host = self.create_host(session=session)
         session.add(Service(host=host, port=80, protocol=ProtocolType.tcp, state=ServiceState.Open))
         session.add(Service(host=host, port=443, protocol=ProtocolType.tcp, state=ServiceState.Open))
         session.add(Service(host=host, port=8080, protocol=ProtocolType.tcp, state=ServiceState.Open))
     # Update port
     with self.assertRaises(Exception):
         with self._engine.session_scope() as session:
             service = session.query(Service).filter_by(port=80, protocol=ProtocolType.tcp).one()
             service.port = 161
     # Update protocol
     with self.assertRaises(Exception):
         with self._engine.session_scope() as session:
             service = session.query(Service).filter_by(port=80, protocol=ProtocolType.tcp).one()
             service.protocol = ProtocolType.udp
     # Update both
     with self.assertRaises(Exception):
         with self._engine.session_scope() as session:
             service = session.query(Service).filter_by(port=80, protocol=ProtocolType.tcp).one()
             service.port = 161
             service.protocol = ProtocolType.udp
     # Perform legit update
     with self._engine.session_scope() as session:
         service = session.query(Service).filter_by(port=80, protocol=ProtocolType.tcp).one()
         service.state = ServiceState.Closed
         service.nmap_service_name = "https"
         service.nmap_service_confidence = 1
         service.nmap_service_name_original = "https?"
         service.nmap_service_state_reason = "reason"
         service.nmap_product = "nmap_product"
         service.nmap_version = "nmap_version"
         service.nmap_extra_info = "nmap_extra_info"
         service.nmap_os_type = "nmap_os_type"
         service.nmap_tunnel = "nmap_tunnel"
         service.nessus_service_name = "nessus_service_name"
         service.nessus_service_confidence = 1
 def _get_commands(self,
                   session: Session,
                   service: Service,
                   collector_name: CollectorName,
                   command: str,
                   user_file: str = None,
                   password_file: str = None,
                   user: str = None,
                   password: str = None) -> List[BaseCollector]:
     """Returns a list of commands based on the provided information."""
     collectors = []
     url = service.get_urlparse()
     if url:
         os_command = [
             command, '--no-banner', '--disable-tls-checks', '-t', '5',
             '-e', 'vp,vt'
         ]
         if self._user_agent:
             os_command.extend(['--user-agent', self._user_agent])
         else:
             os_command.extend(
                 ['--user-agent', self._default_user_agent_string])
         if self._cookies:
             os_command.extend(['--cookie', self._cookies[0]])
         if self._http_proxy:
             os_command.extend(['-r', self.http_proxy.geturl()])
         if user_file:
             os_command.extend(['--usernames', user_file])
         if password_file:
             os_command.extend(['--wordlist', password_file])
         os_command.extend(['--url', service.get_urlparse().geturl()])
         collector = self._get_or_create_command(session,
                                                 os_command,
                                                 collector_name,
                                                 service=service)
         collectors.append(collector)
     return collectors
Example #11
0
 def _analyze_fingerprint(self, service: Service, port_tag: str) -> None:
     """
     This method analyzes the results of the NSE script fingerprint and updates the given
     service accordingly
     """
     script = port_tag.findall("*/[@id='fingerprint-strings']")
     if script and service.nmap_service_name not in ["http", "https"]:
         output = DatabaseImporter.get_xml_attribute(
             "output", script[0].attrib)
         if self._re_http_response.findall(output):
             print("[I]   update service name '{}' of {}:{} ({}) to 'http'".
                   format(service.nmap_service_name, service.host.address,
                          service.port, service.protocol.name.lower()),
                   file=self._stdout)
             service.nmap_service_name = "https" if service.tls else "http"
 def _get_commands(self,
                   session: Session,
                   service: Service,
                   collector_name: CollectorName,
                   command: str,
                   user: str = None,
                   password: str = None,
                   output_file: str = None) -> List[BaseCollector]:
     """Returns a list of commands based on the provided information."""
     collectors = []
     url = service.get_urlparse().geturl()
     url = url if url[-1] == "/" else url + "/"
     if url:
         os_command = [
             command, "--scope", "url", "--scan-force", "normal",
             "--format", "txt", "--no-bugreport", "--flush-attacks",
             "--flush-session"
         ]
         if self._user_agent:
             os_command += ['--user-agent', '{}'.format(self._user_agent)]
         else:
             os_command += [
                 '--user-agent',
                 '{}'.format(self._default_user_agent_string)
             ]
         if user:
             password = password if password else ""
             os_command += [
                 "--auth-type", "basic", "--auth-cred",
                 "{}%{}".format(user, password)
             ]
         if self._http_proxy:
             os_command += ['--proxy', self.http_proxy.geturl()]
         if output_file:
             os_command += [
                 "--output", ExecutionInfoType.binary_output_file.argument
             ]
         os_command += ["-u", url]
         collector = self._get_or_create_command(session,
                                                 os_command,
                                                 collector_name,
                                                 service=service,
                                                 binary_file=output_file)
         collectors.append(collector)
     return collectors
 def _get_commands(self, session: Session, service: Service,
                   collector_name: CollectorName,
                   command: str) -> List[BaseCollector]:
     """Returns a list of commands based on the provided information."""
     collectors = []
     wordlists = self._wordlist_files if self._wordlist_files else [
         self._wordlist_kiterunner
     ]
     for wordlist in wordlists:
         os_command = [
             command, 'scan', '--output', 'text', '--kitebuilder-full-scan',
             '-q', '-w', wordlist, '-x', 10, '--user-agent',
             self._user_agent
             if self._user_agent else self.default_user_agent,
             service.get_urlparse().geturl()
         ]
         collector = self._get_or_create_command(session,
                                                 os_command,
                                                 collector_name,
                                                 service=service)
         collectors.append(collector)
     return collectors
 def _get_commands(self,
                   session: Session,
                   service: Service,
                   collector_name: CollectorName,
                   command: str,
                   user: str = None,
                   password: str = None) -> List[BaseCollector]:
     """Returns a list of commands based on the provided information."""
     collectors = []
     if (service.host and service.host.version == 4) or service.host_name:
         url = service.get_urlparse()
         os_command = [command]
         if self._user_agent:
             os_command.extend(
                 ['-useragent', '{}'.format(self._user_agent)])
         else:
             os_command.extend([
                 '-useragent', '{}'.format(self._default_user_agent_string)
             ])
         if user:
             password = password if password else ""
             os_command.extend(["-id", "{}:{}".format(user, password)])
         if self._cookies:
             os_command.extend(['-c', self._cookies])
         if service.nmap_tunnel == 'ssl':
             os_command.append('-ssl')
         if self._http_proxy:
             os_command.extend(['-useproxy', self.http_proxy.geturl()])
         os_command.extend([
             '-Tuning', '12357b', '-no404', '-nointeractive', '-host',
             url.geturl()
         ])
         collector = self._get_or_create_command(session,
                                                 os_command,
                                                 collector_name,
                                                 service=service)
         collectors.append(collector)
     return collectors
 def _get_commands(self,
                   session: Session,
                   service: Service,
                   collector_name: CollectorName,
                   command: str,
                   user: str=None,
                   password: str=None) -> List[BaseCollector]:
     """Returns a list of commands based on the provided information."""
     collectors = []
     address = service.address
     if address:
         os_command = [command,
                       '--batch',
                       '--disable-coloring',
                       '--forms',
                       '--threads', '2',
                       '--risk', '3',
                       '--level', '5',
                       '--time-sec', '10',
                       '--crawl', '5',
                       '--technique', 'BEUSTQ',
                       '-u', service.get_urlparse().geturl()]
         if self._user_agent:
             os_command.append('--user-agent={}'.format(self._user_agent))
         else:
             os_command.append('--user-agent={}'.format(self._default_user_agent_string))
         if user:
             password = password if password else ""
             os_command.extend(["--auth-type=Basic",
                                "--auth-cred={}:{}".format(user, password)])
         if self._cookies:
             os_command.append('--cookie={}'.format(self._cookies[0]))
         if self._http_proxy:
             os_command.append('--proxy={}'.format(self.http_proxy.geturl()))
         collector = self._get_or_create_command(session, os_command, collector_name, service=service)
         collectors.append(collector)
     return collectors
Example #16
0
 def _get_commands(self,
                   session: Session,
                   collector_name: CollectorName,
                   workspace: Workspace,
                   output_path: str,
                   input_file: str = None,
                   host: Host = None,
                   network: Network = None,
                   host_name: HostName = None,
                   email: Email = None,
                   company: Company = None,
                   service: Service = None) -> List[BaseCollector]:
     """Returns a list of commands based on the provided information."""
     collectors = []
     python3_command = self._path_python3
     kisimport_command = self._path_kisimport
     if not self.api_credentials_available():
         logger.warning("api keys not set in config file '{}' for "
                        "collector {}".format(self._api_config.full_path,
                                              collector_name.name))
         return collectors
     if host:
         target = host.address
     elif network:
         target = network.network
     elif host_name:
         target = host_name.domain_name.name
     elif email:
         target = email.email_address
     elif company:
         target = company.name
     elif service:
         target = service.get_urlparse().geturl()
     else:
         raise ValueError("parameter host, host_name, email, company, or service is required")
     if not os.path.isfile(kisimport_command):
         raise FileNotFoundError("script '{}' does not exist".format(kisimport_command))
     # Create command
     os_command = [python3_command,
                   kisimport_command,
                   "kiscollect",
                   '-w', workspace.name,
                   "-O", ExecutionInfoType.output_path.argument,
                   "--id", ExecutionInfoType.command_id.argument]
     if input_file:
         os_command += [self._argument_name, ExecutionInfoType.input_file.argument]
     else:
         os_command += [self._argument_name, target]
     # Add command to database
     command = self._get_or_create_command(session,
                                           os_command,
                                           collector_name,
                                           host=host,
                                           network=network,
                                           host_name=host_name,
                                           email=email,
                                           company=company,
                                           output_path=output_path,
                                           service=service,
                                           input_file=input_file)
     command.execution_info[ExecutionInfoType.command_id.name] = str(command.id)
     collectors.append(command)
     return collectors
Example #17
0
 def import_content(self, xml_content: str) -> None:
     """
     This method imports the given XML content into the database.
     :param xml_content: The XML content
     :return:
     """
     try:
         root = ET.fromstring(xml_content)
     except xml.etree.ElementTree.ParseError:
         root = ET.fromstring(xml_content + "</nmaprun>")
     source = Engine.get_or_create(self._session, Source, name=self._source)
     re_domain = re.compile("^Domain: (?P<domain>.+?), Site: .*$")
     for host_tag in root.findall('host'):
         host = None
         ipv4_address = None
         ipv6_address = None
         mac_address = None
         status_tag = host_tag.findall("status")
         host_up = None
         host_up_reason = None
         if status_tag:
             host_up = DatabaseImporter.get_xml_attribute(
                 "state", status_tag[0].attrib) == "up"
             host_up_reason = DatabaseImporter.get_xml_attribute(
                 "reason", status_tag[0].attrib)
         port_tags = host_tag.findall('*/port')
         for addr in host_tag.findall('address'):
             type = DatabaseImporter.get_xml_attribute(
                 "addrtype", addr.attrib)
             if type == "ipv4":
                 ipv4_address = DatabaseImporter.get_xml_attribute(
                     "addr", addr.attrib)
                 resource_type = DnsResourceRecordType.a
             if type == "ipv6":
                 ipv6_address = DatabaseImporter.get_xml_attribute(
                     "addr", addr.attrib)
                 resource_type = DnsResourceRecordType.aaaa
             if type == "mac":
                 mac_address = DatabaseImporter.get_xml_attribute(
                     "addr", addr.attrib)
         if not host_up:
             print("[I]   host '{}' is down and thus, is not imported.".
                   format(ipv4_address),
                   file=self._stdout)
             continue
         if ipv4_address and ipv6_address:
             raise NotImplementedError(
                 "case IPv4 and IPv6 address available at the same time is not implemented"
             )
         host_created = False
         for port in port_tags:
             port_state_tag = port.findall("state[1]")[0].attrib
             port_state = DatabaseImporter.get_xml_attribute(
                 "state", port_state_tag)
             extra_reason = DatabaseImporter.get_xml_attribute(
                 "reason", port_state_tag)
             service_protocol = DatabaseImporter.get_xml_attribute(
                 "protocol", port.attrib)
             service_protocol = Service.get_protocol_type(service_protocol)
             port_state = Service.get_service_state(port_state)
             if port_state in self._service_states:
                 if not host_created:
                     host_created = True
                     # at least one service exists and therefore, we create the host
                     host = self._create_host(source, host_up,
                                              host_up_reason, host_tag,
                                              ipv4_address, ipv6_address,
                                              mac_address)
                 service_port = DatabaseImporter.get_xml_attribute(
                     "portid", port.attrib)
                 service = self._domain_utils.add_service(
                     session=self._session,
                     port=service_port,
                     protocol_type=service_protocol,
                     state=port_state,
                     host=host,
                     source=source,
                     report_item=self._report_item)
                 service.nmap_service_state_reason = extra_reason
                 services = port.findall("service[1]")
                 if len(services) == 1:
                     service_tag = services[0]
                     nmap_service_confidence = DatabaseImporter.get_xml_attribute(
                         "conf", service_tag.attrib)
                     nmap_service_confidence = int(nmap_service_confidence) \
                         if nmap_service_confidence is not None else None
                     service_name = DatabaseImporter.get_xml_attribute(
                         "name", service_tag.attrib)
                     service.nmap_service_name_original = service_name
                     tunnel = DatabaseImporter.get_xml_attribute(
                         "tunnel", service_tag.attrib)
                     if service_name == "http" and tunnel == "ssl":
                         service_name = DatabaseImporter.HTTPS_SERVICE_NAME[
                             0]
                     service.nmap_service_name = service_name
                     service.nmap_service_confidence = nmap_service_confidence
                     service.nmap_product = DatabaseImporter.get_xml_attribute(
                         "product", service_tag.attrib)
                     service.nmap_version = DatabaseImporter.get_xml_attribute(
                         "version", service_tag.attrib)
                     service.nmap_os_type = DatabaseImporter.get_xml_attribute(
                         "ostype", service_tag.attrib)
                     service.nmap_tunnel = DatabaseImporter.get_xml_attribute(
                         "tunnel", service_tag.attrib)
                     if service.nmap_os_type and host.os_family is None:
                         os = service.nmap_os_type.lower()
                         host.os_family = "windows" if " windows " in os else os
                     if not service.nmap_tunnel and service_name == DatabaseImporter.HTTPS_SERVICE_NAME[
                             0]:
                         service.nmap_tunnel = "ssl"
                     for item in ["debian", "ubuntu"]:
                         if service.nmap_version and item in service.nmap_version.lower(
                         ) and host.os_family is None:
                             host.os_family = "linux"
                     hostname = DatabaseImporter.get_xml_attribute(
                         "hostname", service_tag.attrib)
                     hostname_levels = len(
                         hostname.split(".")) if hostname else 0
                     if hostname:
                         host_name = self._domain_utils.add_domain_name(
                             session=self._session,
                             workspace=host.workspace,
                             item=hostname,
                             source=source,
                             verify=True,
                             report_item=self._report_item)
                         if not host_name:
                             print("[I]   ignoring host name: {}".format(
                                 hostname.lower()),
                                   file=self._stdout)
                         else:
                             self._domain_utils.add_host_host_name_mapping(
                                 self._session,
                                 host=host,
                                 host_name=host_name,
                                 source=source,
                                 mapping_type=resource_type,
                                 report_item=self._report_item)
                     extra_info = DatabaseImporter.get_xml_attribute(
                         "extrainfo", service_tag.attrib)
                     if extra_info:
                         service.nmap_extra_info = extra_info
                         match_domain = re_domain.match(extra_info)
                         if match_domain:
                             domain = match_domain.group("domain")
                             domain_level = len(domain)
                             if hostname_levels == 1 and domain_level > 1:
                                 host_name = self._domain_utils.add_domain_name(
                                     session=self._session,
                                     workspace=self._workspace,
                                     item="{}.{}".format(hostname, domain),
                                     source=source,
                                     verify=True,
                                     report_item=self._report_item)
                             else:
                                 host_name = self._domain_utils.add_domain_name(
                                     session=self._session,
                                     workspace=self._workspace,
                                     item=domain,
                                     source=source,
                                     verify=True,
                                     report_item=self._report_item)
                             if host_name:
                                 self._domain_utils.add_host_host_name_mapping(
                                     self._session,
                                     host=host,
                                     host_name=host_name,
                                     source=source,
                                     mapping_type=resource_type,
                                     report_item=self._report_item)
                     self._analyze_fingerprint(service, port)
                     # Extract additional information from XML
                     self.extractor.execute(session=self._session,
                                            workspace=self._workspace,
                                            domain_utils=self._domain_utils,
                                            ip_utils=self._ip_utils,
                                            service=service,
                                            source=source,
                                            report_item=self._report_item,
                                            service_tag=extra_info,
                                            host_tag=host_tag,
                                            port_tag=port)
                 elif len(services) > 1:
                     raise NotImplementedError(
                         "more than one service identified. this case has not "
                         "been implemented!")
             if not host_created:
                 print(
                     "[I]   host '{}' did not have any services to import and thus, "
                     "is ignored".format(ipv4_address),
                     file=self._stdout)
         # if not host_created:
         #     host = self._create_host(source,
         #                              host_up,
         #                              host_up_reason,
         #                              host_tag,
         #                              ipv4_address,
         #                              ipv6_address,
         #                              mac_address)
         os_tag = host_tag.find("os")
         if host and os_tag is not None:
             for item in os_tag.findall("*/osclass"):
                 accuracy = DatabaseImporter.get_xml_attribute(
                     "accuracy", item.attrib)
                 if accuracy and int(accuracy) == 100:
                     osfamily = DatabaseImporter.get_xml_attribute(
                         "osfamily", item.attrib)
                     host.os_family = osfamily.lower(
                     ) if osfamily is not None and host.os_family is None else None
Example #18
0
 def _import_file(self, input_file: str) -> None:
     """
     This method imports the given file into the database.
     :param input_file: The file to be imported
     :return:
     """
     tree = ET.parse(input_file)
     root = tree.getroot()
     source = Engine.get_or_create(self._session, Source, name=self._source)
     for host_tag in root.findall('*/ReportHost'):
         host = None
         properties = host_tag.find("HostProperties")
         ip_address = DatabaseImporter.get_xml_attribute(
             "name", host_tag.attrib)
         if properties:
             ipv4_address = properties.find("*/[@name='host-ip']")
             ipv4_address = ipv4_address.text if ipv4_address is not None else ip_address
             os_info = properties.find("*/[@name='os']")
             os_info = os_info.text if os_info is not None else None
             host = self._ip_utils.add_host(session=self._session,
                                            workspace=self._workspace,
                                            address=ipv4_address,
                                            source=source,
                                            report_item=self._report_item)
             host.os_family = os_info.lower(
             ) if os_info is not None and host.os_family is None else None
         if host:
             for item in host_tag.findall("ReportItem"):
                 port = int(
                     DatabaseImporter.get_xml_attribute(
                         "port", item.attrib))
                 severity = int(
                     DatabaseImporter.get_xml_attribute(
                         "severity", item.attrib))
                 protocol = DatabaseImporter.get_xml_attribute(
                     "protocol", item.attrib)
                 service_name = DatabaseImporter.get_xml_attribute(
                     "svc_name", item.attrib)
                 if service_name:
                     if service_name[-1] == '?':
                         confidence = 7
                         service_name = service_name[:-1]
                     else:
                         confidence = 10
                 else:
                     confidence = None
                 protocol = Service.get_protocol_type(protocol)
                 if protocol:
                     if port > 0:
                         plugin_id = DatabaseImporter.get_xml_attribute(
                             "pluginID", item.attrib)
                         plugin_name = DatabaseImporter.get_xml_attribute(
                             "pluginName", item.attrib)
                         nmap_tunnel = "ssl" if plugin_id == "56984" and \
                                                plugin_name == "SSL / TLS Versions Supported" else None
                         service = self._domain_utils.add_service(
                             session=self._session,
                             port=port,
                             protocol_type=protocol,
                             state=ServiceState.Open,
                             nessus_service_confidence=confidence,
                             nessus_service_name=service_name,
                             host=host,
                             nmap_tunnel=nmap_tunnel,
                             source=source,
                             report_item=self._report_item)
                         # add vulnerability information
                         if severity > 0:
                             description = XmlUtils.get_element_text(
                                 item, "description")
                             cve = XmlUtils.get_element_text(item, "cve")
                             cvss_base_score = XmlUtils.get_element_text(
                                 item, "cvss_base_score")
                             cvss3_base_score = XmlUtils.get_element_text(
                                 item, "cvss3_base_score")
                             row = [[
                                 cve, cvss3_base_score, cvss_base_score,
                                 "{} - {}".format(plugin_id,
                                                  plugin_name), description
                             ]]
                             vulnerability = self._domain_utils.get_list_as_csv(
                                 row)
                             self._domain_utils.add_additional_info(
                                 session=self._session,
                                 service=service,
                                 name="CVEs",
                                 values=vulnerability,
                                 source=source,
                                 report_item=self._report_item)
Example #19
0
 def import_content(self, xml_content: str) -> None:
     """
     This method imports the given XML content into the database.
     :param xml_content: The XML content
     :return:
     """
     try:
         root = ET.fromstring(xml_content)
     except xml.etree.ElementTree.ParseError:
         return
     source = Engine.get_or_create(self._session, Source, name=self._source)
     for host_tag in root.findall('host'):
         ipv4_address = None
         ipv6_address = None
         mac_address = None
         for addr in host_tag.findall('address'):
             type = DatabaseImporter.get_xml_attribute(
                 "addrtype", addr.attrib)
             if type == "ipv4":
                 ipv4_address = DatabaseImporter.get_xml_attribute(
                     "addr", addr.attrib)
             elif type == "ipv6":
                 ipv6_address = DatabaseImporter.get_xml_attribute(
                     "addr", addr.attrib)
             elif type == "mac":
                 mac_address = DatabaseImporter.get_xml_attribute(
                     "addr", addr.attrib)
         if ipv4_address:
             host = self._ip_utils.add_host(session=self._session,
                                            workspace=self._workspace,
                                            address=ipv4_address,
                                            source=source,
                                            report_item=self._report_item)
         elif ipv6_address:
             host = self._ip_utils.add_host(session=self._session,
                                            workspace=self._workspace,
                                            address=ipv6_address,
                                            source=source,
                                            report_item=self._report_item)
         else:
             raise NotImplementedError(
                 "the case that the host neither has an IPv4 nor an IPv6 address is not "
                 "implemented!")
         host.mac_address = mac_address
         for port in host_tag.findall('*/port'):
             port_state_tag = port.findall("state[1]")[0].attrib
             port_state = DatabaseImporter.get_xml_attribute(
                 "state", port_state_tag)
             port_state = Service.get_service_state(port_state)
             if port_state == ServiceState.Open:
                 service_protocol = DatabaseImporter.get_xml_attribute(
                     "protocol", port.attrib)
                 service_port = DatabaseImporter.get_xml_attribute(
                     "portid", port.attrib)
                 service_protocol = Service.get_protocol_type(
                     service_protocol)
                 service = self._domain_utils.add_service(
                     session=self._session,
                     port=service_port,
                     protocol_type=service_protocol,
                     state=port_state,
                     host=host,
                     source=source,
                     report_item=self._report_item)
                 service.nmap_service_state_reason = DatabaseImporter.get_xml_attribute(
                     "reason", port_state_tag)
                 if port.findall("service[@name='ssl']"):
                     service.nmap_tunnel = "ssl"