如何发现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 或字符串占位
为什么要判断闭合方式
- 特别是字符型,必须先判断闭合方式
- 在SQL注入中,用户输入被拼接到查询语句里,如果没有正确闭合原有的引号或括号,整个SQL语句就会语法错误,导致注入失败。
- 比如,如果原始查询是用单引号包裹字符串,而攻击者没有闭合它,后面就会有多余的引号,引发错误
- 字符型闭合(单引号/双引号)
- 括号闭合
- 场景:参数被包裹在括号中(常见于复杂查询或框架生成的SQL)
- 示例:
SELECT * FROM users WHERE (username='[输入]');
- 闭合方法:
') OR 1=1 --
- 混合闭合(引号+括号)
- 如何快速判断闭合方式?
- 触发语法错误
- 输入'、"、),观察是否报错
- 若输入'报错,可能是单引号闭合
- 若输入)报错,可能需要闭合括号
- 布尔测试验证
- 单引号闭合:
- ' AND '1'='1 → 正常
- ' AND '1'='2 → 异常
- 括号闭合:
判断注入类型
数字型
- 数字型注入发生在参数不需要引号包裹的情况下
- 常见场景:URL中的ID参数、分页参数等
- 检测方法
- 输入数字运算:
id=1+1 -- 正常应返回id=2的结果
- 布尔测试:
id=1 AND 1=1 -- 正常显示 id=1 AND 1=2 -- 无数据
字符型
- 字符型注入则涉及用引号包裹的参数,如 username='admin'
- 检测方法
- 闭合引号测试:
username='' OR '1'='1' -- 若绕过登录,说明存在注入,在测试时输入单引号后,如果报错,说明可能存在字符型注入,需要闭合单引号并注释掉后续代码
- 布尔测试:
username='admin' AND '1'='1' -- → 正常显示
username='admin' AND '1'='2' -- → 无数据
万能密码
- 什么是万能密码?
- 万能密码是通过 SQL 注入构造的特殊字符串,使登录验证的 SQL 查询条件恒为真,从而绕过用户名和密码校验
- 示例:
' or '1'='1 --
- 适用阶段
- 阶段 1:漏洞探测(初步测试)
- 目标:快速判断是否存在 SQL 注入漏洞。
- 操作:
- 在登录框的用户名或密码字段输入万能密码。
- 观察是否成功绕过登录验证
- 阶段 2:漏洞验证(确认闭合方式)
- 目标:明确参数的闭合方式(单引号、双引号、括号等)。
- 操作:
- 尝试不同闭合方式的万能密码
- 根据是否登录成功,确定闭合符号类型
- 场景限制
- 密码哈希存储:若密码经过哈希处理,即使绕过验证也无法直接获取明文密码。
- 二次验证:部分系统登录后还需二次验证(如 OTP、IP 白名单)。
- 权限限制:若数据库用户权限不足,无法访问敏感表(如 users)
过滤空格
过滤引号
- 用 CHAR() 函数或十六进制编码
- 示例:
' OR CHAR(49)=CHAR(49) --
posted @
2025-03-01 19:44
micryfotctf
阅读(
167)
评论()
收藏
举报