콘텐츠로 이동

동적 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를 만들지 마라 가 아니라
어디까지가 운영에서 허용 가능한 선택인가를 기록함.