You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Postgres同时使用预编译语句和字符转义能否抵御恶意输入攻击?

问题核心漏洞

你这套写法本质上完全没有正确利用预编译语句的安全防护能力:你只是预编译了查询模板,最后执行时依然手动拼接参数到SQL字符串中,和直接拼接SQL没有本质区别,仅靠转义单引号的防护非常脆弱,存在明确的注入风险。

可行注入方式

就算你做了单引号转义,也可以通过空字节截断实现注入,只需要让function_that_returns_user_input_string()返回如下内容即可:

任意内容\x00'); DROP TABLE myschema.mytable;--

攻击原理:
PostgreSQL解析字符串时遇到空字节(\x00)会直接截断字符串内容,你转义后的参数拼接到SQL中后结构如下:

EXECUTE mystatement ('任意内容\x00''); DROP TABLE myschema.mytable;--');

数据库读到\x00时就认为参数的字符串已经结束,后面的'); DROP TABLE...会被当成独立的SQL语句执行,直接删除目标表。

除此之外如果数据库客户端使用GBK等多字节编码,还可以通过宽字节注入绕过单引号转义防护,不需要空字节也能完成注入。

替换为INSERT语句的影响

完全不会改变存在注入风险的结论。只要你还是保持手动拼接EXECUTE参数的写法,不管是SELECT、INSERT、UPDATE还是DELETE语句,都可以通过同样的思路构造注入 payload,比如INSERT场景下可以构造payload插入管理员权限账号、篡改业务数据,也可以直接用堆叠查询执行删库、提权等恶意操作。

正确的防护写法

完全不需要自己做单引号转义,直接用数据库驱动的参数绑定能力传参即可:

# 错误写法:手动拼接参数
# cursor.execute(f"EXECUTE mystatement ('{modified_input}');")
# 正确写法:通过驱动绑定参数
cursor.execute("EXECUTE mystatement (%s)", (user_input,))

这种写法下参数会被驱动单独处理,完全不会被解析为SQL语法的一部分,从根源上避免SQL注入风险。


内容的提问来源于stack exchange,提问作者JCollier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 02:09:03