오늘은 PostgreSQL에서 최근 발견된 중대한 보안 취약점인 CVE-2025-1094에 대해 자세히 알아보겠습니다. 이 취약점은 특히 아시아 지역에서 널리 사용되는 문자 인코딩과 관련되어 있어 주목할 필요가 있습니다.
2025년 2월 13일, PostgreSQL 커뮤니티는 고위험도 SQL 인젝션 취약점을 발표했습니다. 이 취약점은 Rapid7의 수석 보안 연구원인 Stephen Fewer가 다른 취약점(CVE-2024-12356) 연구 중 우연히 발견한 것으로, 문자 인코딩 처리 과정에서 발생하는 심각한 보안 허점을 드러냈습니다.
1. CVE-2025-1094 취약점의 핵심 원인 분석
이번 취약점의 가장 큰 문제는 PostgreSQL의 libpq 라이브러리에서 문자열 이스케이핑(String Escaping) 처리 과정에 있습니다. 구체적으로 다음 함수들이 영향을 받습니다:
- PQescapeLiteral() – 리터럴 문자열 이스케이핑
- PQescapeIdentifier() – 식별자 이스케이핑
- PQescapeString() – 일반 문자열 이스케이핑
- PQescapeStringConn() – 연결별 문자열 이스케이핑
문제는 이러한 함수들이 따옴표 구문을 제대로 중성화하지 못한다는 점입니다. 특히 특정 멀티바이트 문자 인코딩을 사용할 때 이 문제가 더욱 심각해집니다.
문자 인코딩별 위험도
인코딩 타입 | 클라이언트 인코딩 | 서버 인코딩 | 위험도 |
---|---|---|---|
위험한 조합 | BIG5 | EUC_TW | 높음 |
위험한 조합 | BIG5 | MULE_INTERNAL | 높음 |
안전한 조합 | UTF-8 | UTF-8 | 낮음 |
안전한 조합 | LATIN1 | LATIN1 | 낮음 |
BIG5는 주로 대만에서 사용되는 번체 중국어 인코딩이고, EUC_TW와 MULE_INTERNAL은 각각 대만용 확장 유닉스 코드와 PostgreSQL 내부 멀티바이트 인코딩입니다.
2. 실제 공격 시나리오와 위험성
CVE-2025-1094의 무서운 점은 단순한 SQL 인젝션을 넘어서 임의 코드 실행(Arbitrary Code Execution)까지 가능하다는 것입니다.
공격 과정
- 1단계: 공격자가 유효하지 않은 UTF-8 문자를 포함한 악성 입력 전송
- 2단계: PostgreSQL의 이스케이핑 함수가 따옴표 구문을 제대로 처리하지 못함
- 3단계: 처리된 결과가 psql(PostgreSQL 대화형 터미널)로 전달됨
- 4단계: psql의 메타 명령어(
\!
)를 통해 운영체제 셸 명령 실행
-- 공격 예시 (실제로는 바이너리 데이터)
SELECT '악성문자열'; \! id; --
이런 방식으로 공격자는 데이터베이스 권한으로 시스템 명령을 실행할 수 있게 됩니다.
3. 영향받는 PostgreSQL 버전 현황
다행히 PostgreSQL 개발팀의 신속한 대응으로 모든 주요 버전에 대한 패치가 제공되었습니다.
취약한 버전들
- PostgreSQL 17 버전 17.3 이전의 모든 버전
- PostgreSQL 16 버전 16.7 이전의 모든 버전
- PostgreSQL 15 버전 15.11 이전의 모든 버전
- PostgreSQL 14 버전 14.16 이전의 모든 버전
- PostgreSQL 13 버전 13.19 이전의 모든 버전
패치된 안전한 버전들
- PostgreSQL 17.3 (2025년 2월 13일 릴리즈)
- PostgreSQL 16.7 (2025년 2월 13일 릴리즈)
- PostgreSQL 15.11 (2025년 2월 13일 릴리즈)
- PostgreSQL 14.16 (2025년 2월 13일 릴리즈)
- PostgreSQL 13.19 (2025년 2월 13일 릴리즈)
공식 패치 노트는 PostgreSQL 릴리즈 페이지에서 확인할 수 있습니다.
4. 현재 사용 중인 PostgreSQL 버전 확인 방법
본격적인 패치 작업에 앞서 현재 시스템의 PostgreSQL 버전을 정확히 파악해야 합니다.
터미널에서 확인
# PostgreSQL 버전 확인
psql --version
# 또는 데이터베이스에 접속하여 확인
psql -c "SELECT version();"
데이터베이스 내에서 확인
-- PostgreSQL 버전과 인코딩 정보 동시 확인
SELECT
version() as postgresql_version,
current_setting('server_encoding') as server_encoding,
current_setting('client_encoding') as client_encoding;
위험한 인코딩 조합 확인
-- 현재 인코딩 설정이 취약한지 확인
SELECT
CASE
WHEN current_setting('client_encoding') = 'BIG5'
AND current_setting('server_encoding') IN ('EUC_TW', 'MULE_INTERNAL')
THEN '위험: CVE-2025-1094 취약점에 노출됨'
ELSE '안전: 현재 인코딩 조합은 안전함'
END as vulnerability_status;
5. 단계별 패치 및 업그레이드 가이드
사전 준비사항
업그레이드를 시작하기 전에 반드시 다음 작업을 수행하세요:
# 1. 전체 데이터베이스 백업
pg_dumpall -U postgres > full_backup_$(date +%Y%m%d).sql
# 2. 개별 데이터베이스 백업 (중요 DB의 경우)
pg_dump -U postgres -d your_database > db_backup_$(date +%Y%m%d).sql
# 3. 설정 파일 백업
cp /etc/postgresql/*/main/postgresql.conf postgresql.conf.backup
cp /etc/postgresql/*/main/pg_hba.conf pg_hba.conf.backup
Ubuntu/Debian 시스템 업그레이드
# 1. 패키지 저장소 업데이트
sudo apt update
# 2. PostgreSQL 업그레이드 (자동으로 최신 패치 버전 설치)
sudo apt upgrade postgresql postgresql-client
# 3. 업그레이드 후 버전 확인
psql --version
# 4. 서비스 재시작
sudo systemctl restart postgresql
sudo systemctl status postgresql
CentOS/RHEL/Rocky Linux 업그레이드
# 1. 패키지 정보 업데이트
sudo yum update -y
# 2. PostgreSQL 업그레이드
sudo yum update postgresql postgresql-server
# 3. 서비스 재시작
sudo systemctl restart postgresql
sudo systemctl status postgresql
Docker 환경에서의 패치
# Dockerfile 업데이트 예시
FROM postgres:17.3 # 이전 버전에서 패치된 버전으로 변경
# 또는 기존 컨테이너 업데이트
docker pull postgres:17.3
docker stop your-postgres-container
docker run --name new-postgres-container -d \
-v your-data-volume:/var/lib/postgresql/data \
postgres:17.3
6. 임시 완화 조치 및 예방 방법
업그레이드를 즉시 수행할 수 없는 환경에서는 다음 완화 조치를 적용할 수 있습니다:
인코딩 설정 변경
-- 데이터베이스별 안전한 인코딩으로 변경
ALTER DATABASE your_database SET client_encoding = 'UTF8';
-- 세션별 임시 설정 변경
SET client_encoding = 'UTF8';
입력 검증 강화
# Python 예시: 입력 데이터 검증
import re
def validate_utf8_input(input_string):
try:
# UTF-8 유효성 검사
input_string.encode('utf-8').decode('utf-8')
# 의심스러운 패턴 제거
dangerous_patterns = [r'\\', r'\x00', r'\x5c']
for pattern in dangerous_patterns:
if re.search(pattern, input_string):
raise ValueError("Potentially dangerous input detected")
return True
except UnicodeDecodeError:
return False
매개변수화된 쿼리 사용
# 안전한 방법: 매개변수화된 쿼리
cursor.execute(
"SELECT * FROM users WHERE username = %s",
(user_input,)
)
# 위험한 방법: 문자열 연결 (사용 금지)
# cursor.execute(f"SELECT * FROM users WHERE username = '{user_input}'")
7. 클라우드 환경에서의 대응 방법
Amazon RDS PostgreSQL
AWS RDS는 자동 패치 기능을 제공하지만, 수동으로도 업그레이드할 수 있습니다:
# AWS CLI를 통한 RDS 인스턴스 업그레이드
aws rds modify-db-instance \
--db-instance-identifier your-rds-instance \
--engine-version 16.7 \
--apply-immediately
Amazon Aurora PostgreSQL 업데이트 정보에서 최신 패치 현황을 확인할 수 있습니다.
Google Cloud SQL
# gcloud CLI를 통한 업그레이드
gcloud sql instances patch your-instance-name \
--database-version=POSTGRES_16_7
Azure Database for PostgreSQL
Azure Portal에서 [Maintenance] → [Schedule Updates] 메뉴를 통해 업그레이드를 예약할 수 있습니다.
8. 보안 모니터링 및 로그 분석
패치 적용 후에도 지속적인 모니터링이 중요합니다:
의심스러운 활동 탐지
-- PostgreSQL 로그에서 의심스러운 패턴 검색
SELECT
log_time,
message
FROM pg_log
WHERE message LIKE '%invalid byte sequence for encoding "UTF8"%'
OR message LIKE '%psql%'
OR message LIKE '%meta-command%'
ORDER BY log_time DESC;
로그 설정 강화
# postgresql.conf 수정
log_statement = 'all' # 모든 SQL 문 로깅
log_min_error_statement = error # 오류 발생 시 상세 로깅
log_connections = on # 연결 로깅
log_disconnections = on # 연결 해제 로깅
9. 추가적으로 보안 강화하는 방법
네트워크 레벨 보안
# 방화벽 설정으로 PostgreSQL 접근 제한
sudo ufw allow from trusted_ip_range to any port 5432
sudo ufw deny 5432
데이터베이스 접근 제어 강화
-- 불필요한 권한 제거
REVOKE ALL PRIVILEGES ON DATABASE sensitive_db FROM public;
-- 최소 권한 원칙 적용
GRANT CONNECT ON DATABASE app_db TO app_user;
GRANT SELECT, INSERT, UPDATE ON specific_table TO app_user;
CVE-2025-1094는 문자 인코딩이라는 기본적인 기능에서 발생한 취약점으로, 다시 한번 보안의 중요성을 일깨워 줍니다. 특히 아시아 지역에서 사용되는 문자 인코딩과 관련된 만큼, 해당 지역의 개발자들은 더욱 주의 깊게 대응해야 합니다. PostgreSQL은 오픈소스 커뮤니티의 신속한 대응으로 빠르게 패치를 제공했습니다. 이번 사건을 계기로 우리 모두가 데이터베이스 보안에 대해 더욱 깊이 생각해보는 기회가 되었으면 합니다. 🙂
참고 자료: