SQL注入原理及代码分析(一)
字数 1134 2025-08-15 21:31:40
SQL注入原理及代码分析教学文档
1. SQL注入概述
SQL注入是一种将恶意SQL代码插入或添加到应用程序输入参数中的攻击技术,攻击者通过这些参数修改后台SQL语句的执行逻辑。
1.1 SQL注入产生条件
- 参数用户可控:前端传给后端的参数内容是用户可以控制的
- 参数带入数据库查询:传入的参数拼接到SQL语句并带入数据库查询
开发原则:外部参数皆不可信
2. SQL注入类型及原理分析
2.1 Union注入攻击
漏洞代码示例
$con=mysqli_connect("localhost","root","XFAICL1314","dvwa");
if(mysqli_connect_error()){
echo "连接失败:" .mysqli_connect_error();
}
$id=$_GET['id'];
$result=mysqli_query($con,"select * from users where `user_id`=".$id);
$row=mysqli_fetch_array($result);
echo $row['user'] . $row['password'];
攻击原理
- 程序直接拼接用户输入的
id参数到SQL语句 - 查询结果直接输出到页面(有回显)
- 攻击者可构造恶意
id值修改SQL语句
攻击步骤
- 判断注入点类型(数字型/字符型)
- 判断字段数:
order by n - 使用union查询获取数据:
union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()
2.2 布尔盲注攻击
漏洞代码示例
$con=mysqli_connect("localhost","root","XFAICL1314","dvwa");
if(mysqli_connect_error()){
echo "连接失败:" .mysqli_connect_error();
}
$id=$_GET['id'];
if(preg_match("/union|sleep|benchmark/i",$id)){
exit("on");
}
$result=mysqli_query($con,"select * from users where `user_id`=".$id);
$row=mysqli_fetch_array($result);
if ($row) {
exit("yes");
}else{
exit("no");
}
攻击原理
- 页面只返回"yes"或"no",无数据回显
- 通过构造布尔条件,根据页面返回结果推断数据
攻击方法
-
判断数据库名长度:
and length(database())>=1 -
逐字符猜解数据库名:
and substr(database(),1,1)=0x64substr(string,start,length)从1开始计数- 字符需转换为16进制格式
-
猜解表名:
and substr((select table_name from information_schema.tables where table_schema=库名 limit 0,1),1,1)=要猜解的字母
2.3 报错注入攻击
漏洞代码示例
$con=mysqli_connect("localhost","root","XFAICL1314","dvwa");
if (mysqli_connect_error()){
echo "连接失败:".mysqli_connect_error();
}
$id=$_GET['id'];
if($result=mysqli_query($con,"select *from users where `user_id`=".$id)){
echo "ok";
}else{
echo mysqli_error($con);
}
攻击原理
- 利用数据库报错信息回显数据
- 常用函数:
updatexml()、floor()
攻击方法
-
获取当前用户:
and updatexml(1,concat(0x7e,(select user()),0x7e),1)0x7e是~的16进制编码concat()用于连接字符串
-
获取数据库名:
and updatexml(1,concat(0x7e,(select database()),0x7e),1)
2.4 时间盲注攻击
漏洞代码示例
$con=mysqli_connect("localhost","root","XFAICL1314","dvwa");
if (mysqli_connect_error()){
echo "连接失败:".mysqli_error();
}
$id=$_GET['id'];
if (preg_match("/union/i",$id)){
exit("<html><body>no</body></html>");
}
$result=mysqli_query($con,"select * from users where `user_id`=".$id);
$row=mysqli_fetch_array($result);
if ($row){
exit("<html><body>yes</body></html>");
}else{
exit("<html><body>no</body></html>");
}
攻击原理
- 页面无数据回显,仅返回"yes"/"no"
- 利用时间延迟函数判断条件真假
攻击方法
-
判断数据库长度:
if (length(database())>3,sleep(5),1)- 如果长度>3,则休眠5秒
-
逐字符猜解:
and if (substr(database(),1,1)=库的第一个字母,sleep(5),1)
3. 防御措施
- 参数化查询(预处理语句)
- 输入验证:白名单过滤
- 最小权限原则:数据库账户仅授予必要权限
- 错误处理:不返回详细错误信息
- Web应用防火墙(WAF)
4. 工具推荐
- 手工测试:Burp Suite的Intruder模块
- 自动化工具:sqlmap
- 编码转换:Hex编码工具
5. 总结
| SQL注入类型 | 特点 | 适用场景 |
|---|---|---|
| Union注入 | 有数据回显 | 查询结果直接输出的页面 |
| 布尔盲注 | 仅返回真假 | 无数据回显但能区分真假 |
| 报错注入 | 错误信息回显 | 开启错误显示的页面 |
| 时间盲注 | 无任何回显 | 完全无回显的页面 |
后续将讨论堆叠注入、二次注入、宽字节注入、cookie注入等其他类型。