1. 程式人生 > >安全測試回顧(四)

安全測試回顧(四)

屏蔽 管理 sets 大致 rest sta 方便 server 進行

SQL註入

幾乎每一個web應用都需要使用數據庫來保存操作所需的各種信息,所以web程序經常會建立用戶提交的數據的SQL語句。如果,建立這種語句的方法不安全,那麽應用程序就很容易受到SQL註入的攻擊。最嚴重的情況下,攻擊者可利用SQL註入讀取甚至修改數據庫中保存的所有數據。

由於互聯網行業的入門門檻不高,程序員的水平及經驗也參差不齊,相當大一部分程序員在編寫代碼的時候,沒有對用戶輸入數據的合法性進行判斷,使應用程序存在安全隱患。用戶可以提交一段數據庫查詢代碼,根據程序返回的結果,獲得某些他想得知的數據,這就是所謂的SQL Injection,即SQL註入。

SQL註入是從正常的WWW端口訪問,而且表面看起來跟一般的Web頁面訪問沒什麽區別,所以目前市面的防火墻都不會對SQL註入發出警報,如果管理員沒查看IIS日誌的習慣,可能被入侵很長時間都不會發覺。

惡意輸入用戶名:Username = ‘’or’1=1’ 和惡意輸入密碼 Password = ‘’or’1’=‘1’
得到的SQL會被篡改為:
SELECT id FROM Users WHERE Username = ‘’or’1=1’ AND Password = ‘’or’1’=‘1’
對於SQL解析器來說,這是一個可以正確解析並且可以被執行的SQL語句,它的結果等效為 SELECT id FROM Users 只要數據庫裏有數據,那麽該語句就能夠獲取user表中每條記錄,一般應用程序會選擇返回第一個記錄作為登錄的用戶,而很多系統第一個用戶為管理員,情況就變得更加糟糕。

我們知道mysql代碼的註釋是使用 --來表示的,所以可以:

SELECT id FROM Users WHERE Username = ‘’or’1’=‘1’ ;drop table users;--’AND Password = ‘’
紅色部分為我們的輸入,這樣我們註入的SQL仍能被正確解析,甚至可以導致users表被刪除(如果有刪除表權限的話);如果沒有刪除表的權限,那麽也可以嘗試用delete from user來代替drop table users。

註入的危害:
?1. 探知數據庫的具體結構,為進一步攻擊做準備
?2. 泄露數據,尤其是機密信息、賬戶信息等
?3. 取得更高權限,來修改表數據甚至是內部結構

SQL註入—簡單可註入點判斷

三步法:

如有一個url為:http://www.sample.com/test.asp?id=1可正常運行。測試步驟如下:
http://www.sample.com/test.asp?id=1’,如果提交的SQL語句變成 SELECT * from table where id=1’,那麽頁面返回異常;
http://www.sample.com/test.asp?id=1 and 1=1,頁面運行正常且頁面與http://www.sample.com/test.asp?id=1完全相同;
http://www.sample.com/test.asp?id=1 and 1=2,運行出現異常或頁面與http://www.sample.com/test.asp?id=1不同,提示BOF或EOF(程序沒做任何判斷時)、或提示找不到記錄(判斷了rs.eof時)、或顯示內容為空(程序加了on error resume next)
如果上面3步全滿足,則一定存在SQL註入漏洞。

不可以註入就比較容易判斷了,一般都會有程序定義的錯誤提示,或提示類型轉換時出錯。

當然,這只是傳入參數是數字型的時候用的判斷方法,實際應用的時候會有字符型和搜索型參數。需要有意識的進行分析,得出相應的註入測試語句。

根據註入參數類型,在腦海中重構SQL語句的原貌,按參數類型主要分為下面三種:
(A) ID=49 這類註入的參數是數字型,SQL語句原貌大致如下:
Select * from 表名 where 字段=49
註入的參數為ID=49 And [查詢條件],即是生成語句:
Select * from 表名 where 字段=49 And [查詢條件]
(B) Class=連續劇 這類註入的參數是字符型,SQL語句原貌大致概如下:
Select * from 表名 where 字段=’連續劇’
註入的參數為Class=連續劇’ and [查詢條件] and ‘’=’ ,即是生成語句:
Select * from 表名 where 字段=’連續劇’ and [查詢條件] and ‘’=’’
(C) 搜索時沒過濾參數的,如keyword=關鍵字,SQL語句原貌大致如下:
Select * from 表名 where 字段like ’%關鍵字%’
註入的參數為keyword=’ and [查詢條件] and ‘%25’=’, 即是生成語句:
Select * from 表名 where字段like ’%’ and [查詢條件] and ‘%’=’%’

