def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        if command.return_code and command.return_code > 0:
            command.hide = False
            self._set_execution_failed(session, command)
            return
        else:
            command.hide = True
        for line in command.stdout_output:
            line = line.strip()
            match = self._smb_info_re.match(line)
            if match:
                os_info = match.group("os").strip()
                domain = match.group("domain").strip()
                signing = match.group("signing").strip().lower()
                smbv1 = match.group("smbv1").strip().lower()
                if domain:
                    command.host.workgroup = domain
                    self.add_host_name(session=session,
                                       command=command,
                                       host_name=domain,
                                       source=source,
                                       verify=True,
                                       report_item=report_item)
                if os_info:
                    if "windows" in os_info.lower():
                        command.host.os_family = "windows"
                    command.host.os_details = os_info
                if signing and signing in ['true', 'false']:
                    command.service.smb_message_signing = signing == 'true'
                self.add_additional_info(
                    session=session,
                    command=command,
                    service=command.service,
                    name="SMB",
                    values=[
                        "SMB message signing: {}, SMBv1: {}".format(
                            signing, smbv1)
                    ],
                    source=source,
                    report_item=report_item)
Example #2
0
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hide = command.return_code and command.return_code > 0
        output = os.linesep.join(command.stderr_output) + os.linesep.join(
            command.stdout_output)
        for match in self._nt_status_re.finditer(output):
            code = match.group("value")
            if code in self._failed_status:
                command.hide = True
                break
