
Db 데이터베이스 평가 도구
Db 데이터베이스 평가 도구
DbDat은 데이터베이스 보안을 평가하기 위해 여러 점검을 수행합니다. 점검 범주는 구성, 권한, 사용자 및 정보입니다. 점검은 쿼리를 실행하거나 데이터베이스 구성 파일을 읽어 수행됩니다. 이 도구의 목표는 즉시 주의가 필요한 문제를 강조하고 적절성 검토가 필요한 구성 설정을 식별하는 것입니다. 이 도구는 애플리케이션의 SQL 인젝션 취약점을 식별하기 위한 것이 아닙니다. 이미 이에 적합한 훌륭한 도구들이 있습니다(예: https://github.com/sqlmapproject). 또한 이 도구는 대상 데이터베이스 버전에 영향을 미칠 수 있는 CVE를 판단하려 시도하지 않습니다(향후에는 가능할 수도 있지만). 대신, 이 도구는 취약한 구성이나 액세스 제어로 인해 성공적인 SQL 인젝션 공격의 잠재적 영향을 더 잘 이해하는 데 도움을 줍니다. 점검의 대부분은 CIS(https://cisecurity.org) 데이터베이스 보안 벤치마크를 기반으로 하므로 CIS에 감사드립니다! 벤치마크 문서는 다음에서 찾을 수 있습니다: https://benchmarks.cisecurity.org/downloads/browse/index.cfm?category=benchmarks.servers.database
대상 데이터베이스에 대한 벤치마크 문서를 다운로드할 것을 적극 권장합니다. 수행되는 점검에 대한 추가 정보가 포함되어 있기 때문입니다.
마지막으로, DbDat은 새로운 플러그인과 점검을 쉽게 생성할 수 있는 프레임워크로 설계되었습니다. 보안 커뮤니티 또는 데이터베이스 관리자 커뮤니티의 기여가 이 도구를 훌륭하게 만들 것입니다. 현재 점검 세트는 결코 완전하지 않으며 더 많은 작업이 필요합니다. 기여해 주세요!
새 데이터베이스 점검 개발
풀 리퀘스트를 환영합니다! 점검은 plugins 폴더에 데이터베이스 유형별(예: MySQL, Oracle, MS SQL 등)로 구성됩니다. 각 점검은 파일 이름이 check_로 시작하는 단일 Python 파일입니다. 각 파일에는 do_check 메서드를 가진 클래스가 포함되어 있습니다. 이 메서드는 점검의 주요 로직입니다. 빠르게 시작하려면 기존 점검 파일을 복사하여 수정하세요. 그러나 자세한 내용은 아래 플러그인 개발 섹션을 참조하십시오.
etc/dbdat.conf 파일에 연결 프로필 항목을 추가하십시오.python dbdat.py -p <프로파일 이름>cd로 reports 디렉토리로 이동한 후 python -m SimpleHTTPServer 9000(또는 원하는 포트 번호 선택)을 실행하십시오. 그런 다음 브라우저를 열고 http://localhost:9000으로 이동하십시오.추가 명령줄 인수 목록을 보려면 python dbdat.py -h를 실행하십시오.
보고서는 결과를 RED, YELLOW, ORANGE, GRAY, GREEN 레벨로 구성합니다.
현재까지 DbDat은 Debian Linux, CentOS Linux 및 Windows 7에서 Python 2.7로 테스트되었습니다.
실행: pip install MySQL-python
또는 Debian에서 실행: apt-get install python-mysqldb
실행: pip install psycopg2
실행: pip install cx_Oracle
참고: 작동하려면 Oracle 클라이언트 라이브러리를 설치해야 합니다.
실행: pip install pymssql
실행: pip install ibm_db 또는 easy_install ibm_db
참고: DbDat을 실행하는 사용자가 DB2 CLP 명령(예: db2 및 db2level)을 실행할 수 있는 액세스 권한이 있는지 확인해야 합니다.
실행: pip install pymongo
MongoDB YAML 구성 파일을 지원하려면 실행: pip install pyyaml
실행: pip install couchdb
plugins 폴더 내에는 각 데이터베이스 유형별 폴더가 있으며, 각 폴더에는 점검 파일이 포함되어 있습니다. 이는 매우 간단한 구조이지만, plugins 폴더를 탐색하여 익숙해질 수 있습니다 https://github.com/foospidy/DbDat/tree/master/plugins
데이터베이스 폴더에는 다음이 포함됩니다.
__init.py - init 파일에는 각 점검 파일에 대한 import 문이 있습니다.check_ 파일 - 실제 데이터베이스 점검을 수행하는 파일입니다. 파일과 파일 내에 정의된 클래스의 이름은 같아야 합니다.helper.py - 공통 함수를 포함하는 파일입니다. 점검 파일은 helper.py를 import하여 공통 함수를 활용할 수 있습니다.새 점검 파일을 추가할 때 해당 플러그인 디렉토리의 __init__.py 파일에 import 문을 추가해야 합니다. 점검의 코드 패턴은 상당히 일관됩니다. 기존 파일을 검토하여 구조를 파악하십시오. sql 유형과 configuration_file 유형의 차이점에 유의하십시오.
정의할 수 있는 점검의 "유형"은 다양합니다. 점검 유형은 TYPE 변수에 의해 결정되며 sql, configuration_file, nosql 또는 clp가 될 수 있습니다. 아래는 다양한 점검 유형 시나리오에 대한 예제 구현입니다.
sql 점검의 경우 do_check 메서드 시그니처는 다음과 같아야 합니다: do_check(self, *results)
https://github.com/foospidy/DbDat/blob/master/plugins/mysql/check_user_empty_password.py
이 예제에서는 호출하는 부모 클래스의 appuser 변수가 필요합니다. appuser를 SQL 문에 동적으로 추가해야 하므로 __init__ 메서드에서 self.SQL 변수가 설정됩니다. 또한 이 do_check 메서드가 sql을 실행해야 하므로 DB 커서(연결)도 필요하며, 이는 __init__ 메서드에서 self.dbcurs = parent.dbcurs로 설정됩니다.
https://github.com/foospidy/DbDat/blob/master/plugins/mysql/check_privilege_user_grants.py
configuration_file 점검의 경우 do_check 메서드 시그니처는 다음과 같아야 합니다: do_check(self, configuration_file)
https://github.com/foospidy/DbDat/blob/master/plugins/mysql/check_configuration_general_log.py
이 예제에서 PostgreSQL 구성 파일에는 섹션(예: [section_name])이 없으므로 PostgreSQL 폴더의 helper 모듈에 이를 처리하는 함수가 포함되어 있습니다. helper.py에 정의된 get_config_value 함수를 참조하십시오.
다른 구성 파일 형식의 경우 자체 구문 분석 로직을 정의해야 합니다.
nosql 점검의 경우 do_check 메서드 시그니처는 다음과 같아야 합니다: do_check(self)
NoSQL 쿼리는 do_check 메서드 내에서 실행되어야 하므로 클래스 __init__ 메서드는 self.db = parent.db를 구현해야 합니다. 그런 다음 self.db 변수를 사용하여 do_check 메서드 내에서 NoSQL 쿼리를 실행할 수 있습니다.
https://github.com/foospidy/DbDat/blob/master/plugins/mongodb/check_information_banner.py
clp 점검의 경우 do_check 메서드 시그니처는 다음과 같아야 합니다: do_check(self, *results). clp 점검은 IBM DB2 데이터베이스에 필요하므로 db2 명령줄 프로세서를 실행하여 데이터베이스에 대한 정보를 얻을 수 있습니다. 그러나 이 점검 유형은 모든 임의 명령줄 명령을 실행하는 데 사용될 수 있습니다. 모든 명령줄 출력은 do_check 메서드에 전달된 results 변수에서 구문 분석할 수 있습니다. 또한 CMD 클래스 메서드를 정의해야 합니다. 이 변수는 명령 및 관련 인수의 목록입니다.
https://github.com/foospidy/DbDat/blob/master/plugins/db2/check_privilege_group_entitlements.py
모든 점검은 CATEGORY 변수를 사용하여 범주를 지정해야 합니다. 범주는 점검을 구성하는 방법입니다. 가능한 범주는 Information, Configuration, Privilege 및 User입니다. 점검 컨텍스트에 가장 관련성이 높은 범주를 지정하십시오.
다음은 점검 파일이 따라야 할 패턴을 보여주는 대략적인 예입니다.
# (OPTIONAL): Add import statements, include any necessary modules to support this check
import helper
# (REQUIRED): Define class, the class must have the same name as its file name.
class check_configuration_evaluate_something():
# (REQUIRED): Add documentation, provide information on this check as this will be displayed in the report.
"""
check_configuration_evaluate_something:
Some description goes here!
"""
# (OPTIONAL): Add references, this is only comments in code, adding references is helpful to others.
# 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
# (REQUIRED): Add the standard set of variables
TITLE = 'Client Password'
CATEGORY = 'Configuration'
TYPE = 'configuration_file'
SQL = None
verbose = False
skip = False
result = {}
# (OPTIONAL): Add any custom variables specific to this check
custom_var = 'custom_val'
# (REQUIRED): Define the do_check method, this is the actual check logic and is called by the main program.
def do_check(self, *results):
# (REQUIRED): check logic goes here, besure to set values for self.result['level'] and self.result['output']
# Results from the SQL variable can be processed using:
for rows in results:
for row in rows:
# (REQUIRED):
# Always set the self.result['level'] and self.result['output'] variables before returning.
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])
# Always return self.result
return self.result
# (REQUIRED): at minimum the __init__ method should print the check being performed.
def __init__(self, parent):
print('Performing check: ' + self.TITLE)
# get values from the parent calling class
self.verbose = parent.verbose