Fortify漏洞之Access Control: Database(數據越權)
繼續對Fortify的漏洞進行總結,本篇主要針對 Access Control: Database(數據越權)的漏洞進行總結,如下:
1、Access Control: Database(數據越權)
1.1、產生原因:
Database access control 錯誤在以下情況下發生:
1. 數據從一個不可信賴的數據源進入程序。
2. 這個數據用來指定 SQL 查詢中主鍵的值。
示例 1:以下代碼使用可轉義元字符並防止出現 SQL 註入漏洞的參數化語句,以構建和執行用於搜索與指定標識符相匹配的清單的 SQL 查詢。您可以從與當前被授權用戶有關的所有清單中選擇這些標識符。
...
id = Integer.decode(request.getParameter("invoiceID"));
String query = "SELECT * FROM invoices WHERE id = ?";
PreparedStatement stmt = conn.prepareStatement(query);
stmt.setInt(1, id);
ResultSet results = stmt.execute();
...
問題在於開發者沒有考慮到所有可能出現的 id 值。雖然接口生成了一個當前用戶的標識符清單,但是攻擊者可以繞過這個接口,從而獲取所需的任何清單。因為此例中的代碼沒有執行檢查,確保用戶有權訪問需要的清單,所以代碼會顯示所有清單,即使這些清單並不屬於當前用戶。
1.2、修復方案:
與其靠表示層來限制用戶輸入的值,還不如在應用程序和數據庫層上進行 access control。任何情況下都不允許用戶在沒有取得相應權限的情況下獲取或修改數據庫中的記錄。每個涉及數據庫的查詢都必須遵守這個原則,這可以通過把當前被授權的用戶名作為查詢語句的一部分來實現。
例:以下代碼實施了與例 1 相同的功能,但是附加了一個限制,即為當前被授權的用戶指定某一特定的獲取清單的方式。
...
userName = ctx.getAuthenticatedUserName();
id = Integer.decode(request.getParameter("invoiceID"));
String query =
"SELECT * FROM invoices WHERE id = ? AND user = ?";
PreparedStatement stmt = conn.prepareStatement(query);
stmt.setInt(1, id);
stmt.setString(2, userName);
ResultSet results = stmt.execute();
總之,要防止數據越權的漏洞問題,需要做到以下兩個要點:
a、對需要查詢的數據,給sql語句加上數據權限的限定條件,限定數據所屬角色。
b、對於這個加上的數據權限的限定條件,最好是從後臺獲取,而不是通過前臺傳入。
Fortify漏洞之Access Control: Database(數據越權)