SQL 注入测试技能(SQLi)
定位:面向真实授权业务系统的注入验证,不是 CTF writeup 的 payload 罗列。重点在「参数边界判定、注入点定位、响应差异建模、误报排除」,而非追求一个 flag。
触发条件
满足以下任一信号即应进入本技能(侦察阶段产出 endpoints.json 已标注候选注入点优先级):
- 端点存在用户可控的查询参数(
id/q/search/sort/ 分页page/offset/ 筛选器filter),且响应体随参数值语义变化(列表条数、字段、排序顺序)。 - HTTP 头部带结构化参数:
Cookie中的会话/偏好字段、X-Forwarded-For、Referer、User-Agent(后端记日志时常拼入 SQL)。 - JSON / XML / GraphQL 请求体存在嵌套字段,后端 ORM 层将其展开为查询条件(ORM 不等于安全,
order_by/group_by字段名注入、raw()/extra()逃逸是高发点)。 - 二阶注入信号:注册/评论/个人资料页写入的值,在另一查询场景(如后台统计、导出)被拼入 SQL 但前端不可见——需结合
assets.json的数据流追踪判断是否值得测。 - 错误回吞但响应可观测差异:同一参数,传入合法值与非法值(超大整数、非预期字符)时,响应大小/耗时/字段集合出现稳定可复现差异。
三层测试模型
对齐 DESIGN §3.1:L1 探测(快速排除明显不存在)→ L2 验证(确立可复现差异)→ L3 绕过(对抗真实 WAF / 风控)。每层只做上一层成立后才推进的事,避免对每个参数都跑完整 payload 表烧 token。
L1 探测
目标:用最小请求量判定「该参数是否可能受 SQL 语法影响」,不追求确认漏洞。
- 布尔语义探针:对同一参数分别传
真值基准与AND 1=1/AND 1=2(数字型)或' AND '1'='1/' AND '1'='2(字符型),比较响应指纹(状态码、Content-Length、关键 DOM 节点数、耗时)。 - 时间探针:对疑似盲注参数传
; WAITFOR DELAY '0:0:3' --(MSSQL)/AND SLEEP(3)(MySQL)/pg_sleep(3)(PG)/DBMS_PIPE.RECEIVE_MESSAGE('a',3)(Oracle),以响应延迟相对基准的稳定偏移(非单次抖动)为信号。 - 语法错误探针:传
'/"/)/\单字符,观察是否触发数据库原生错误回显、HTTP 500、或响应结构塌缩(ORM 异常常表现为 500 + 框架默认错误页)。 - 边界类型混淆:数字参数传字母串、字符串参数传超大数字、JSON 字段传数组/对象——ORM 反序列化失败有时会泄露底层 SQL 片段。
L1 的产出是「候选参数 + 初判数据库指纹 + 注入类型假设」,写入
findings.json的hypothesis字段,不直接定级。
L2 验证
目标:把 L1 假设变成可复现、可向他人演示的差异证据,禁止仅凭响应码或单次延迟下结论。
- 布尔盲注建立稳定基线:重复 N 次(≥3)取「真条件响应」与「假条件响应」的指纹差,确认差异在去掉网络抖动后稳定存在;记录两组完整请求/响应(脱敏后)。
- 时间盲注建立统计:连续发 K 次(≥5)延迟探针 + K 次基准请求,用延迟分布(中位数而非单点)判定是否触发
sleep;单次 3s 不能定论(GC、慢查询同样造成延迟)。 - 联合查询/报错注入:若 L1 暴露回显或报错,用
ORDER BY n二分定位列数,再取可见回显列;报错型优先用函数回显(如 MySQLupdatexml/ PGCAST异常 / MSSQLconvert),避免堆叠多请求。 - 数据库指纹收口:联合查询确定列数 + 版本函数(
@@version/version()/banner from v$version)一起取,把「假设的库」收敛为「确认的库」,定级与后续 payload 都依赖它。
L3 绕过
目标:在目标存在 WAF / 风控 / 输入过滤时,验证注入是否仍可达——这才是实战与靶场的分水岭。
- 关键字过滤识别:逐个传
SELECT/UNION/AND/ 空格 / 注释符,记录哪些被拦截(403 / WAF 页 / 静默丢弃),建立「过滤面」清单,而非盲目堆 payload 字典。 - 编码与变形:对被拦关键字尝试大小写混写、内联注释
/**/、URL 双重编码、%0b等空白替代、等价函数(SUBSTRING↔MID、ASCII↔ORD);变形以「绕过该特定 WAF」为目标,逐个验证而非组合爆破。 - 语义等价改写:
AND被禁用&&/BETWEEN;空格被禁用括号语法UNION(SELECT...);引号被转义时尝试宽字节(GBK 场景%bf%27)或CHAR()构造。 - 风控对抗:控制单 IP 请求频率、轮换行为正常的请求伪装成业务流(先访问首页再发探针)、避免在风控采样窗口内集中触发——目标是「证明在真实对抗环境下注入仍可达」,不是触发风控封禁。
L3 成立是定级上调的依据(绕过防护 = 利用链真实可达),但产出仍须 PoC + 证据,不得凭「能绕过」直接定级。
证据要求
什么才算确认 SQLi(缺一不可,禁止仅凭响应码/单次现象下结论):
- 可复现:同一 PoC 在去掉抖动后重复执行(≥3 次)稳定复现差异或回显,记录每次的请求与响应指纹。
- 对照基线:提供「注入 payload」与「等价无注入基准」的成对请求/响应(如
id=1vsid=1 AND 1=2),证明差异由 SQL 语义而非业务逻辑引起。 - 数据库确证:至少一条证据指向具体数据库与版本(版本函数回显、报错中的方言特征、
information_schema/sysobjects可访问性),避免「疑似注入」的模糊定级。 - 影响说明:注明该注入可读取/篡改的具体数据边界(当前库、跨库、是否 DBA 权限、是否可写文件/执行命令),基于已确认的权限而非假设。
- 证据脱敏:响应中出现的真实用户数据、业务记录只记录结构与条数,不落明文;发现的凭证样式字符串(连接串里的口令等)只存哈希。
禁止事项
- 仅授权目标:本技能只在
scope.yamlin_scope且有书面授权的目标上运行;ScopeGuardHook 拦截即停,不尝试旁路自身防护。 - 不破坏数据:不执行
DROP/UPDATE/DELETE/INSERT/ 写文件 / 执行系统命令等破坏性或持久化操作——证明可读性已足以定级,写操作不提供额外安全价值且违反只读原则。 - 凭证不落明文:响应或数据库内容中出现的口令、Token、连接串,证据里只记录哈希与类型,原文不入
findings.json/ 日志 / 报告。 - 不超范围扩张:发现的注入点只能用于确认该参数的漏洞边界,不得据此横向探测 scope 外资产或枚举库表以外的系统信息。
- 不依赖错误回显作为唯一证据:错误回吞是常态,能确认就别只靠报错型;报错证据须与盲注证据至少二选一可独立成立。