데이터베이스 보안 체크리스트
데이터베이스의 보안 설정 및 운영 현황을 점검하세요. · 2025.02 기준
MySQL의 root, PostgreSQL의 postgres, Oracle의 SYS/SYSTEM 등 DBMS 설치 시 생성되는 기본 관리자 계정의 이름과 비밀번호를 반드시 변경해야 합니다. 기본 계정은 공격자에게 가장 먼저 시도되는 진입 경로입니다.
각 데이터베이스 사용자에게 업무 수행에 필요한 최소한의 권한만 부여해야 합니다. SELECT만 필요한 사용자에게 DELETE, DROP 등의 권한을 부여하지 않도록 하며, 스키마 변경 권한은 DBA에게만 제한합니다.
개별 사용자에게 직접 권한을 부여하는 대신 역할(Role)을 정의하고, 사용자에게 역할을 할당하여 권한을 관리해야 합니다. 이를 통해 권한 관리의 일관성을 확보하고 오류를 줄일 수 있습니다.
DB 계정에 대해 최소 길이 12자 이상, 대소문자/숫자/특수문자 조합, 비밀번호 이력 관리, 주기적 변경 정책을 적용해야 합니다. DBMS 자체의 비밀번호 검증 플러그인을 활성화합니다.
일정 시간 이상 활동이 없는 DB 연결은 자동으로 종료되도록 타임아웃을 설정해야 합니다. 방치된 세션은 세션 하이재킹의 대상이 되거나 리소스를 불필요하게 점유할 수 있습니다.
일정 횟수 이상 인증에 실패한 계정은 자동으로 잠금 처리하여 무차별 대입 공격(Brute Force)을 방지해야 합니다. 잠금 해제는 관리자 승인 또는 일정 시간 경과 후 자동 해제되도록 설정합니다.
DBMS에서 PUBLIC 역할에 기본적으로 부여된 권한을 검토하고 불필요한 권한을 회수해야 합니다. PUBLIC에 부여된 권한은 모든 사용자에게 상속되므로 과도한 권한이 노출될 수 있습니다.
여러 애플리케이션이 동일한 DB 계정을 공유하지 않도록 애플리케이션별 전용 계정을 생성해야 합니다. 이를 통해 문제 발생 시 추적이 용이하고, 한 애플리케이션의 침해가 다른 애플리케이션에 영향을 주지 않습니다.
클라이언트와 DB 서버 간의 통신을 TLS 1.2 이상으로 암호화하여 네트워크 스니핑을 통한 데이터 유출을 방지해야 합니다. 평문 통신은 비밀번호와 쿼리 데이터가 그대로 노출됩니다.
데이터 파일, 로그 파일, 백업 파일에 대해 투명 데이터 암호화(Transparent Data Encryption)를 적용하여 물리적 디스크 탈취 시에도 데이터를 보호해야 합니다.
주민등록번호, 카드번호, 비밀번호 등 법적 보호가 필요한 개인정보 필드는 컬럼 단위로 AES-256 이상의 알고리즘을 사용하여 개별 암호화해야 합니다.
데이터 암호화에 사용되는 키를 DB 서버와 분리된 키 관리 시스템(KMS)에서 관리해야 합니다. 암호화 키를 소스 코드나 설정 파일에 하드코딩하면 키 유출 시 모든 암호화 데이터가 위험에 노출됩니다.
암호화 키는 정기적으로(최소 연 1회) 순환하여 키 유출 피해를 최소화해야 합니다. 키 순환 시 기존 데이터의 재암호화 절차와 이전 키 보관 정책을 수립해야 합니다.
데이터베이스 백업 파일은 반드시 암호화하여 저장해야 합니다. 비암호화 백업 파일이 유출될 경우 전체 데이터가 노출되므로, 백업 도구의 암호화 옵션을 활성화합니다.
사용자 비밀번호를 DB에 저장할 때 평문이나 단순 해시(MD5, SHA-1) 대신 bcrypt, argon2 등 솔트가 포함된 적응형 해시 알고리즘을 사용해야 합니다.
DBMS의 감사(Audit) 기능을 활성화하여 모든 로그인 시도, DDL 명령, 권한 변경 등 주요 이벤트를 기록해야 합니다. 보안 사고 발생 시 원인 분석과 책임 추적의 기반이 됩니다.
개인정보, 금융 정보 등 민감 데이터가 저장된 테이블에 대한 SELECT, UPDATE, DELETE 쿼리를 별도로 로깅해야 합니다. 누가 언제 어떤 데이터에 접근했는지 추적할 수 있어야 합니다.
모든 DB 로그인 시도에 대해 성공과 실패를 기록하고, 특히 실패한 로그인 시도에 대해 접속 IP, 사용자명, 시도 시간을 상세히 기록해야 합니다. 무차별 대입 공격 탐지에 활용됩니다.
CREATE, ALTER, DROP 등 스키마 변경 DDL 명령에 대한 이력을 기록하고 관리해야 합니다. 승인되지 않은 스키마 변경을 탐지하고, 변경 전후 상태를 비교할 수 있어야 합니다.
감사 로그가 변조, 삭제되지 않도록 로그 파일에 대한 접근 권한을 제한하고, 가능하면 별도의 로그 서버로 실시간 전송해야 합니다. 공격자가 흔적을 지우는 것을 방지합니다.
법적 요구사항 및 내부 정책에 따라 감사 로그의 최소 보관 기간을 설정하고, 보관 기간이 지난 로그는 안전하게 폐기해야 합니다. 일반적으로 최소 1년 이상 보관을 권장합니다.
실행 시간이 비정상적으로 긴 쿼리를 기록하는 슬로우 쿼리 로그를 활성화해야 합니다. 비효율적인 쿼리는 성능 문제뿐 아니라 DoS 공격이나 데이터 유출 시도의 징후일 수 있습니다.
cron, Windows Task Scheduler 등을 활용하여 데이터베이스 전체 백업을 자동으로 정기 수행해야 합니다. 백업 주기는 데이터 변경 빈도에 따라 일 1회 이상으로 설정합니다.
최소 분기 1회 이상 백업 데이터를 실제로 복구하여 정상 동작을 검증해야 합니다. 백업이 존재하더라도 복구에 실패하면 무의미하므로, 복구 절차와 소요 시간을 검증합니다.
백업 파일을 DB 서버와 물리적으로 분리된 원격지에 보관해야 합니다. 서버 장애, 화재, 재해 등으로 인한 동시 손실을 방지하기 위해 최소 2개 이상의 다른 위치에 백업을 유지합니다.
전체 백업과 함께 증분 또는 차등 백업을 병행하여 백업 시간과 저장 공간을 최적화해야 합니다. 트랜잭션 로그 백업을 통해 특정 시점 복구(Point-in-Time Recovery)가 가능하도록 구성합니다.
백업 파일의 보관 기간을 명확히 정의하고, 기간이 경과한 백업은 안전하게 삭제해야 합니다. 오래된 백업 파일이 방치되면 불필요한 데이터 유출 위험이 발생합니다.
백업 파일에 대한 접근 권한을 DBA 또는 백업 관리자에게만 제한해야 합니다. 백업 파일에는 전체 데이터가 포함되어 있어, 비인가 접근 시 대량의 데이터가 유출될 수 있습니다.
데이터 센터 장애, 자연 재해 등 대규모 사고에 대비한 재해 복구 계획을 수립하고 정기 훈련을 실시해야 합니다. RPO(목표 복구 시점)와 RTO(목표 복구 시간)를 명확히 정의합니다.
MySQL 3306, PostgreSQL 5432, MSSQL 1433 등 기본 포트를 변경하고, 방화벽에서 허용된 IP에서만 DB 포트에 접근할 수 있도록 설정해야 합니다. 외부 네트워크에서의 직접 접근을 차단합니다.
DB 서버의 바인드 주소를 localhost(127.0.0.1) 또는 허용된 내부 IP로 제한해야 합니다. 0.0.0.0으로 설정하면 모든 네트워크 인터페이스에서 접근이 가능해져 공격 표면이 증가합니다.
사용하지 않는 DBMS 기능, 확장 모듈, 저장 엔진, 프로시저를 비활성화하여 공격 표면을 최소화해야 합니다. 특히 xp_cmdshell(MSSQL), LOAD DATA INFILE(MySQL) 등 위험한 기능은 반드시 비활성화합니다.
DBMS 벤더에서 제공하는 보안 패치를 정기적으로 적용하여 알려진 취약점을 제거해야 합니다. 패치 적용 전 테스트 환경에서 호환성을 검증하고, 패치 이력을 관리합니다.
최대 동시 연결 수, 쿼리 최대 실행 시간, 메모리 사용량 등을 제한하여 DoS 공격이나 비효율적 쿼리로 인한 서비스 장애를 방지해야 합니다.
my.cnf, postgresql.conf, pg_hba.conf 등 DBMS 설정 파일에 대한 읽기/쓰기 권한을 DB 관리자에게만 제한해야 합니다. 설정 파일이 노출되면 인증 정보와 보안 설정이 유출됩니다.
DBMS 설치 시 포함되는 샘플 데이터베이스(test, world, sakila 등)와 테스트 계정을 프로덕션 환경에서 제거해야 합니다. 이들은 공격자에게 불필요한 정보를 제공할 수 있습니다.
모든 SQL 쿼리에서 사용자 입력값을 문자열 결합(concatenation) 대신 파라미터 바인딩으로 처리해야 합니다. 이는 SQL 인젝션 공격을 방지하는 가장 기본적이고 효과적인 방법입니다.
ORM(Sequelize, TypeORM, SQLAlchemy 등) 사용 시에도 raw query, literal 함수, query builder에서 사용자 입력이 직접 포함되지 않도록 해야 합니다. ORM이 자동으로 모든 인젝션을 방어하지는 않습니다.
테이블명, 컬럼명, 정렬 기준 등 파라미터 바인딩이 불가능한 SQL 요소에 사용자 입력이 반영될 경우, 허용된 값 목록(화이트리스트)으로 검증해야 합니다. 블랙리스트 방식은 우회 가능성이 높습니다.
저장 프로시저 내에서 EXECUTE IMMEDIATE, sp_executesql 등으로 동적 SQL을 생성할 때도 반드시 파라미터 바인딩을 사용해야 합니다. 프로시저 내부의 인젝션 취약점은 간과되기 쉽습니다.
SQL 에러 발생 시 테이블명, 컬럼명, 쿼리문 등 DB 내부 구조가 사용자에게 노출되지 않도록 에러 처리를 구현해야 합니다. 에러 기반 인젝션(Error-based SQL Injection) 공격에 악용됩니다.
애플리케이션에서 사용하는 DB 계정에 FILE, PROCESS, SUPER 등의 시스템 권한이나 OS 명령 실행 권한을 부여하지 않아야 합니다. 인젝션 성공 시 피해 범위를 최소화합니다.
DB에 저장된 데이터가 이후 다른 쿼리에서 사용될 때도 인젝션이 발생할 수 있습니다(Second-Order Injection). 데이터를 DB에서 읽어 쿼리에 사용할 때도 항상 파라미터 바인딩을 적용해야 합니다.
MongoDB 등 NoSQL 데이터베이스를 사용하는 경우, 쿼리 연산자 인젝션($gt, $ne 등)과 JavaScript 인젝션($where)을 방지해야 합니다. 입력값의 타입을 검증하고 연산자 사용을 제한합니다.