데이터베이스 보호를 위한 상위 7가지 MySQL 보안 모범 사례
액세스 제어, 네트워크 노출, TLS, 패치, 로깅 및 암호화에 대한 7가지 실용적인 MySQL 보안 점검 사항입니다.
MySQL 데이터베이스 보호를 위한 상위 7가지 보안 모범 사례
MySQL 보안은 누가 연결할 수 있는지, 무엇을 할 수 있는지, 호스트가 손상되었을 때 무엇이 노출되는지를 줄이는 것에서 시작됩니다. 아래 7가지 점검 사항은 단일 설정으로 MySQL을 "안전하게" 만들 수 있다고 가정하지 않고 프로덕션 데이터베이스에 대한 실용적인 기준을 제공합니다.
1. 안전한 사용자 액세스 관리
데이터베이스에 액세스할 수 있는 사람과 그들이 할 수 있는 작업을 제어하는 것이 첫 번째 방어선입니다. 여기에는 최소 권한 원칙에 따라 특정 사용자 계정을 생성하는 것이 포함되며, 사용자는 작업을 수행하는 데 필요한 권한만 가져야 합니다.
강력한 계정 생성
공유 애플리케이션 사용자와 약한 비밀번호를 피하세요. 자체 관리 서버에서 mysql_secure_installation을 사용하여 익명 사용자를 제거하고, 해당되는 경우 테스트 데이터베이스를 제거하며, 초기 root 계정 설정을 강화하세요.
최소 권한 부여
애플리케이션에 필요한 특정 데이터베이스, 테이블 및 작업에 대해 GRANT 문을 사용하세요. 애플리케이션 계정에 ALL PRIVILEGES를 피하세요.
예시:
CREATE USER 'webapp_user'@'10.0.10.%' IDENTIFIED BY 'use-a-real-secret-here';
GRANT SELECT, INSERT, UPDATE ON mydatabase.* TO 'webapp_user'@'10.0.10.%';
일반적인 CREATE USER 또는 GRANT 문 후에 FLUSH PRIVILEGES가 필요하지 않습니다. MySQL은 해당 문에 대한 권한 테이블을 자동으로 업데이트합니다.
정기적으로 계정을 감사하세요:
SELECT user, host, account_locked FROM mysql.user ORDER BY user, host;
SHOW GRANTS FOR 'webapp_user'@'10.0.10.%';
2. 네트워크 액세스 제한
MySQL로의 네트워크 경로를 제한하세요. 유효한 기본값은 MySQL 버전 및 패키지에 따라 다르므로 로컬에서만 수신한다고 가정하지 말고 실행 중인 서버를 검사하세요.
리스너 확인:
ss -ltnp | grep 3306
로컬 클라이언트만 액세스해야 하는 경우 MySQL을 localhost에 바인딩하세요:
[mysqld]
bind-address = 127.0.0.1
애플리케이션 서버가 원격으로 연결하는 경우 개인 인터페이스에 바인딩하고 보안 그룹, 방화벽 또는 네트워크 ACL을 사용하여 해당 소스만 포트 3306에 액세스할 수 있도록 허용하세요.
3. 연결에 TLS 사용
전송 중 데이터를 암호화하면 도청 및 중간자 공격을 방지할 수 있습니다. MySQL은 클라이언트-서버 연결에 SSL/TLS 암호화를 지원합니다.
서버 구성은 일반적으로 다음과 같습니다:
[mysqld]
ssl-ca=/path/to/ca.pem
ssl-cert=/path/to/server-cert.pem
ssl-key=/path/to/server-key.pem
클라이언트 예시:
mysql -h your_host -u your_user -p --ssl-mode=REQUIRED
더 엄격한 확인을 위해 인증서와 일치하는 호스트 이름과 함께 --ssl-mode=VERIFY_IDENTITY를 사용하세요. REQUIRED는 연결을 암호화하지만 서버 ID를 강력하게 확인하지는 않습니다.
4. MySQL 업데이트 유지
소프트웨어 취약점은 자주 발견되고 패치됩니다. 오래된 버전의 MySQL을 실행하면 알려진 익스플로잇에 데이터베이스가 노출될 수 있습니다.
실행 중인 릴리스 스트림을 추적하고, 보안 업데이트를 적용하며, 프로덕션에 적용하기 전에 스테이징에서 업그레이드를 테스트하세요. 관리형 데이터베이스 서비스를 사용하는 경우 공급자의 유지 관리 정책을 검토하고 팀이 실제로 모니터링하는 유지 관리 기간을 설정하세요.
5. MySQL 서버 구성 강화
네트워크 바인딩 외에도 여러 다른 구성 옵션이 보안을 강화할 수 있습니다.
애플리케이션에 LOAD DATA LOCAL INFILE이 필요하지 않은 경우 local_infile을 비활성화하세요:
[mysqld]
local_infile = 0
구성 파일, TLS 키 및 백업 자격 증명을 적절한 시스템 사용자만 읽을 수 있도록 유지하세요. 또한 설치된 플러그인을 검토하고 사용하지 않는 플러그인을 제거하세요.
6. 로그 감사 및 모니터링
로깅은 의심스러운 활동을 감지하고 보안 사고 후 포렌식 분석에 중요합니다.
MySQL Enterprise에는 감사 로그 플러그인이 포함되어 있습니다. 커뮤니티 배포는 환경에 따라 운영 체제 로그, 오류 로그, 프록시 로그, 클라우드 데이터베이스 감사 기능 또는 타사 감사 플러그인을 사용하는 경우가 많습니다.
최소한 다음을 모니터링하세요:
- 실패한 로그인 및 인증 오류.
- 새 사용자, 변경된 권한 및 권한 있는 명령문.
- 예상치 못한 호스트의 연결.
- 백업 작업 실패 및 복원 테스트 실패.
특정 단기 문제 해결 요구 사항이 없는 한 사용량이 많은 프로덕션 서버에서 일반 쿼리 로그를 활성화된 상태로 두지 마세요. 이는 많은 I/O를 생성하고 민감한 쿼리 값을 캡처할 수 있습니다.
7. 저장 데이터 보호
SSL/TLS는 전송 중 데이터를 보호하지만, 저장 데이터 암호화는 기본 스토리지가 손상된 경우 데이터를 보호합니다.
광범위한 기준으로 스토리지 또는 볼륨 암호화를 사용하세요. 민감한 필드의 경우 데이터베이스가 데이터를 해독하는 데 필요한 모든 것을 보유하지 않도록 애플리케이션 수준 암호화를 고려하세요.
MySQL에는 AES_ENCRYPT() 및 AES_DECRYPT()와 같은 암호화 함수도 있지만 SQL에 키를 하드코딩하거나 데이터 옆에 저장하지 마세요.
간단한 예시:
UPDATE users
SET sensitive_data = AES_ENCRYPT('user_private_info', @encryption_key)
WHERE user_id = 1;
SELECT AES_DECRYPT(sensitive_data, @encryption_key)
FROM users
WHERE user_id = 1;
실제 시스템에는 적절한 키 관리 프로세스를 사용하세요. 키 순환, 액세스 제어 및 키 자료 백업이 없는 암호화는 복구 가능한 사고를 영구적인 데이터 손실로 바꿀 수 있습니다.
결론
가장 많은 위험을 제거하는 제어부터 시작하세요: 최소 권한 사용자, 개인 네트워크 액세스, TLS, 패치 및 테스트된 백업. 그런 다음 규정 준수 및 위협 모델과 일치하는 감사 로깅 및 암호화 제어를 추가하세요. 주요 스키마, 인프라 또는 액세스 변경 후마다 설정을 검토하세요.