参数化查询是唯一可靠防线,因其强制将用户输入视为纯数据而非SQL代码,使sleep()等时间延迟函数无法执行;字符串拼接必然失败,因攻击者可注入sleeP(5)、if(1=1,sleep(1),0)等绕过防护,直接触发数据库延迟响应。

参数化查询是唯一可靠防线,其他手段都只是辅助或容易被绕过。
为什么字符串拼接必然失败
时间盲注不依赖错误回显或数据返回,只靠响应延迟判断逻辑真假。只要用户输入参与了 SQL 字符串拼接,攻击者就能把 sleep(5)、waitfor delay '0:0:5' 或 pg_sleep(5) 注入进去——数据库解析器会照单执行,根本不会“识别”这是恶意行为。
- PHP 中用
mysql_query()或mysqli_query()拼接,哪怕加了addslashes()也拦不住大小写变形(sleeP(5))或嵌套(if(1=1,sleep(1),0)) - Java 里用
Statement+String.format(),sleep(5)会原样进 SQL,预编译阶段都没走到 - Python 若用
.format()或 f-string 构造查询,%s占位符形同虚设,实际没生效
各语言必须用的参数化写法
不是“推荐用”,而是“不用就等于开门揖盗”。不同语言的正确路径非常明确:
- PHP:必须走
PDO::prepare()+bindValue()或bindParam();禁用所有mysql_*和裸mysqli_query() - Java:只允许
PreparedStatement,且所有变量必须通过setString()等方法绑定;禁止Statement+ 字符串拼接 - Python:
sqlite3.Cursor.execute(sql, params)或psycopg2的%s占位符;绝不能用.format()、f-string 或+拼接 SQL 字符串 - MyBatis:只允许
#{},${}等同于字符串拼接,sleep(5)会直接进语句
ORM 安全不是绝对安全
Django ORM、Laravel Eloquent 默认走参数化,但一旦调用原生接口,防线立刻崩塌:
- Django 的
raw()、extra()、cursor.execute()—— 若传入未过滤的用户输入,等同于裸拼接 - Laravel 的
DB::select()、DB::statement()同理,whereRaw()里若含用户输入,sleep(5)就能执行 - 存储过程里用
EXEC(@sql)或CONCAT()动态拼接,应用层参数化完全无效,属于高危设计
WAF 和日志监控只能当耳目,不能当盾牌
指望 WAF 拦截 sleep、benchmark、waitfor 是危险的幻想:
- 关键词可大小写混淆:
SLEEp(5)、slEEp(5)轻松绕过规则 - 可嵌套绕过:
if(1=1,benchmark(1000000,sha1('a')),0)不含 sleep 却等效延时 - 慢查询日志难区分:
sleep(1)响应时间刚好卡在业务正常波动边缘,无法告警 - 真正要盯的是异常长事务、非预期的
pg_sleep调用、WAITFOR出现在非 DBA 操作上下文中
最常被忽略的点是环境一致性:本地开发用 MySQL 写了 if(1=1,sleep(5),0),上线切到 MSSQL 后语法报错,反而暴露了数据库类型,给攻击者提供了关键线索。

















