예제 #1
0
    def __replace_tokens_from_matchobj(self, string, match):
        """
        Replace tokens $1, $2 ... with the corresponding value of matching group.
        E.g. : $1 <-> (?P<m1>...)
        This method is used when the matching method "finditer" is used (default)

        :param str string: String that may contain some tokens ($1, $2 ...)
        :param _sre.SRE_Match match: Match object resulting from re.search()
        :return: String with tokens replaced with correct values (or None in case of
            error)
        :rtype: str|None
        """
        output = string
        for i in range(1, 10):
            token = '${}'.format(i)
            if token in string:
                group = 'm{}'.format(i)

                if group in match.groupdict():
                    # Replace token by value of matching group
                    # If value is None, replace by empty string
                    output = output.replace(token, match.group(group) or '')

                else:
                    logger.smarterror('Invalid matchstring for service={service}, ' \
                        'tool={tool}'.format(
                            service=self.service.name,
                            tool=self.tool_name))
                    return None

            # else:
            #     # Token must be sequentials ($1, $2...)
            #     break

        return output
예제 #2
0
    def __replace_tokens_from_captdict(self, string, captdict, index):
        """
        Replace tokens $1, $2 ... with the corresponding value of matching group.
        E.g. : $1 <-> (?P<m1>...)
        This method is used when the matching method "search" is used

        :param str string: String that may contain some tokens ($1, $2 ...)
        :param dict captdict: Captures dict resulting from regex.search().capturesdict()
        :return: String with tokens replaced with correct values (or None in case of
            error)
        :rtype: str|None
        """
        output = string
        for i in range(1, 10):
            token = '${}'.format(i)
            if token in string:
                group = 'm{}'.format(i)

                if group in captdict and index < len(captdict[group]):
                    output = output.replace(token, captdict[group][index])
                else:
                    logger.smarterror('Invalid matchstring for service={service}, ' \
                        'tool={tool}'.format(
                            service=self.service.name,
                            tool=self.tool_name))
                    return None

            # else:
            #     # Token must be sequentials ($1, $2...)
            #     break

        return output
예제 #3
0
    def __detect_specific_options(self):
        """Detect specific option update from command output"""
        if self.service.name in options_match.keys():

            if self.tool_name in options_match[self.service.name].keys():
                p = options_match[self.service.name][self.tool_name]

                for pattern in p.keys():
                    logger.debug('Search for option pattern: {pattern}'.format(
                        pattern=pattern))

                    try:
                        m = re.search(pattern, 
                                      self.cmd_output, 
                                      re.IGNORECASE|re.MULTILINE)
                    except Exception as e:
                        logger.warning('Error with matchstring [{pattern}], you should '\
                            'review it. Exception: {exception}'.format(
                                pattern=pattern, exception=e))
                        break


                    # If pattern matches cmd output, update specific option
                    if m:
                        logger.debug('Option pattern matches')
                        if 'name' in p[pattern]:
                            name = self.__replace_tokens_from_matchobj(
                                p[pattern]['name'], m)
                            if name is None:
                                continue
                        else:
                            logger.smarterror('Invalid matchstring for ' \
                                'service={service}, tool={tool}: Missing ' \
                                '"name" key'.format(
                                    service=self.service.name,
                                    tool=self.tool_name))
                            continue

                        if 'value' in p[pattern]:
                            value = self.__replace_tokens_from_matchobj(
                                p[pattern]['value'], m)
                            if value is None:
                                continue
                        else:
                            logger.smarterror('Invalid matchstring for ' \
                                'service={service}, tool={tool}: Missing ' \
                                '"value" key'.format(
                                    service=self.service.name,
                                    tool=self.tool_name))
                            continue 

                        # Add specific option to context
                        self.cu.add_option(name, value)                           