確定了SQL註入漏洞確實存在,作為測試人員,我們已經可以將這個漏洞報給開發人員進行修復了。

避免sql註入的方法:

1.針對輸入值過濾

Select update delete drop insert ‘ () and or = ! , <>等過濾掉

2.參數化查詢

Sql語句預處理

// 定義查詢結構
String query = “SELECT username , role FROM USER WHERE username= ? And password =?”;
//預處理
stm= con.prepareStatement(query);
//將用戶輸入添加到第一個占位符?
stm.setString(1, request.getParameter(“name”));
Stm.setString(2, request.getParameter(“password”));
rs=stm.executeQuery;

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

攻擊方面:

將查詢條件替換成SQL語句,猜解表名,例如:
?And 1=1
?ID=49 And (Select Count(*) from Admin)>=0
?如果頁面就與ID=49的相同,說明附加條件成立,即表Admin存在,反之,即不存在(請牢記這種方法)。如此循環,直至猜到表名為止。
?表名猜出來後,將Count(*)替換成Count(字段名),用同樣的原理猜解字段名。
?有人會說:這裏有一些偶然的成分,如果表名起得很復雜沒規律的,那根本就沒得玩下去了。說得很對,這世界根本就不存在100%成功的黑客技術,蒼蠅不叮無縫的蛋,無論多技術多高深的黑客,都是因為別人的程序寫得不嚴密或使用者保密意識不夠,才有得下手。

SQL註入—破解字段值

在表名和列名猜解成功後,再使用SQL語句,得出字段的值,下面介紹一種最常用的方法-Ascii逐字解碼法,雖然這種方法速度很慢,但肯定是可行的方法。
?我們舉個例子,已知表Admin中存在username字段,首先,我們取第一條記錄,測試長度:
?http://www.sample.com/showdetail.asp?id=1 and (select top 1 len(username) from Admin)>0
?先說明原理:如果top 1的username長度大於0,則條件成立;接著就是>1、>2、>3這樣測試下去,一直到條件不成立為止,比如>7成立,>8不成立,就是len(username)=8
?當然沒人會笨得從0,1,2,3一個個測試,怎麽樣才比較快就看各自發揮了。在得到username的長度後,用mid(username,N,1)截取第N位字符,再asc(mid(username,N,1))得到ASCII碼,比如:
?id=1 and (select top 1 asc(mid(username,1,1)) from Admin)>0
?同樣也是用逐步縮小範圍的方法得到第1位字符的ASCII碼,註意的是英文和數字的ASCII碼在1-128之間,可以用折半法加速猜解,可以用Burp進行測試,效率會有極大的提高。

SQL註入—避開過濾

有時候,開發人員會有意識的執行某種輸入過濾以防止攻擊者輸入如’、selecet等字符;
?1. 使用ASCII碼動態構建替代,如在輸入中,單引號被屏蔽,我們可以嘗試使用字符的ASCII碼代替,CHAR(39)。
?2. 如果select關鍵字被屏蔽,嘗試使用URL hex編碼:
?%00SELECT
?%53%45%4c%45%43%54

SQL註入—經驗小結

1.有些人會過濾Select、Update、Delete這些關鍵字,但偏偏忘記區分大小寫,所以大家可以用selecT這樣嘗試一下。
?2.在猜不到字段名時,不妨看看網站上的表單,一般為了方便起見,字段名都與表單的輸入框取相同的名字。
?3.特別註意:http請求的+號傳入程序後解釋為空格,%2B解釋為+號,%25解釋為%號
?4.用Get方法註入時,IIS、apache等或者服務器會記錄你所有的提交字符串,對Post方法做則不記錄,所以能用Post的網址盡量不用Get。

?5. 一種實用的註入方法:
?(對於SQLSERVER數據庫)
http://www.sample.com/test.asp?id=1 and user>0
這句語句包含了SQLServer特有註入方法的精髓。user是SQLServer的一個內置變量,它的值是當前連接的用戶名,類型為nvarchar。一個nvarchar數據類型的值跟 int的數值0比較,系統會先試圖將nvarchar的值轉成int型,轉的過程中就會出錯,SQLServer的出錯提示是:將nvarchar值 ”test” 轉換數據類型為 int 的列時發生語法錯誤,這樣test正是變量user的值,成功拿到了數據庫的用戶名。

安全測試回顧(四)