Source code for credsweeper.filters.value_pattern_check

import re

from credsweeper.config import Config
from credsweeper.credentials import LineData
from credsweeper.file_handler.analysis_target import AnalysisTarget
from credsweeper.filters import Filter


[docs]class ValuePatternCheck(Filter): """Check if candidate value contain specific pattern. Similar to linguistic sequences of characters, random strings shouldn't contain math sequences of characters. Based on "How Bad Can It Git? Characterizing Secret Leakage in Public GitHub Repositories", details: https://www.ndss-symposium.org/ndss-paper/how-bad-can-it-git-characterizing-secret-leakage-in-public-github-repositories/ PatternCheck checks the occurrence in "line_data.value" of three types of sequence: - N or more identical characters in sequence, example: "AAAA", "1111" ... - N or more increasing characters sequentially, example: "abcd", "1234" ... - N or more decreasing characters sequentially, example: "dcba", "4321" ... Default pattern LEN is 4 """ def __init__(self, config: Config): """Create ValuePatternCheck with a specific pattern_len to check. Args: config: pattern len to use during check. DEFAULT_PATTERN_LEN by default """ if 'ValuePemPatternCheck' == self.__class__.__name__: self.pattern_len = config.pem_pattern_len else: self.pattern_len = config.pattern_len # use non whitespace symbol pattern self.pattern = re.compile(fr"(\S)\1{{{str(self.pattern_len - 1)},}}")
[docs] def equal_pattern_check(self, line_data_value: str) -> bool: """Check if candidate value contain 4 and more same chars or numbers sequences. Args: line_data_value: string variable, credential candidate value Return: True if contain and False if not """ if self.pattern.findall(line_data_value): return True return False
[docs] def ascending_pattern_check(self, line_data_value: str) -> bool: """Check if candidate value contain 4 and more ascending chars or numbers sequences. Arg: line_data_value: credential candidate value Return: True if contain and False if not """ count = 1 for key in range(len(line_data_value) - 1): if ord(line_data_value[key + 1]) - ord(line_data_value[key]) == 1: count += 1 else: count = 1 continue if count == self.pattern_len: return True return False
[docs] def descending_pattern_check(self, line_data_value: str) -> bool: """Check if candidate value contain 4 and more descending chars or numbers sequences. Arg: line_data_value: string variable, credential candidate value Return: boolean variable. True if contain and False if not """ count = 1 for key in range(len(line_data_value) - 1): if ord(line_data_value[key]) - ord(line_data_value[key + 1]) == 1: count += 1 else: count = 1 continue if count == self.pattern_len: return True return False
[docs] def run(self, line_data: LineData, target: AnalysisTarget) -> bool: """Run filter checks on received credential candidate data 'line_data'. Arg: line_data: LineData object, credential candidate data target: multiline target from which line data was obtained Return: boolean variable. True, if need to filter candidate and False if left """ if len(line_data.value) < self.pattern_len: return True if self.equal_pattern_check(line_data.value): return True if self.ascending_pattern_check(line_data.value): return True if self.descending_pattern_check(line_data.value): return True return False