예제 #4
0
    def __detect_credentials(self):
        """
        Detect usernames/credentials from command output
        Important: A command output might contain several usernames/passwords with the
        same pattern.

        Example method "search":

        >>> text = "
        ... Prefix
        ... Found credentials: 
        ...     admin:pass
        ...     toto:pwd
        ... lorem ipsum
        ... lorem ipsum"
        >>> import regex
        >>> m = regex.search('Pre[\s\S]*?Found credentials:(\s*(?P<m1>\S+):(?P<m2>\S+)\s*\n)+', text)
        >>> matchs = m.capturesdict()
        >>> matchs
        {'m1': ['admin', 'toto'], 'm2': ['pass', 'pwd']}

        >>> m = regex.search('(\[v\] Trying Credentials:\s*(?P<user>\S+)\s*(?P<password>\S+)\s*\n)+', text)
        >>> m.capturesdict()
        {'user': ['Miniwick', 'Miniwick', 'Miniwick', 'Miniwick', 'Miniwick'], 'password': ['password', 'admin', '123456', 'Password1', 'Miniwick']}
        >>> m = regex.search('WordPress[\s\S]*?(\[v\] Trying Credentials:\s*(?P<user>\S+)\s*(?P<password>\S+)\s*\n)+', text)
        >>> m.capturesdict()
        {'user': ['Miniwick', 'Miniwick', 'Miniwick', 'Miniwick', 'Miniwick'], 'password': ['password', 'admin', '123456', 'Password1', 'Miniwick']}

        """
        if self.service.name in creds_match.keys():

            if self.tool_name in creds_match[self.service.name].keys():
                p = creds_match[self.service.name][self.tool_name]

                for pattern in p.keys():

                    # Important: Multiple search/match
                    #m = re.search(pattern, self.cmd_output, re.IGNORECASE|re.DOTALL)
                    logger.debug('Search for creds pattern: {pattern}'.format(
                        pattern=pattern))

                    if 'user' not in p[pattern]:
                        logger.smarterror('Invalid matchstring for service={service}, ' \
                            ' tool={tool}: Missing "user" key'.format(
                                service=self.service.name,
                                tool=self.tool_name))
                        continue

                    # Matching method
                    if 'meth' in p[pattern] \
                            and p[pattern]['meth'] in ('finditer', 'search'):
                        method = p[pattern]['meth']
                    else:
                        method = 'finditer'

                    # Perform regexp matching
                    try:
                        if method == 'finditer':
                            m = re.finditer(pattern, self.cmd_output,
                                            re.IGNORECASE)
                        else:
                            m = regex.search(pattern, self.cmd_output,
                                             regex.IGNORECASE)
                    except Exception as e:
                        logger.warning('Error with matchstring [{pattern}], you should ' \
                            'review it. Exception: {exception}'.format(
                                pattern=pattern, exception=e))
                        break

                    if not m:
                        continue

                    pattern_match = False

                    # Method "finditer"
                    if method == 'finditer':
                        for match in m:
                            pattern_match = True
                            cred = dict()

                            # Replace tokens in user, pass, type
                            cred['user'] = self.__replace_tokens_from_matchobj(
                                p[pattern]['user'], match)
                            if cred['user'] is None:
                                continue

                            if 'pass' in p[pattern]:
                                cred[
                                    'pass'] = self.__replace_tokens_from_matchobj(
                                        p[pattern]['pass'], match)
                                if cred['pass'] is None:
                                    continue

                            if 'type' in p[pattern]:
                                cred[
                                    'type'] = self.__replace_tokens_from_matchobj(
                                        p[pattern]['type'], match)
                                if cred['type'] is None:
                                    continue

                            # Add username/cred to context
                            if 'pass' in cred:
                                self.cu.add_credentials(
                                    username=cred.get('user'),
                                    password=cred.get('pass'),
                                    auth_type=cred.get('type'))
                            elif 'user' in cred:
                                self.cu.add_username(
                                    username=cred.get('user'),
                                    auth_type=cred.get('type'))

                    # Method "search"
                    else:
                        pattern_match = True
                        matchs = m.capturesdict()
                        if 'm1' not in matchs:
                            logger.smarterror('Invalid matchstring for ' \
                                'service={service}, tool={tool}: Missing match ' \
                                'group'.format(
                                    service=self.service.name,
                                    tool=self.tool_name))
                            return

                        nb_groups = len(matchs['m1'])

                        for i in range(nb_groups):
                            cred = dict()

                            # Replace tokens in user, pass, type
                            cred['user'] = self.__replace_tokens_from_captdict(
                                p[pattern]['user'], matchs, i)
                            if cred['user'] is None:
                                continue

                            if 'pass' in p[pattern]:
                                cred[
                                    'pass'] = self.__replace_tokens_from_captdict(
                                        p[pattern]['pass'], matchs, i)
                                if cred['pass'] is None:
                                    continue

                            if 'type' in p[pattern]:
                                cred[
                                    'type'] = self.__replace_tokens_from_captdict(
                                        p[pattern]['type'], matchs, i)
                                if cred['type'] is None:
                                    continue

                            # Add username/cred to context
                            if 'pass' in cred:
                                self.cu.add_credentials(
                                    username=cred.get('user'),
                                    password=cred.get('pass'),
                                    auth_type=cred.get('type'))
                            elif 'user' in cred:
                                self.cu.add_username(
                                    username=cred.get('user'),
                                    auth_type=cred.get('type'))

                    # If a pattern has matched, skip the next patterns
                    if pattern_match:
                        logger.debug('Creds pattern matches (user only)')
                        return