동적 Trigger 생성과 secure_file_priv의 위험성¶
운영 환경에서 동적 Trigger 생성을 시도하며 실제로 겪은 문제를 기반으로
MySQL의 제약과 그에 따른 보안 리스크를 정리함.
1. 문제의 배경¶
특정 서비스에서는 다음과 같은 특성이 존재했음.
- 테이블이 동적으로 생성됨
- 생성된 테이블에 맞춰 Trigger 또한 동적으로 생성되어야 함
이 구조는 기능적으로는 필요했으나, MySQL의 다음 제약과 충돌함.
2. MySQL의 제약 사항¶
MySQL은 다음과 같은 제한을 가짐.
CREATE TRIGGER구문은 Prepared Statement에서 실행할 수 없음
즉, 다음 방식은 불가능함.
PREPARE stmt FROM 'CREATE TRIGGER ...';
EXECUTE stmt;
이는 MySQL의 설계상 제약이며, 현재까지 우회 불가한 제한임.
3. 선택한 우회 방식¶
Trigger 생성 SQL을 파일로 출력한 뒤, MySQL의 SOURCE 명령으로 실행하는 방식을 사용함.
SOURCE /path/to/trigger.sql;
이 방식 자체는 MySQL에서 허용된 기능임.
4. secure_file_priv 설정 변경¶
위 방식을 사용하기 위해 MySQL 설정에서 다음 값을 사용함.
secure_file_priv = ""
이 설정은 다음 의미를 가짐.
MySQL의 파일 입출력 경로 제한을 완전히 해제
5. 발생 가능한 보안 리스크¶
5.1 임의 파일 생성 및 덮어쓰기 위험¶
secure_file_priv 제한이 없는 경우, SQL 실행 권한을 확보한 사용자는 다음과 같은 작업을 시도할 수 있음.
- 임의 경로에 파일 생성
- 기존 파일 덮어쓰기
이는 다음 위험으로 이어질 수 있음.
- 시스템 설정 파일 손상
- cron, 로그 파일 오염
- 서비스 장애 또는 백도어 가능성
5.2 SQL Injection 공격의 확장¶
일반적인 SQL Injection은 데이터 조회·변조에 그치는 경우가 많음.
그러나 secure_file_priv = "" 상태에서는:
- 파일 생성
- 파일 덮어쓰기
- 간접적인 OS 레벨 공격 벡터 확보
로 공격 범위가 확장될 수 있음.
6. 운영 관점에서의 결론¶
다음 결론에 도달함.
- 기능적 요구를 충족하기 위해
- 보안 경계를 무너뜨리는 설정을 사용하는 것은
- 운영 환경에서 정답이 아님
특히 다음 설정은 운영 환경에서 사용하지 않는 것이 원칙임.
secure_file_priv = ""
7. 운영 환경에서의 대안¶
대안 1: Trigger 생성은 운영 작업으로 제한¶
- 애플리케이션에서 Trigger 생성 관여 ❌
- 운영자가 명시적으로 관리
- 자동화 범위 최소화
대안 2: secure_file_priv 제한적 허용¶
secure_file_priv = /var/lib/mysql-files
- MySQL 전용 디렉터리만 허용
- OS 권한 및 SELinux와 함께 제한
- 일반 애플리케이션 계정에는 FILE 권한 부여 ❌
대안 3: 구조 자체 재검토¶
- Trigger 의존도 축소
- Application Layer 처리
- Batch / Event 기반 처리
Cloud Managed DB 환경에서는
이 접근이 더 현실적인 경우가 많음.
8. 정리¶
- MySQL의 제약을 우회하는 방법은 존재함
- 그러나 모든 우회가 운영 환경에서 허용되는 것은 아님
- 보안 경계를 허무는 설정은 언젠가 비용으로 돌아옴
Trigger를 만들지 마라 가 아니라
어디까지가 운영에서 허용 가능한 선택인가를 기록함.