【SQL injection】認識注入攻擊與 7 種防範方式
SQL 為結構化查詢語言(Structured Query Language)的縮寫,是一種可以管理資料庫的程式語言,用來對資料庫下查詢、插入、刪除資料,及更新資料庫等指令。使用 SQL 的資料庫應用廣泛,也因此針對 SQL 的 SQL injection 攻擊長年被致力於資訊安全的國際非營利組織 OWASP(Open Web Application Security Project)列在十大網路攻擊名單中。然而 SQL injection 究竟是什麼呢?運作原理為何?可以造成何種威脅?又該如何防範?本文將以深入淺出的方式回答以上問題。
認識 SQL injection(SQL 注入)
SQL injection 攻擊常翻譯作 SQL 注入、插入、注射、注碼或資料隱碼攻擊,顧名思義是以 SQL 程式語言進行的注入攻擊(Injection Attacks),利用網頁/應用程式與資料庫之間的安全漏洞,竊取或破壞資料。
所謂的注入攻擊指的是,駭客透過輸入程式碼至網頁或應用程式中,以在其執行過程或目的上動手腳,使系統誤將惡意代碼當成合法指令並執行。用比喻的方式來說,注入攻擊可以想像成:法庭上,被告在姓名欄位填入自己的名字某某以及「無罪」兩字。法官被告個人資料時,便會直接唸出「某某無罪」。
一、SQL injection 攻擊原理
SQL injection 可能會因為個別資料庫設定不同有變化,但其核心概念皆為:駭客在提供使用者輸入資訊的欄位,鍵入 SQL 語法。舉例來說,在登入欄位、搜尋欄位、聯繫表單等位置,以 SQL 程式碼對資料庫下達指令。
【各欄位示意圖】
以下比較正常 SQL 指令和 SQL injection 攻擊,並以實際例子說明 SQL injection。
假設使用者輸入正確的帳號(AAA)及密碼(12345)後,資料庫收到 SQL 指令為:
Select user_data from TABLE Where user_name=‘AAA’ and password=‘12345’ |
代表從資料庫中的「TABLE」表格,執行以下:
取出使用者資料: 滿足(使用者名稱等於 AAA)TRUE 並且 AND 滿足(使用者密碼等於 12345)TRUE |
使用者名稱等於 AAA 為「條件 1」,而使用者密碼為 12345 為「條件 2」。程式在資料庫中找到,使用者名稱 AAA 並且密碼為 12345 的使用者後,程式便會判斷「條件 1」和「條件 2」皆為 TRUE,並抓出該使用者資料。
駭客在不知道正確帳號密碼的情況下,也可以透過在帳號密碼欄位下 SQL 指令登入系統。例如在帳號密碼欄位輸入空白以及「OR 1=1」:
Select user_data from TABLE Where user_name=‘ OR 1=1’ and password=‘ OR 1=1’ |
代表從資料庫中的「TABLE」表格,執行以下:
取出使用者資料: 滿足(使用者名稱等於 或 1=1)FALSE OR TRUE 並且 AND 滿足(使用者密碼等於 或 1=1)FALSE OR TRUE |
在這個範例裡,條件 1 為「『空白內容』或是『1=1』」,系統無法找到空白內容的使用者名稱,但「1=1」為 TRUE,因此條件 1 仍會被判定為 TRUE。同樣道理,條件 2 也會被判定為 TRUE。駭客便可以順利登入系統,獲取資料。
【SQL injection 攻擊流程示意圖】
SQL injection 攻擊會造成什麼影響?
駭客可利用 SQL injection 攻擊干擾應用程式,取得未經授權的資料、竄改資料庫中的資料、顛覆應用程式邏輯等等,進而威脅到對無論是個人、組織還是公司企業來說,最有價值的資料。資料遭竊的個人使用者,可能遭盜用身份、盜刷信用卡或因此陷入釣魚詐騙的陷阱;對企業組織來說亦是非同小可,可能導致公司名譽受損、客戶流失、法律糾紛、金錢損失等危機。
除此之外,SQL injection 還可以衍生和搭配不同網路攻擊手法,達到不同的攻擊目的。例如駭客甚至能透過 SQL injection,攻擊應用程式的伺服器或其他後端基礎架構;藉著 SQL injection 發動阻斷服務(DoS)攻擊;或發動複合 SQL injection 攻擊,針對同一目標同時使用 DDoS 攻擊或其他網路攻擊。
【想要進一步瞭解 Dos 攻擊和 DDoS 攻擊嗎?請參考《DDoS 攻擊》文章。】
SQL 注入攻擊的種類
SQL injection 攻擊本身原理雖然單純,但實際使用上,會根據各資料庫查詢規定設置差異,出現各種情況。同時,網頁和應用程式開發者不斷加強資料庫防禦,駭客也會想更多辦法繞過預防措施。而依據駭客存取後端資料的方式,以及可造成的影響,SQL injection 可以分成三大類:In-band SQL injection、Inferential SQL injection 和 Out-of-band SQL injection。
一、In-band SQL injection
In-band SQL injection 也稱作「經典 SQL injection」,指駭客利用同一個溝通管道(即使用者和應用程式互動的介面)發動 SQL injection 攻擊和收集竊取來的資訊。例如駭客在同一網頁上入侵資料庫和提取資料。In-band SQL injection 是最簡單的攻擊方式,也因此最為普遍,又有 Error-based 和 Union-based 兩種子類別。
Error-based 故意以錯誤的 SQL 查詢來獲得關於資料庫本身結構的資訊,用以策劃未來、針對性更高的網路攻擊。而 Union-based 則是利用 Union 運算子(SQL Union Operator)將兩個或兩個以上的 SQL 查詢合併在一起,在單一欄位中,要求資料庫提供其他多項資訊。
二、Inferential SQL injection/Blind SQL injection
有些網站頁面不會在發生錯誤時,提供錯誤的詳細內容或其他資料庫資料。但駭客可藉由反覆盲測、和資料庫互動,並觀察其反應,進一步瞭解攻擊目標,這樣的攻擊手法稱為 Inferential SQL injection 或 Blind SQL injection。 駭客使用這類 SQL injection 攻擊,所花費時間較多,但具有一定威脅性。Blind SQL injection 同樣可以分成兩個子類別:Boolean-based 和 Time-based。
Boolean-based 類型的 SQL injection 中,駭客對資料庫送出 SQL 查詢後,觀察伺服器的回應來判斷該查詢的條件是否為真。另一方面,駭客則依據伺服器回應所需的時間,推斷送給資料庫的查詢內容是否為真。
三、Out-of-band SQL injection
相對於 In-band SQL injection,進行 Out-of-band SQL injection 時,駭客使用不同的溝通管道攻擊和收集資料。由於 Out-of-band SQL injection 主要針對與資料庫串連的其他系統,如 DNS 伺服器等,受攻擊的目標伺服器需要有其他串連,並且能夠以 DNS 或 HTTP 回應,攻擊才能順利發揮效用。因此 Out-of-band SQL injection 有一定限制,而較少為駭客所用。
7 種 SQL injection 防範方式
提供網站或應用程式服務的企業,在實務上可以透過以下方式阻斷 SQL injection 攻擊:
-
將查詢參數化(Query Parameterization):開發人員可以事先定義所有 SQL 代碼為不同的參數,並限制使用參數進行 SQL 查詢。如此一來,可輸入查詢的內容範圍有限,駭客便無法任意使用 SQL 程式碼,要求伺服器執行指令。
-
轉義參數(Escape Parameters):檢查輸入的查詢內容,並將其中夾雜的 SQL 代碼替換成其他字元,以防止 SQL 程式碼被置入網頁或應用程式。但採用此方法需多留意 SQL 語法更新,隨其修改檢查規定;同時檢查規則中可能有遺漏的 SQL 程式碼,降低防範強度。
-
使用白名單(White List):建立白名單,只允許特定的數值輸入進欄位。
-
採用最低權限原則(Principle of Least Privilege,PoLP):將 SQL 指令限制在最小的範圍裡,透過降低 SQL 指令可以執行的動作,減低 SQL injection 攻擊的風險。
-
不顯示錯誤訊息:針對 Blind SQL injection,可減少透露錯誤的原因,僅顯示「請重新再試一次」,避免駭客藉盲測收集情報。
-
關閉預設帳號:有些資料庫會有預設的帳號,未關閉或移除預設帳號,讓駭客有機可乘,透過 SQL injection 登入。
-
注意資料表命名方式:使用 SQL injection 攻擊時,駭客需猜測資料庫中的資料表和欄位名稱,比方說「以 SQL 指令要求應用程式從資料庫中的某一表格刪除資料」。若使用「login」或「user」等常見名稱命名表格,駭客猜中的機率較高,SQL injection 攻擊的成功機率也因此提高。
現代社會中,資料的重要性不可言喻。針對資料而進行的 SQL injection 攻擊固然可怕,但只要採取適當的防禦措施,謹慎制定資料庫查詢規則,就可以將風險降至最低。