AndersonArruda

Artigos de tecnologia ao alcance de um clique!


Analisando log do PostgreSQL para evitar Brute Force - Parte 2
brute force log reader postgresql python python postgresql uml coding

Analisando log do PostgreSQL para evitar Brute Force - Parte 2

31/01/2023 21:29

Sejam muito bem vindos a parte dois dessa nossa saga! YEEEEE!!!

Caso não tenha visto a parte 1 desse artigo corra lá antes de ler esse, vai ser super rapidinho e importante. Parte 1.


Logo perceberão que no meio da construção da fase 1 do projeto já mudei algumas coisinhas, porém muitas coisas mais irão ser mudadas, inclusive a ordem de invocação das classes e a forma de armazenar o retorno das classes, será simplificado, dinâmico e direto ao assunto, como sabemos se uma classe faz coisas demais... talvez devesse ser várias classes diferentes.


Novamente vou deixar o link do projeto no Github, se puderem me seguir lá ficarei grato.

Link do Github


Sem mais delongas comecei criando a classe que é responsável por abrir e ler linha a linha do arquivo de log.


reader.py

from os import path
from src.filter import filter

class reader:
    def __init__(self, filepath):
        if not(path.exists(filepath)):
            raise Exception('File does not exists.')

        self._file = open(filepath, 'r')
        self._filter = []

    def __any_filter_match(self, line):
        for f in self._filter:
            if f.exec(line):
                return True

        return False

    def __readingLines(self, filter=None, use_filters=False):
        lines = self._file.readlines()
        list = []
        for line in lines:
            if filter is not None and filter.exec(line):
                list.append(line)

            if use_filters and self.__any_filter_match(line):
                list.append(line)

            if filter is None and use_filters is False:
                list.append(line)

        return list

    def toList(self):
        return self.__readingLines()

    def isFilter(self, input_filter):
        if not (isinstance(input_filter, filter)):
            raise Exception('Need to be a filter class to be setted over here.')

    def set_filter(self, filter):
        self.isFilter(filter)
        self._filter.append(filter)
        return self

    def getByFilter(self, filter):
        self.isFilter(filter)
        return self.__readingLines(filter)

    def filter_all(self):
        return self.__readingLines(use_filters=True)

Como podem reparar essa classe tem muitas funções, e a coletânea de dados a serem resgatados é inconclusiva tornando confuso, o que pretendo fazer é inverter e usar o modelo de filtro pra unir as duas pontas.

Mas basicamente o que essa classe faz é abrir o arquivo de log, converter linha a linha pra uma lista, verificar se uma classe é um filtro, setar um filtro, pegar resultados através de um filtro específico, filtrar através de todas as classes de filtro definidas.

Um pouco demais pra agora imagino, mas na próxima versão todas as funções estarão devidamente comentadas.

Seguindo a linha de raciocínio teve mudanças em funções acessórias como isFilter, __readingLines, __any_filter_match e etc...

Na próxima versão não terá mais set_filter, getByFilter e coisas relacionadas pois haverá uma inversão tornando o objetivo muito mais intuitivo.


Logo em seguida eu criei a classe de filtro, tcharannnnnn.....


filter.py

import re

class filter:
    def __init__(self, regex):
        try:
            self._regex = re.compile(regex)
        except re.error:
            raise Exception('Input regex is not a valid one.')

    def exec(self, line):
        return self._regex.search(line)

Essa classe em si não foi um grade desafio criá-la a nível de código, mas a nível de raciocínio deu bastante trabalho principalmente em questão de como fundir com a próxima classe.

Essa classe basicamente recebe uma expressão regular que filtra a linha do log retornando true ou false caso a linha corresponda.

Graças a dificuldade no conceito surgiu a idéia de inverter o modelo e começar a próxima versão pela classe que apresentarei abaixo muito mais robusta.


pgsqlAuthFailed.py

from src.filter import filter

class pgsqlAuthFailed:
    @staticmethod
    def getFilter():
        regex = r"invalid length of startup packet|password authentication failed|password does not match|no postgresql user name specified in startup packet"
        return filter(regex)

Nessa versão essa classe é responsável por ter somente a expressão regular que dirá se a linha é a que o filtro busca ou não, na próxima versão tudo começará através dessa classe,

inclusive terá a possibilidade de quebrar parte dos dados relevantes, claro que isso deve ser construído modelo a modelo.


Esse é a continuação porém teremos mais continuações desse assunto, vim aqui mais mostrar que teve evoluções de conceito e de código.

O código é muito dinâmico e evoluí muito rápido, o conceito é extremamente importante para definir uma linha, testes são importantes para verificar se a linha definida está sendo traçada, e devemos estar sempre vigilantes pra novas idéias serem pautadas em próximas versões, se não acaba que a story nunca termina.


Eu sou Anderson Arruda, agradeço a atenção de todos em mais esse artigo, deixem nos comentários idéias de artigos e assuntos que eu deveria abordar.

Até a próxima e fui!

Espaço para publicidade
0 Comentário(s)
Seja o primeiro a comentar o nosso artigo!
Todos os direitos reservados. © 2021-2031
SBBlog Powered By Powered By Sysborg | Powered By Anderson Arruda