
Db Ferramenta de Avaliação de Banco de Dados
Ferramenta de Avaliação de Banco de Dados Db
O DbDat realiza inúmeras verificações em um banco de dados para avaliar a segurança. As categorias de verificações realizadas são configuração, privilégios, usuários e informações. As verificações são executadas por meio de consultas ou leitura de arquivos de configuração do banco de dados. O objetivo desta ferramenta é destacar problemas que precisam de atenção imediata e identificar configurações que devem ser revisadas quanto à adequação. Esta ferramenta não serve para identificar vulnerabilidades de SQL Injection em uma aplicação; já existem boas ferramentas para isso (por exemplo, https://github.com/sqlmapproject). Além disso, esta ferramenta não tenta determinar quais CVEs podem afetar a versão do banco de dados alvo (mas poderá fazê-lo no futuro – talvez). Em vez disso, esta ferramenta pode ajudá-lo a entender melhor o impacto potencial de um ataque bem-sucedido de SQL Injection devido a configuração fraca ou controles de acesso inadequados. A maioria das verificações são baseadas nos CIS (https://cisecurity.org) Security Benchmarks para bancos de dados, então agradecimentos ao CIS! Os documentos de benchmark podem ser encontrados aqui: https://benchmarks.cisecurity.org/downloads/browse/index.cfm?category=benchmarks.servers.database
Recomendo fortemente baixar o documento de benchmark para o seu banco de dados alvo, pois ele contém informações adicionais sobre as verificações realizadas.
Por fim, o DbDat foi concebido como um framework para facilitar a criação de novos plugins e verificações. Contribuições da comunidade de segurança, ou mesmo de administradores de banco de dados, são o que tornarão esta ferramenta excelente. O conjunto atual de verificações está longe de estar completo – certamente há mais a ser feito. Contribua!
Desenvolvendo Novas Verificações de Banco de Dados
Pull requests são muito bem-vindos! As verificações são organizadas por tipo de banco de dados (ex.: MySQL, Oracle, MS SQL, etc.) na pasta plugins. Cada verificação é um único arquivo Python cujo nome deve começar com check_. Cada arquivo contém uma classe com um método do_check. Este método é a lógica principal da verificação. A maneira rápida de começar é copiar um arquivo de verificação existente e modificá-lo. No entanto, consulte a seção "Desenvolvendo Plugins" abaixo para mais detalhes.
etc/dbdat.conf para cada banco de dados que deseja avaliar.python dbdat.py -p <nome_do_perfil>reports e execute python -m SimpleHTTPServer 9000 (ou escolha um número de porta de sua preferência). Em seguida, abra seu navegador e navegue até http://localhost:9000.Para ver uma lista de argumentos adicionais de linha de comando, execute python dbdat.py -h
O relatório organiza os resultados por níveis: VERMELHO, AMARELO, LARANJA, CINZA e VERDE.
Até o momento, o DbDat foi testado em Debian Linux, CentOS Linux e Windows 7 com Python 2.7.
Execute: pip install MySQL-python
Ou no Debian, execute: apt-get install python-mysqldb
Execute: pip install psycopg2
Execute: pip install cx_Oracle
Nota: você precisará instalar as bibliotecas cliente Oracle para que isso funcione.
Execute: pip install pymssql
Execute: pip install ibm_db ou easy_install ibm_db
Nota: você precisará garantir que o usuário que executa o DbDat tenha acesso para executar comandos CLP do DB2 (ex.: db2 e db2level).
Execute: pip install pymongo
Para suportar arquivos de configuração YAML do MongoDB, execute: pip install pyyaml
Execute: pip install couchdb
Dentro da pasta plugins há uma pasta para cada tipo de banco de dados, e cada pasta contém arquivos de verificação. Esta é uma estrutura muito simples, mas você também pode navegar pela pasta plugins para se familiarizar: https://github.com/foospidy/DbDat/tree/master/plugins
As pastas de banco de dados conterão:
__init.py – O arquivo de inicialização contém uma declaração de importação para cada arquivo de verificação.check_ – Estes são os arquivos que realmente executam as verificações no banco de dados. O arquivo e a classe definida dentro dele devem ter o mesmo nome.helper.py – Um arquivo contendo funções comuns. Os arquivos de verificação podem importar helper.py para aproveitar essas funções.Ao adicionar um novo arquivo de verificação, uma declaração de importação precisa ser adicionada ao arquivo __init__.py do diretório de plugin correspondente. O padrão de código para as verificações é bastante consistente. Revise os arquivos existentes para entender como eles são estruturados. Observe a diferença entre verificações do tipo sql e configuration_file.
Existem diferentes "tipos" de verificações que podem ser definidos. O tipo de verificação é determinado pela variável TYPE e pode ser sql, configuration_file, nosql ou clp. Abaixo estão exemplos de implementação para os diferentes cenários de tipos de verificação.
sqlPara verificações do tipo sql, a assinatura do método do_check deve ser: do_check(self, *results)
sql típicahttps://github.com/foospidy/DbDat/blob/master/plugins/mysql/check_user_empty_password.py
sql onde a variável SQL é definida na inicializaçãoNeste exemplo, precisamos da variável appuser da classe pai que chama. O appuser precisa ser adicionado dinamicamente à instrução SQL, então a variável self.SQL está sendo definida no método __init__. Além disso, como este método do_check precisa executar o SQL, também precisamos do cursor DB (conexão), que é definido no método __init__ com self.dbcurs = parent.dbcurs.
https://github.com/foospidy/DbDat/blob/master/plugins/mysql/check_privilege_user_grants.py
configuration_filePara verificações do tipo configuration_file, a assinatura do método do_check deve ser: do_check(self, configuration_file)
https://github.com/foospidy/DbDat/blob/master/plugins/mysql/check_configuration_general_log.py
Neste exemplo, o arquivo de configuração do PostgreSQL não possui seções (ex.: [nome_da_seção]), então o módulo auxiliar na pasta PostgreSQL contém uma função que lida com isso. Veja a função get_config_value definida em helper.py.
Para outros formatos de arquivo de configuração, você precisará definir sua própria lógica de análise.
nosqlPara verificações do tipo nosql, a assinatura do método do_check deve ser: do_check(self)
Consultas NoSQL precisam ser executadas dentro do método do_check, então o método __init__ da classe deve implementar self.db = parent.db. A variável self.db pode então ser usada para executar consultas NoSQL dentro do método do_check.
https://github.com/foospidy/DbDat/blob/master/plugins/mongodb/check_information_banner.py
clpPara verificações do tipo clp, a assinatura do método do_check deve ser: do_check(self, *results). Verificações clp são necessárias para bancos de dados IBM DB2, para que o processador de linha de comando db2 possa ser executado para obter informações sobre o banco de dados. No entanto, este tipo de verificação pode ser usado para executar qualquer comando arbitrário de linha de comando. Toda a saída da linha de comando pode ser analisada a partir da variável results passada para o método do_check. Além disso, você precisará definir o método de classe CMD. Esta variável é uma lista do comando e seus argumentos relacionados.
https://github.com/foospidy/DbDat/blob/master/plugins/db2/check_privilege_group_entitlements.py
Toda verificação deve ter uma categoria especificada usando a variável CATEGORY. A categoria é uma forma de organizar as verificações. As categorias possíveis são: Information, Configuration, Privilege e User. Especifique a categoria mais relevante para o contexto da verificação.
Este é um exemplo aproximado que demonstra o padrão que um arquivo de verificação deve seguir:
# (OPCIONAL): Adicione declarações de importação, incluindo quaisquer módulos necessários para suportar esta verificação
import helper
# (OBRIGATÓRIO): Defina a classe. A classe deve ter o mesmo nome que o nome do arquivo.
class check_configuration_evaluate_something():
# (OBRIGATÓRIO): Adicione documentação. Forneça informações sobre esta verificação, pois serão exibidas no relatório.
"""
check_configuration_evaluate_something:
Alguma descrição vai aqui!
"""
# (OPCIONAL): Adicione referências. Isto é apenas comentário no código. Adicionar referências é útil para outros.
# References:
# https://www.percona.com/blog/2012/12/28/auditing-login-attempts-in-mysql/
# https://dev.mysql.com/doc/refman/5.7/en/password-security-user.html
# (OBRIGATÓRIO): Adicione o conjunto padrão de variáveis
TITLE = 'Client Password'
CATEGORY = 'Configuration'
TYPE = 'configuration_file'
SQL = None
verbose = False
skip = False
result = {}
# (OPCIONAL): Adicione quaisquer variáveis personalizadas específicas para esta verificação
custom_var = 'custom_val'
# (OBRIGATÓRIO): Defina o método do_check. Esta é a lógica real da verificação e é chamada pelo programa principal.
def do_check(self, *results):
# (OBRIGATÓRIO): A lógica da verificação vai aqui. Certifique-se de definir os valores para self.result['level'] e self.result['output']
# Resultados da variável SQL podem ser processados usando:
for rows in results:
for row in rows:
# (OBRIGATÓRIO):
# Sempre defina as variáveis self.result['level'] e self.result['output'] antes de retornar.
if row[0] == 'bad':
self.result['level'] = 'RED'
self.result['output'] = 'Result is %s' % (row[0])
elif row[0] == 'needs review':
self.result['level'] = 'YELLOW'
self.result['output'] = 'Result is %s' % (row[0])
else:
self.result['level'] = 'GREEN'
self.result['output'] = 'Result is %s' % (row[0])
# Sempre retorne self.result
return self.result
# (OBRIGATÓRIO): No mínimo, o método __init__ deve exibir a verificação que está sendo executada.
def __init__(self, parent):
print('Performing check: ' + self.TITLE)
# Obter valores da classe pai que chama
self.verbose = parent.verbose