Example #3
0
    def verify_results(self, session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None, **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        for line in command.stdout_output:
            if self._re_no_response.match(line):
                command.hide = True
                break
        paths = self.add_robots_txt(session=session,
                                    command=command,
                                    service=command.service,
                                    robots_txt=command.stdout_output,
                                    source=source,
                                    report_item=report_item)
        if not paths:
            command.hide = True
Example #4
0
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        summary = False
        text = "{} Summary:".format(self._path_davtest)
        for line in command.stdout_output:
            if summary and line:
                command.hide = False
                report_item.details = "potential file upload via HTTP PUT"
                report_item.report_type = "UPLOAD"
                self.add_report_item(report_item)
            if text in line:
                summary = True
Example #5
0
    def verify_results(self, session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None, **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        success = False
        for line in command.stdout_output:
            match_creds = self._re_success.match(line)
            if match_creds:
                success = True
                credential = self.add_credential(session=session,
                                                 command=command,
                                                 username=None,
                                                 password=None,
                                                 credential_type=None,
                                                 source=source,
                                                 service=command.service,
                                                 report_item=report_item)
                if not credential:
                    logger.debug("ignoring credentials in line: {}".format(line))
        command.hide = not success
    def verify_results(self, session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None, **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hint = []
        for line in command.stdout_output:
            match = self._export_re.match(line)
            if match:
                export = match.group("export").strip().strip('"').strip("'")
                self.add_path(session=session,
                              command=command,
                              service=command.service,
                              path=export,
                              path_type=PathType.nfs_export,
                              source=source,
                              report_item=report_item)
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hint = []
        command.hide = command.return_code and command.return_code > 0
        for line in command.stdout_output:
            line = line.strip()
            match_share = self._re_shares.match(line)
            if match_share:
                ipv4_address = command.service.host.ipv4_address
                name = "/{}".format(match_share.group(1))
                self.add_path(session=session,
                              command=command,
                              service=command.service,
                              path=name,
                              path_type=PathType.smb_share,
                              source=source,
                              report_item=report_item)
                self.add_hint(
                    command=command,
                    hint="$ smbclient //{}{} -U\"$user\"%\"$password\" -c "
                    "'prompt OFF;recurse ON;mget *'".format(
                        ipv4_address, name))
                self.add_hint(
                    command=command,
                    hint=
                    "$ sudo mount -t cifs -o user=$usr,password=$pwd //{}/{} "
                    "$mountpoint".format(ipv4_address, name))
Example #8
0
 def _filter(self, command: Command) -> bool:
     """
     Method determines whether the given item shall be included into the report
     """
     return command.is_processable(
         included_items=self._included_items,
         excluded_items=self._excluded_items,
         exclude_collectors=self._excluded_collectors,
         include_collectors=self._included_collectors,
         scope=self._scope)
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        if command.return_code and command.return_code > 0:
            self._set_execution_failed(session, command)
        else:
            command.hide = True
        command.stderr_output = []
        for line in command.stdout_output:
            line = line.strip()
            match = self._result_re.match(line)
            if match:
                size_bytes = int(match.group("size"))
                status_code = int(match.group("status"))
                url = match.group("url")
                self.add_url_path(session=session,
                                  service=command.service,
                                  url_path=url,
                                  status_code=status_code,
                                  size_bytes=size_bytes,
                                  source=source,
                                  report_item=report_item)
Example #10
0
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        contexts = {}
        unique = {}
        matchers = [
            "defaultNamingContext:", "defaultNamingContext:",
            "rootDomainNamingContext:"
        ]
        command.hint = []
        for line in command.stdout_output:
            for matcher in matchers:
                if matcher in line:
                    tmp = line.split(":")
                    if len(tmp) >= 2:
                        key = tmp[0]
                        value = ":".join(tmp[1:])
                        contexts[key] = value
                        unique[value] = True
        for key, value in contexts.items():
            self.add_additional_info(session=session,
                                     command=command,
                                     service=command.service,
                                     name="{} {}".format(
                                         command.collector_name.name, key),
                                     values=[value],
                                     source=source,
                                     report_item=report_item)
        for key, _ in unique.items():
            new_command = command.os_command_substituted[:-2]
            new_command.extend(['-b', '"{}"'.format(key)])
            self.add_hint(command=command,
                          hint="$ {}".format(" ".join(new_command)))
Example #11
0
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hide = True
        for line in command.stdout_output:
            path_status_pair = None
            line = line.strip()
            match = self._re_path.match(line)
            match_wildcard = self._re_wildcard_response.match(line)
            if match:
                path_str = match.group(1).strip()
                status_code = int(match.group(2).strip())
                size_bytes = int(match.group(3).strip())
                path_status_pair = [path_str, status_code, size_bytes]
            elif match_wildcard:
                path_str = match.group(1).strip()
                status_code = int(match.group(2).strip())
                path_status_pair = [path_str, status_code, None]
            if path_status_pair:
                path_str, status_code, size_bytes = path_status_pair
                url = self.add_url_path(session=session,
                                        service=command.service,
                                        url_path=path_str,
                                        status_code=status_code,
                                        size_bytes=size_bytes,
                                        source=source,
                                        report_item=report_item)
                if not url:
                    logger.debug(
                        "ignoring host name due to invalid domain in line: {}".
                        format(line))
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hide = True
        for line in command.stdout_output:
            match = self._re_pointer.match(line)
            if match:
                host_name = match.group("value").strip().lower()
                # Add host name to database
                host_name = self.add_host_name(session=session,
                                               command=command,
                                               source=source,
                                               host_name=host_name,
                                               report_item=report_item)
                if not host_name:
                    logger.debug(
                        "ignoring host name due to invalid domain in line: {}".
                        format(line))
                else:
                    self.add_host_host_name_mapping(
                        session=session,
                        command=command,
                        host=command.host,
                        host_name=host_name,
                        source=source,
                        mapping_type=DnsResourceRecordType.ptr,
                        report_item=report_item)
Example #13
0
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hide = True
        output = os.linesep.join(command.stdout_output)
        certificates = self._re_cert.findall(output)
        certificates_len = len(certificates)
        if certificates_len == 0:
            self._set_execution_failed(session, command)
        for i in range(0, certificates_len):
            if i == 0:
                cert_type = CertType.identity
            elif i == (certificates_len - 1):
                cert_type = CertType.root
            else:
                cert_type = CertType.intermediate
            self.add_certificate(session=session,
                                 command=command,
                                 content=certificates[i],
                                 type=cert_type,
                                 source=source,
                                 report_item=report_item)
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hide = True
        for line in command.stdout_output:
            match = self._success_re.match(line)
            if match:
                ntlm = match.group("ntlm")
                lm = match.group("lm")
                user_name = match.group("user")
                domain = match.group("domain")
                self.add_credential(session=session,
                                    command=command,
                                    password="******".format(lm, ntlm),
                                    credential_type=CredentialType.hash,
                                    username=user_name,
                                    domain=domain,
                                    source=source,
                                    service=command.service,
                                    report_item=report_item)
Example #15
0
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hide = True
        for line in command.stdout_output:
            match = self._re_entry.match(line)
            if match:
                host_name_str = match.group("hostname").strip(". ")
                record_type_str = match.group("type").strip().lower()
                content = match.group("content").strip().strip(". ")
                try:
                    record_type = DnsResourceRecordType[record_type_str]
                    host_name = self.add_host_name(session=session,
                                                   command=command,
                                                   host_name=host_name_str,
                                                   source=source,
                                                   report_item=report_item)
                    if host_name:
                        if record_type in [
                                DnsResourceRecordType.a,
                                DnsResourceRecordType.aaaa
                        ] and content:
                            # Add IPv4 address to database
                            host = self.add_host(session=session,
                                                 command=command,
                                                 source=source,
                                                 address=content,
                                                 report_item=report_item)
                            if not host:
                                logger.debug(
                                    "ignoring host due to invalid IP address in line: {}"
                                    .format(line))
                            else:
                                self.add_host_host_name_mapping(
                                    session=session,
                                    command=command,
                                    host=host,
                                    host_name=host_name,
                                    source=source,
                                    mapping_type=record_type,
                                    report_item=report_item)
                        if record_type == DnsResourceRecordType.cname and content:
                            cname_host_name = self.add_host_name(
                                session=session,
                                command=command,
                                host_name=content,
                                source=source,
                                report_item=report_item)
                            if cname_host_name:
                                self.add_host_name_host_name_mapping(
                                    session=session,
                                    command=command,
                                    source_host_name=host_name,
                                    resolved_host_name=cname_host_name,
                                    source=source,
                                    mapping_type=DnsResourceRecordType.cname,
                                    report_item=report_item)
                            else:
                                logger.debug(
                                    "ignoring host name due to invalid domain in line: {}"
                                    .format(line))

                        else:
                            for item in self._domain_utils.extract_domains(
                                    content):
                                host_name = self.add_host_name(
                                    session=session,
                                    command=command,
                                    host_name=item,
                                    source=source,
                                    report_item=report_item)
                                if not host_name:
                                    logger.debug(
                                        "ignoring host name due to invalid domain in line: {}"
                                        .format(line))
                    else:
                        logger.debug(
                            "ignoring host name due to invalid domain in line: {}"
                            .format(line))
                except KeyError as ex:
                    logger.exception(ex)
Example #16
0
    def verify_results(self, session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None, **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        companies = {}
        email_objects = {}
        network_objects = {}
        command.hide = True
        # extract company names
        for line in command.stdout_output:
            match = self._re_organizations.match(line)
            if match:
                name = match.group("name").strip().lower()
                companies[name] = None
        # extract IPv4/IPv6 networks and emails
        for line in command.stdout_output:
            match_ip_network_range = self._re_ip_network_range.match(line)
            match_ipv4_network_cidr = self._re_ipv4_network_cidr.match(line)
            match_ipv6_network_cidr = self._re_ipv6_network_cidr.match(line)
            emails = self._email_utils.extract_emails(line)
            for email in emails:
                email_objects[email] = None
            if match_ip_network_range:
                try:
                    for item in IpUtils.qualys_to_cidr(match_ip_network_range.group("range")):
                        network_objects[str(item)] = None
                except ValueError as ex:
                    logger.exception(ex)
            elif match_ipv4_network_cidr:
                try:
                    for item in self._split_cidr(match_ipv4_network_cidr.group("range")):
                        network_objects[item] = None
                except ValueError as ex:
                    logger.exception(ex)
            elif match_ipv6_network_cidr:
                try:
                    for item in self._split_cidr(match_ipv6_network_cidr.group("range")):
                        network_objects[item] = None
                except ValueError as ex:
                    logger.exception(ex)
        # saving companies, IPv4/IPv6 networks, and emails
        for item in network_objects.keys():
            network = self.add_network(session=session,
                                       command=command,
                                       network=item,
                                       source=source,
                                       report_item=report_item)
            if not network:
                logger.debug("ignoring network '{}' due to invalid format.".format(item))
            else:
                for name in companies.keys():
                    company = self.add_company(session=session,
                                               workspace=command.workspace,
                                               name=name,
                                               network=network,
                                               source=source,
                                               report_item=report_item)
                    if not company:
                        logger.debug("ignoring company '{}' due to invalid format.".format(company))
        for item in email_objects.keys():
            email = self.add_email(session=session,
                                   command=command,
                                   email=item,
                                   source=source,
                                   report_item=report_item)
            if not email:
                logger.debug("ignoring email '{}' due to invalid format.")
            else:
                for name in companies.keys():
                    company = self.add_company(session=session,
                                               workspace=command.workspace,
                                               name=name,
                                               domain_name=email.host_name.domain_name,
                                               source=source,
                                               report_item=report_item)
                    if not company:
                        logger.debug("ignoring company '{}' due to invalid format.".format(company))
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hide = True
        for line in command.stdout_output:
            line = line.strip()
            match = self._re_vhost.match(line)
            if match:
                vhost = match.group("vhost").strip()
                return_code = int(match.group("status").strip())
                size_bytes = int(match.group("size").strip())
                if IpUtils.is_valid_address(vhost):
                    # Add IP address to database
                    host = self.add_host(session=session,
                                         command=command,
                                         address=vhost,
                                         source=source,
                                         report_item=report_item)
                    if not host:
                        logger.debug(
                            "ignoring IP address due to invalid domain in line: {}"
                            .format(line))
                    else:
                        self.add_vhost_name_mapping(session=session,
                                                    host=host,
                                                    service=command.service,
                                                    return_code=return_code,
                                                    size_bytes=size_bytes,
                                                    source=source,
                                                    report_item=report_item)
                else:
                    # Add host name to database
                    host_name = self.add_host_name(session=session,
                                                   command=command,
                                                   source=source,
                                                   host_name=vhost,
                                                   verify=False,
                                                   report_item=report_item)
                    if not host_name:
                        logger.debug(
                            "ignoring host name due to invalid domain in line: {}"
                            .format(line))
                    else:
                        self.add_vhost_name_mapping(session=session,
                                                    host_name=host_name,
                                                    service=command.service,
                                                    return_code=return_code,
                                                    size_bytes=size_bytes,
                                                    source=source,
                                                    report_item=report_item)
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hide = True
        if command.return_code and command.return_code > 0:
            self._set_execution_failed(session=session, command=command)
        try:
            if command.json_output:
                for json_object in command.json_output:
                    if "server_scan_results" in json_object:
                        # Obtain all relevant information from JSON object
                        server_scan_results = json_object[
                            "server_scan_results"]
                        for server_scan_result in server_scan_results:
                            certificate_deployments = self._json_utils.get_attribute_value(
                                json_object=server_scan_result,
                                path=
                                "scan_result/certificate_info/result/certificate_deployments",
                                default_value=[])
                            ssl_2_0_cipher_suites = self._json_utils.get_attribute_value(
                                json_object=server_scan_result,
                                path="scan_result/ssl_2_0_cipher_suites/result"
                            )
                            ssl_3_0_cipher_suites = self._json_utils.get_attribute_value(
                                json_object=server_scan_result,
                                path="scan_result/ssl_3_0_cipher_suites/result"
                            )
                            tls_1_0_cipher_suites = self._json_utils.get_attribute_value(
                                json_object=server_scan_result,
                                path="scan_result/tls_1_0_cipher_suites/result"
                            )
                            tls_1_1_cipher_suites = self._json_utils.get_attribute_value(
                                json_object=server_scan_result,
                                path="scan_result/tls_1_1_cipher_suites/result"
                            )
                            tls_1_2_cipher_suites = self._json_utils.get_attribute_value(
                                json_object=server_scan_result,
                                path="scan_result/tls_1_2_cipher_suites/result"
                            )
                            tls_1_3_cipher_suites = self._json_utils.get_attribute_value(
                                json_object=server_scan_result,
                                path="scan_result/tls_1_3_cipher_suites/result"
                            )
                            # Parse the certificate information
                            for certificate_deployment in certificate_deployments:
                                if "received_certificate_chain" in certificate_deployment and \
                                        isinstance(certificate_deployment["received_certificate_chain"], list):
                                    chain = certificate_deployment[
                                        "received_certificate_chain"]
                                    i = 1
                                    for item in chain:
                                        if "as_pem" in item:
                                            self.add_certificate(
                                                session=session,
                                                command=command,
                                                content=item["as_pem"],
                                                type=CertType.identity if i
                                                == 1 else CertType.intermediate
                                                if i < len(chain) else
                                                CertType.root,
                                                source=source,
                                                report_item=report_item)
                                            i += 1
                                        else:
                                            raise NotImplementedError(
                                                "unexpected JSON format (missing attribute 'as_pem')"
                                            )
                                else:
                                    raise NotImplementedError(
                                        "unexpected JSON format (missing attribute "
                                        "'received_certificate_chain')")
                            # Process all TLS versions
                            self._parse_cipher_suites(
                                session=session,
                                command=command,
                                report_item=report_item,
                                source=source,
                                tls_version=TlsVersion.ssl2,
                                tls_result=ssl_2_0_cipher_suites)
                            self._parse_cipher_suites(
                                session=session,
                                command=command,
                                report_item=report_item,
                                source=source,
                                tls_version=TlsVersion.ssl3,
                                tls_result=ssl_3_0_cipher_suites)
                            self._parse_cipher_suites(
                                session=session,
                                command=command,
                                report_item=report_item,
                                source=source,
                                tls_version=TlsVersion.tls10,
                                tls_result=tls_1_0_cipher_suites)
                            self._parse_cipher_suites(
                                session=session,
                                command=command,
                                report_item=report_item,
                                source=source,
                                tls_version=TlsVersion.tls11,
                                tls_result=tls_1_1_cipher_suites)
                            self._parse_cipher_suites(
                                session=session,
                                command=command,
                                report_item=report_item,
                                source=source,
                                tls_version=TlsVersion.tls12,
                                tls_result=tls_1_2_cipher_suites)
                            self._parse_cipher_suites(
                                session=session,
                                command=command,
                                report_item=report_item,
                                source=source,
                                tls_version=TlsVersion.tls13,
                                tls_result=tls_1_3_cipher_suites)
        except xml.etree.ElementTree.ParseError as e:
            logger.exception(e)
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hide = True
        try:
            tls_info_list = {}
            if command.xml_output:
                xml_root = ET.fromstring(command.xml_output)
                if xml_root is None:
                    return
                results_tag = xml_root.find("ssltest")
                if results_tag is None:
                    return
                certinfo = results_tag.find(
                    "./certificates/*/certificate-blob")
                if certinfo is not None and certinfo.text:
                    self.add_certificate(session=session,
                                         command=command,
                                         content=certinfo.text,
                                         type=CertType.identity,
                                         source=source,
                                         report_item=report_item)
                else:
                    logger.error("no certificate information found.")
                order = 1
                for cipher_tag in results_tag.findall("cipher"):
                    status = self._xml_utils.get_xml_attribute(
                        "status", cipher_tag.attrib)
                    sslversion = self._xml_utils.get_xml_attribute(
                        "sslversion", cipher_tag.attrib)
                    cipher = self._xml_utils.get_xml_attribute(
                        "cipher", cipher_tag.attrib)
                    curve = self._xml_utils.get_xml_attribute(
                        "curve", cipher_tag.attrib)
                    tls_version = TlsInfo.get_tls_version(sslversion)
                    if tls_version:
                        heartbleed_tag = results_tag.find(
                            "heartbleed[@sslversion='{}']".format(sslversion))
                        heartbleed = self._xml_utils.get_xml_attribute(
                            "vulnerable", heartbleed_tag.attrib)
                        heartbleed = heartbleed != "0"
                        if sslversion not in tls_info_list:
                            tls_info_list[sslversion] = self.add_tls_info(
                                session=session,
                                service=command.service,
                                version=tls_version,
                                heartbleed=heartbleed)
                            order = 1
                        if tls_info_list[sslversion]:
                            tls_info = tls_info_list[sslversion]
                            kex_algorithm = TlsInfoCipherSuiteMapping.get_kex_algorithm(
                                curve) if curve else None
                            # sslscan does not consistently use one cipher suite notation.
                            mapping = self.add_tls_info_cipher_suite_mapping(
                                session=session,
                                tls_info=tls_info,
                                order=order,
                                kex_algorithm_details=kex_algorithm,
                                gnutls_name=cipher,
                                prefered=status == "preferred",
                                source=source,
                                report_item=report_item)
                            if not mapping:
                                mapping = self.add_tls_info_cipher_suite_mapping(
                                    session=session,
                                    tls_info=tls_info,
                                    order=order,
                                    kex_algorithm_details=kex_algorithm,
                                    iana_name=cipher,
                                    prefered=status == "preferred",
                                    source=source,
                                    report_item=report_item)
                                if not mapping:
                                    mapping = self.add_tls_info_cipher_suite_mapping(
                                        session=session,
                                        tls_info=tls_info,
                                        order=order,
                                        kex_algorithm_details=kex_algorithm,
                                        openssl_name=cipher,
                                        prefered=status == "preferred",
                                        source=source,
                                        report_item=report_item)
                                    if not mapping:
                                        logger.error(
                                            "cipher suite '{}' does not exist. ignoring cipher suite"
                                            .format(cipher))
                            if mapping:
                                order += 1
        except xml.etree.ElementTree.ParseError as e:
            logger.exception(e)
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hide = True
        if command.return_code and command.return_code > 0:
            self._set_execution_failed(session, command)
        for line in command.stdout_output:
            match = self._re_organizations.match(line)
            if match:
                name = match.group("name").strip().lower()
                company = self.add_company(
                    session=session,
                    workspace=command.workspace,
                    name=name,
                    domain_name=command.host_name.domain_name,
                    source=source,
                    report_item=report_item)
                if not company:
                    logger.debug("ignoring company: {}".format(name))
            emails = self._email_utils.extract_emails(line)
            match = self._re_name_server_info.match(line)
            if match:
                host_name = match.group("domain")
                ipv4_address = match.group("ipv4")
                host = self.add_host(session=session,
                                     command=command,
                                     address=ipv4_address,
                                     source=source,
                                     report_item=report_item)
                if not host:
                    logger.debug(
                        "ignoring host due to invalid address in line: {}".
                        format(line))
                host_name = self.add_host_name(session=session,
                                               command=command,
                                               host_name=host_name,
                                               source=source,
                                               report_item=report_item)
                if not host_name:
                    logger.debug(
                        "ignoring host name due to invalid domain in line: {}".
                        format(line))
                elif host:
                    self.add_host_host_name_mapping(
                        session=session,
                        command=command,
                        host=host,
                        host_name=host_name,
                        source=source,
                        mapping_type=DnsResourceRecordType.ns,
                        report_item=report_item)
            for item in emails:
                email = self.add_email(session=session,
                                       command=command,
                                       email=item,
                                       source=source,
                                       report_item=report_item)
                if not email:
                    logger.debug("ignoring company: {}".format(item))
Example #21
0
    def verify_results(self,
                       session: Session,
                       command: Command,
                       source: Source,
                       report_item: ReportItem,
                       process: PopenCommand = None,
                       **kwargs) -> None:
        """This method analyses the results of the command execution.

        After the execution, this method checks the OS command's results to determine the command's execution status as
        well as existing vulnerabilities (e.g. weak login credentials, NULL sessions, hidden Web folders). The
        stores the output in table command. In addition, the collector might add derived information to other tables as
        well.

        :param session: Sqlalchemy session that manages persistence operations for ORM-mapped objects
        :param command: The command instance that contains the results of the command execution
        :param source: The source object of the current collector
        :param report_item: Item that can be used for reporting potential findings in the UI
        :param process: The PopenCommand object that executed the given result. This object holds stderr, stdout, return
        code etc.
        """
        command.hide = True
        for line in command.stdout_output:
            ipv4_match = self._re_ipv4.match(line)
            ipv6_match = self._re_ipv6.match(line)
            cname_match = self._re_cname.match(line)
            mx_host_match = self._re_host_mx.match(line)
            if ipv4_match:
                source_host_str = ipv4_match.group("domain").strip()
                address = ipv4_match.group("address")
                # Add IPv4 address to database
                host = self.add_host(session=session,
                                     command=command,
                                     source=source,
                                     address=address,
                                     report_item=report_item)
                if source_host_str and source_host_str != command.host_name.full_name:
                    source_host = self.add_host_name(session=session,
                                                     command=command,
                                                     host_name=source_host_str,
                                                     source=source,
                                                     report_item=report_item)
                    if source_host and host:
                        self._domain_utils.add_host_host_name_mapping(
                            session=session,
                            host=host,
                            host_name=source_host,
                            source=source,
                            mapping_type=DnsResourceRecordType.a,
                            report_item=report_item)
                        session.flush()
                    else:
                        logger.debug(
                            "could not link host name '{}' with host '{}'".
                            format(source_host_str, address))
                if address and not host:
                    logger.debug(
                        "ignoring host due to invalid IPv4 address in line: {}"
                        .format(line))
                elif host:
                    self._domain_utils.add_host_host_name_mapping(
                        session=session,
                        host=host,
                        host_name=command.host_name,
                        source=source,
                        mapping_type=DnsResourceRecordType.a,
                        report_item=report_item)
                    session.flush()
            elif ipv6_match:
                source_host_str = ipv6_match.group("domain").strip()
                address = ipv6_match.group("address")
                # Add IPv4 address to database
                host = self.add_host(session=session,
                                     command=command,
                                     source=source,
                                     address=address,
                                     report_item=report_item)
                if source_host_str and source_host_str != command.host_name.full_name:
                    source_host = self.add_host_name(session=session,
                                                     command=command,
                                                     host_name=source_host_str,
                                                     source=source,
                                                     report_item=report_item)
                    if source_host and host:
                        self._domain_utils.add_host_host_name_mapping(
                            session=session,
                            host=host,
                            host_name=source_host,
                            source=source,
                            mapping_type=DnsResourceRecordType.aaaa,
                            report_item=report_item)
                        session.flush()
                    else:
                        logger.debug(
                            "could not link host name '{}' with host '{}'".
                            format(source_host_str, address))
                if address and not host:
                    logger.debug(
                        "ignoring host due to invalid IPv6 address in line: {}"
                        .format(line))
                elif host:
                    self._domain_utils.add_host_host_name_mapping(
                        session=session,
                        host=host,
                        host_name=command.host_name,
                        source=source,
                        mapping_type=DnsResourceRecordType.aaaa,
                        report_item=report_item)
                    session.flush()
            elif mx_host_match:
                mx_host_name = mx_host_match.group("domain")
                # Add host name to database
                host_name = self.add_host_name(session=session,
                                               command=command,
                                               source=source,
                                               host_name=mx_host_name,
                                               report_item=report_item)
                if not host_name:
                    logger.debug(
                        "ignoring host name due to invalid domain in line: {}".
                        format(line))
            elif cname_match:
                source_domain = cname_match.group("domain1").strip()
                target_domain = cname_match.group("domain2").strip()
                source_host_name = self.add_host_name(session=session,
                                                      command=command,
                                                      host_name=source_domain,
                                                      source=source,
                                                      report_item=report_item)
                target_host_name = self.add_host_name(session=session,
                                                      command=command,
                                                      host_name=target_domain,
                                                      source=source,
                                                      report_item=report_item)
                if not source_host_name:
                    logger.debug(
                        "ignoring host name due to invalid domain in line: {}".
                        format(source_domain))
                elif not target_host_name:
                    logger.debug(
                        "ignoring host name due to invalid domain in line: {}".
                        format(source_domain))
                else:
                    self.add_host_name_host_name_mapping(
                        session=session,
                        command=command,
                        source_host_name=source_host_name,
                        resolved_host_name=target_host_name,
                        source=source,
                        mapping_type=DnsResourceRecordType.cname,
                        report_item=report_item)