雖然 SQL Injection 提出至今已經經過了許多年,但是 SQL Injection 依舊是目前網站應用程式的主要弱點之一,更是資料外洩的主要管道。根據 WhiteHat Security 的一份 White Paper 的內容指出,可以採用下列 10 個方法來避免 SQL Injection 產生危害:
- 將資料庫與網站伺服器分別安裝在不同的機器上,並確保機器維持在最新的更新狀態。(Install the database on a different machine than the Web server or application server. Make sure all the latest patches are applied.)
- 應該將資料庫內所有預設帳號與密碼加以關閉,尤其是管理者的帳號更是不可掉以輕心。(The database should have all the default accounts and passwords disabled, including the super-user account.)
- 建立一個應用程式專用的帳號,並給予其執行任務所需的最小權限。將所有範例表格以及不需使用的 stored procedure 加以移除。(Create an application user account in your database that has minimum privileges necessary for that application to access the data. Remove all the sample tables. Disable access to any stored procedure that is not required by that application user.)
- 找出所有需要執行的 SQL 指令,並僅允許這些指令的執行。(Identify the list of SQL statements that will be used by the application and only allow such SQL statements from the application, e.g. Select, Insert, Update, etc.)
- 在不需要使用 insert 或 update 的情形下使用 view 的方式來存取資料庫,可以應用在搜尋或是登入功能。(Use read-only views for SQL statements that do not require any inserts or updates, e.g. Search functionality or Login functionality.)
- 檢查輸入 (包含資料類型、長度、格式等) 並去除不必要的內容。(Sanitize the input by validating it in your code.)
- 使用參數化的查詢並避免使用動態式的查詢。以 Java 為例,應該使用 PreparedStatement 物件而非 Statement 物件。(Use parameterized queries instead of dynamic queries. For example, in Java, use Prepared Statement instead of Statement Object.)
- 採用合適的錯誤處理與記錄功能以確保資料庫發生錯誤時的訊息或其他技術資訊不會因此而洩漏。(Employ proper error handling and logging within the application so that a database error or any other type of technical information is not revealed to the user.)
- 選擇不易猜測的資料庫表格/欄位名稱。(Choose names for tables and fields that are not easy to guess.)
- 盡可能的使用 stored procedures。(Use stored procedures instead of raw SQL wherever possible.)
嚴格來說,第 7 點才是目前專門針對 SQL Injection 最主要也是最有效的控制措施。然而其他控制措施雖然並不是特別針對 SQL Injection 這類威脅,但是卻可以減少當系統發生問題時所產生的危害,因此也有其實施的效益。雖說如此,對於第 9 點與第 10 點我個人倒是有一些不同的看法。
首先針對第 9 點,雖然採用較難猜測的表格/欄位名稱可以減少攻擊者成功執行 SQL Injection 的機會,但是如果因此走向極端而將所有表格/欄位名稱改成無意義的名詞,那麼對於開發人員所造成的困擾可能遠大於其所帶來效益,在執行上必須小心謹慎。
而對於第 10 點我個人則採取完全相反的意見。雖然使用 stored procedures 確實可以增加 SQL Injection 成功的難度 (stored procedures 本身還是會遭受 SQL Injection 的攻擊),但是 stored procedures 的大量使用很容易使得系統的可移植性受到不良影響。更重要的是 stored procedures 將使得程式邏輯隱含在資料庫內部,對於系統功能的模組化往往是一大傷害。我這樣說並不是說 stored procedures 完全不可使用,而是 stored procedures 要不要使用、要使用到什麼程度,不應該從安全的角度來加以考量,而是應該回歸到業務與系統本身的需求。
除了這些要項之外,採用好的自動化工具 (不管是白箱或黑箱測試工具) 對避免 SQL Injection 的威脅也是目前相當有效的一種作法,值得需要系統化管理 SQL Injection 威脅的團隊加以評估。
相關連結: