再谈Mysql中limit后的注入

L.N. (http://ln.sycsec.com/) | 2016-03-10 19:10

0×01 问题来了

   前几天@DM_同学在群里发现一个问题,关于mysql中limit的注入。带有oeder by的limit,目前limit后注入的唯一方法是使用procedure analyse进行报错注入,详细请阅读http://zone.wooyun.org/content/18220,在文中提到此方法适用于5.x系列的mysql,然而DM_测试5.6.11的时候此方法报错(无耻盗@DM_图一张):

c01ab81b-85a5-4e1a-9ea7-d42404bcd9b2.jpg

  那么问题就来了,翻遍国内外资料,群里各位大佬介不知情况。本着追根溯源的精神,我“不自量力”的翻看了mysql源码,发现了此问题的原因。

0×02问题根源

先说结论:此方法只适用于小于5.6.6的5.x系列。

翻看5.6.6以下版本的analyse()实现

https://github.com/mysql/mysql-server/blob/5.5/sql/sql_analyse.cc

重点在加粗函数

else if (param->next)

  {

    // first parameter

    if (!(*param->item)->fixed && (*param->item)->fix_fields(thd, param->item))

    {

      DBUG_PRINT("info", ("fix_fields() for the first parameter failed"));

      goto err;

    }

······

······  

    // second parameter

    if (!(*param->item)->fixed && (*param->item)->fix_fields(thd, param->item))

    {

      DBUG_PRINT("info", ("fix_fields() for the second parameter failed"));

      goto err;

    }


我们动态调试

输入语句:SELECT id FROM test WHERE id >0 ORDER BY id LIMIT 1,1 procedure analyse(1,extractvalue(rand(),concat(0x3a,version())));

给proc_analyse_init函数下断点

对第一个参数做验证,fixed=1

25a11ac4-3964-490a-b57b-4e1e2c87fb90.png

对第二个参数做验证,fixed=0,表示此参数没有被固定,将被fix_fields函数处理

544ed245-b59a-46c8-aba1-3d4878b215f9.png

此次可以看见我们的第二个参数extractvalue(rand(),concat(0x3a,version()))将被fix_fields处理

在mysql中所有函数都是用Item_func类来表示的,当然extractvalue也不例外。

继续跟:

81af7e0d-8468-46e6-968e-d2d730f9d21d.png

0×03为什么5.6.6以后不行了

在这个版本的时候analyse函数进行了改写,于是乎不行了

d6e9b5eb-7bfb-4022-999e-e1422532bd0d.png

怎么改写的?你没有看错,两个参数都只能为uint了。

3c9808f7-e038-4060-9071-ed1e29ede9c7.png

0×03总结

各种装逼半天,其实我就想说limit后的注入,使用analyse()只能5.0.0<mysql<5.6.6的版本

21fa8ab7-87c9-4f0a-8cd3-f85d286d0e0b.jpg

c515a53e-6277-4ea3-b43c-5c491d1f3c33.png