如何发现SQL注入漏洞
使用注释符
- 在注入时使用注释符,主要是为了消除原始查询中剩余的部分,防止语法错误。MySQL中使用-- (注意末尾空格)
- 若应用过滤空格,可用/**/注释符替代
单引号测试
- 在输入框的输入点添加一个
'
(单引号),观察页面是否报错。 - 预期结果:
- 存在漏洞:页面返回数据库错误(如MySQL、SQL Server的报错信息)。
- 无漏洞:页面正常或显示通用错误(如“参数错误”)
- 示例:
URL/?id=1'
- 报错原因:SQL语句中单引号未闭合
- 为什么存在漏洞:如果应用直接将数据库的报错信息显示给用户,说明输入没有被过滤或转义,可能存在注入漏洞,数据库报错说明用户输入直接影响到了SQL语句的结构,导致语法错误
- 注意:并非所有返回错误的情况都是SQL注入漏洞
- 例如,应用可能自己检测到非法输入并返回错误页面,这时候的错误信息并不是来自数据库,而是应用层控制的
- 因此,关键要看错误信息的内容是否是数据库特定的,比如MySQL的错误信息会有“You have an error in your SQL syntax”这样的提示
布尔测试(真/假条件判断)
- 原理:构造一个恒真或恒假的条件,观察页面响应差异
- 恒真条件:
' AND 1=1 --
- 如果页面正常显示,说明条件被接受
- 恒假条件:
' AND 1=2 --
- 如果页面无数据或异常,说明条件生效
- 两者结果一致 → 可能无漏洞或需进一步测试
- 为什么存在漏洞:如果应用程序没有正确过滤输入,攻击者的条件会被拼接到SQL语句中,从而改变查询的原始逻辑。例如,永真条件会让WHERE子句始终成立,而永假条件则让查询结果为空。攻击者注入的AND 1=1或AND 1=2会被拼接到SQL语句中,直接影响查询逻辑
- 考虑到盲注的情况,即页面没有明显回显,但通过真假的响应差异(如页面内容的不同、HTTP状态码的变化,或者响应时间的差异)来判断。这时候布尔测试尤为重要,因为它不依赖错误信息或数据回显
- 适用场景:
- 页面无显式回显:无法通过UNION SELECT直接显示数据
- 无数据库报错信息:错误信息被屏蔽,无法触发Error-Based注入
- 盲注环境:仅能通过页面内容、HTTP状态码或响应时间差异间接推断结果
- 局限性:
- 依赖响应差异:若真/假条件响应无区别,无法判断漏洞
- 效率较低:盲注需逐字符猜测,耗时较长
- 过滤绕过:若关键词(如AND、OR)被过滤,需使用替代方案(如&&、||)
联合查询测试(Union-Based)
- 尝试通过 UNION SELECT 联合查询获取数据
- 适用场景:页面会回显数据库查询结果(如文章详情页)
- 步骤:
- 确定字段数:
order by
- 联合查询测试回显位:
union select 1,2,3
- 确定字段数:
- 为什么要联合查询测试回显位:回显位指的是网页上显示数据库查询结果的位置。当进行联合查询时,攻击者需要确定他们的注入查询结果会显示在网页的哪个位置,这样才能有效地提取数据
- 通过测试不同的列数,并观察页面变化,攻击者可以确定哪些列的数据会被回显到页面上,从而在这些位置插入恶意查询以提取信息
- 为什么必须测试回显位?
- 数据可见性:只有通过回显位才能直接看到注入的查询结果
- 若注入的数据未显示在页面上,攻击者需依赖盲注(Boolean/Time-Based),效率大幅降低
- 精准提取信息:回显位允许攻击者直接插入数据库函数或查询语句,快速获取敏感数据
SELECT 1
在SQL中的基本含义是什么?其实这是一个简单的查询,返回数字1- 当攻击者使用
UNION SELECT 1,2,3
时,这里的1、2、3是为了匹配原始查询的列数,从而让联合查询生效。这时候,数字1、2、3本身并没有实际的数据意义,只是用来占位,方便后续替换成实际的函数或数据,比如database()
或者version()
- 在注入过程中如何确定需要多少个
SELECT 1,2,3
中的数字。这需要先通过ORDER BY
子句来确定原始查询的列数,然后确保联合查询的列数相同,否则会引发错误。所以这里的数字个数是根据ORDER BY
测试得到的列数来决定的 - 将显示的数字位置替换为数据库函数以提取数据
- 若原始查询的字段类型不兼容(如某列需字符串类型),可使用 NULL 或字符串占位