再探偏移注射

2010, January 1, 1:55 PM. 黑友网文
Submitted by admin

t00ls.ent

好寂寞的版块,我发篇烂文,黑客们都把私藏的0day发出来嘛
关于Union偏移注射这个东西,最早貌似是lake2大黑客提出来的,以前一直当他是鸡肋,没去关注过,直到昨天遇到一个mysql 4.1的点。
表,列都猜出来了,就差数据。因为他的参数是按“,”分割的,所以在注射的时候必须避开逗号,这样一来普通的union就用不成了,想暴力猜解也不行,因为substring也得用到逗号。无奈中想起join语句,偏移注射里面有一个很重要的技巧就是用join语句来控制字段数和数据显示的位置。麻烦的地方在于很多时候你根本不知道目标系统的环境,表里到底有多少列,数据类型什么的,怎么把他拼装到凑齐字段数,只能靠乱猜。
目标网站order by 7正常,order by 8无返回,那么一共是7个字段,按照通常的做法,应该是先and 1=2 union select 1,2,3,4,5,6,7#来看看情况,这里因为要避开逗号,就必须用到join语句。但是不知道用户表一共有几列,没有关系,我们可以用select * from ((select username from users)as a join (select username from users)as b on a.username=b.username),把select出部分字段的结果集当做一个表,然后来join到一起,这样只要把(select username from users)as a重复7次,就可以把字段补齐。
上面的语句在mysql5里面可以正常执行,也可以用到union子句中,可是在mysql4里就报语法错误,看来4.x不支持这么复杂的嵌套。修改了一下:
select * from users as a join (select id from users) as b on a.id=b.id
这样在4.1里可以正常执行,4.0因为不支持子语句,简单的说就是不支持()里带select,所以就木有办法鸟。
但是这样又有问题鸟,因为第一个select后面必须跟*,否则只会返回第一列。Mysql的join语句默认应该是inner join,也就是内连接,我尝试换成left join或者right join都不行,我记得mysql4应该是支持左连接和右连接的,搞不懂这里为什么行不通。这么一来又必需猜目标表的字段数了,而且目标表的字段数必需<=语句里select出的字段数才行,也受显示数据字段的制约。好处就是不知道列名也没关系,可以用常数来代替,即select 1,2,3,4,5 union select * from users as a join (select 1 from users) as b join (select 1 from users) as c on a.id=1
这样就完全避开了“,”,select出来的数据里可能会有很多重复,用distinct关键字过滤掉即可。
如果目标表的字段>前面选择的字段也没关系,因为必需保证最前面的字段是*,找一个字段少一点的表,即select * from news as a join (select username from users) as b,不过这个东西受到扫出来的表名,字段数,显示数据字段的制约,比较鸡肋了。
以上语句在mysql里测试成功,如果要在access或者mssql里使用,估计得另外调试。这个跟以前提出来那个偏移注射有些区别,也姑且算另外一种意义上的偏移注射吧。核心思想就是不断的join来补齐字段,从而避开,。

最郁闷的是,最后竟然是用fckeditor搞定shell的,真没技术含量,一下午白研究了-_-

刚才在外面骑车的时候,突然想到,之前的语句select * from users as a join (select id from users) as b on a.id=b.id前面必须要用到*是因为他并没有把这个select * from users as a作为一个整体来解析,而是将users as a跟后面的join到一起了,即select * from (users as a join (select id from users) as b on a.id=b.id),当然前面要用*,才能返回子语句里所有的列数了。
那么改写成select distinct * from (select 1 from users)as a join (select 2 from users)as b即可,然后依次像后面join补齐字段,最后把合适的地方换成用户名密码字段即可。mysql 4.1下测试成功,当然还是需要知道列名,呵呵

续:
刚才测试了一下,这个方法也可以用到acc环境下,那么以前认为是鸡肋的偏移注射看来也不那么鸡肋了
Access偏移注射为什么以前被认为鸡肋,没有意义,第一是猜到表之后猜不到列的可能性比较小(小不代表没有),二是很难控制密码字段所在的位置,假设有下面的环境:
注射点一共select了19个字段,其中2,3,5字段显示在页面上。Admin表猜出来了,猜不到用户和密码字段,猜到一个id字段。试探出admin表一共有7列(如果不知道表里有多少列数据可以union select 1,* from admin这样递增,后面的常数,什么时候有返回了,表的列数就确定了)。假设用户名和密码分别在第二三列。按照以前的方法,admin表只能join一次,即把列数填充到本身的2倍,然后前面用常数补齐,即and 1=2 union select 1,2,3,4,5,* from admin as a inner join admin as b on a.id=b.id。这个时候,username字段在7和14处,password字段在8和15处,都没有显示到页面里。而这个时候你没有办法再调整username跟password的位置了,原因前人说得很清楚了,access环境下,跟在union后面出来的结果集总是把*放在最后的。所以说偏移注射里面,显示字段的位置不能任意调整,受环境限制太大,很难灵活运用在实际注射中。
好了,现在我们用到前面的方法,把select 出部分字段的结果集当作一个表,来和前面的join在一起,即and 1=2 union select * from ((select * from admin) as a inner join (select * from admin) as b on a.id=b.id) inner join (select id,1,2,3,4 from admin) as c on c.id=a.id,就把用户名和密码字段排到显示的位置上来了。如果数据显示的位置在其他地方也没关系,因为这时候*的位置在字段里是可以控制的。假设现在显示位置的字段在6,7,那么and 1=2 union select 1,2,3,4,* from ((select * from admin) as a inner join (select * from admin) as b on a.id=b.id) inner join (select id from admin) as c on c.id=a.id,就可以把用户密码字段移动到正确的位置上。遇到一些变态的点的时候也可以用来避开,,只要不断的构造join,凑齐字段数就行了。当然,如果用户表里的字段数大于前面语句里select出的字段数那就一点办法也没有了。
Access不像mssql,union语句里字段类型的互相兼容还是比较好的,常用的数据类型基本都可以混在一起显示,那么这个手段在实际应用的意义中还是很乐观的,不过捏,实际环境中的运用还有待测试,因为语句越复杂,出错的可能性就越大,也越容易被过滤掉。
当然,任何技巧都会有局限性,第一个问题是必需知道表里面任意一个字段的名称,因为后面的on c.id=a.id要求是实体列,常数列不行。第二个就是,假设显示的字段在2,3列,用户名或者密码字段从4列开始就不行了,或者说假设显示的字段在倒数第二列,用户名或者密码字段后面还有2列以上就不行了,因为*虽然是可以在字段里任意移动,但是这个*里面的结构是固定的。不管怎么说,这个方法的灵活性提高了很多,要是遇到那样BT的环境的话只能说明你RP实在太低了哈哈~~

« 上一篇 | 下一篇 »

Trackbacks
点击获得Trackback地址,Encode: UTF-8 点击获得Trackback地址,Encode: GB2312 or GBK 点击获得Trackback地址,Encode: BIG5
发表评论

评论内容 (必填):