更新時間:2022-04-25 09:57:19 來源:動力節點 瀏覽795次
SQL注入是一種注入攻擊。當攻擊者提交惡意制作的輸入時,就會發生注入攻擊,從而導致應用程序執行意外操作。由于SQL數據庫無處不在,SQL 注入是互聯網上最常見的攻擊類型之一。
如果您只有時間保護自己免受一個漏洞的影響,那么您應該檢查代碼庫中的 SQL 注入漏洞!
當您遭受 SQL 注入攻擊時,可能發生的最糟糕的事情是什么?
我們的示例 hack向您展示了如何繞過登錄頁面:銀行網站的一個巨大安全漏洞。更復雜的攻擊將允許攻擊者在數據庫上運行任意語句。過去,黑客使用注入攻擊來:
提取敏感信息,例如社會安全號碼或信用卡詳細信息。
枚舉在網站上注冊的用戶的身份驗證詳細信息,因此這些登錄信息可用于對其他網站的攻擊。
刪除數據或刪除表,破壞數據庫,使網站無法使用。
當用戶訪問該站點時,注入要執行的更多惡意代碼。
SQL 注入攻擊非常普遍。雅虎和索尼等大公司的應用程序受到了損害。在其他情況下,黑客組織針對 特定的應用程序或編寫旨在收集身份驗證詳細信息的腳本。即使是安全公司 也不能幸免!
所以 SQL 注入是一個嚴重的風險。你怎么能保護自己?
參數化語句
編程語言使用數據庫驅動程序與 SQL 數據庫對話。 驅動程序允許應用程序針對數據庫構建和運行 SQL 語句,根據需要提取和操作數據。參數化語句確保傳遞給 SQL 語句的參數(即輸入)以安全的方式處理。
例如, 使用參數化語句在JDBC中運行 SQL 查詢的安全方法是:
// Connect to the database.
Connection conn = DriverManager.getConnection(URL, USER, PASS);
// Construct the SQL statement we want to run, specifying the parameter.
String sql = "SELECT * FROM users WHERE email = ?";
// Generate a prepared statement with the placeholder parameter.
PreparedStatement stmt = conn.prepareStatement(sql);
// Bind email value into the statement at parameter index 1.
stmt.setString(1, email);
// Run the query...
ResultSet results = stmt.executeQuery(sql);
while (results.next())
{
// ...do something with the data returned.
}
將此與 SQL 字符串的顯式構造進行對比,后者非常非常危險:
// The user we want to find.
String email = "[email protected]";
// Connect to the database.
Connection conn = DriverManager.getConnection(URL, USER, PASS);
Statement stmt = conn.createStatement();
// Bad, bad news! Don't construct the query with string concatenation.
String sql = "SELECT * FROM users WHERE email = '" + email + "'";
// I have a bad feeling about this...
ResultSet results = stmt.executeQuery(sql);
while (results.next()) {
// ...oh look, we got hacked.
}
關鍵區別在于傳遞給executeQuery(...) 方法的數據。在第一種情況下,參數化字符串和參數分別傳遞給數據庫,這允許驅動程序正確解釋它們。在第二種情況下,完整的 SQL 語句是在調用驅動程序之前構建的,這意味著我們容易受到惡意制作的參數的攻擊。
您應該始終在可用的情況下使用參數化語句,它們是防止 SQL 注入的第一保護。
您可以在下面的代碼示例中看到更多不同語言的參數化語句示例。
許多開發團隊更喜歡使用對象關系映射 (ORM) 框架來使 SQL 結果集到代碼對象的轉換更加無縫。ORM 工具通常意味著開發人員很少需要在他們的代碼中編寫 SQL 語句——幸運的是,這些工具在后臺使用了參數化語句。
最著名的 ORM 可能是 Ruby on Rails 的Active Record框架。使用 Active Record 從數據庫中獲取數據如下所示:
def current_user(email)
# The 'User' object is an Active Record object, that has find methods
# auto-magically generated by Rails.
User.find_by_email(email)
end
像這樣的代碼可以免受 SQL 注入攻擊。
然而,使用 ORM 并不會自動讓您免受 SQL 注入的影響。 當需要對數據庫執行更復雜的操作時,許多 ORM 框架允許您構造 SQL 語句或 SQL 語句的片段。例如,以下 Ruby 代碼容易受到注入攻擊:
def current_user(email)
# This code would be vulnerable to a maliciously crafted email parameter.
User.where("email = '" + email + "'")
end
作為一般經驗法則:如果您發現自己通過連接字符串來編寫 SQL 語句,請仔細考慮您在做什么。
如果您無法使用參數化語句或為您編寫 SQL 的庫,則下一個最佳方法是確保正確轉義輸入參數中的特殊字符串字符。
注入攻擊通常依賴于攻擊者能夠制作一個輸入,該輸入將過早關閉它們出現在 SQL 語句中的參數字符串。(這就是為什么您經常會在嘗試的 SQL 注入攻擊中看到'或字符的原因。)"
編程語言有標準的方法來描述其中包含引號的字符串——SQL 在這方面沒有什么不同。通常,將引號字符加倍——替換'為''——意味著 “將此引號視為字符串的一部分,而不是字符串的結尾”。
轉義符號字符是防止大多數 SQL 注入攻擊的簡單方法,許多語言都有標準函數 來實現這一點。但是,這種方法有幾個缺點:
您需要非常小心地在構建 SQL 語句的代碼庫中的任何地方轉義字符。
并非所有注入攻擊都依賴于引用字符的濫用。 例如,當 SQL 語句中需要數字 ID 時,不需要引號字符。無論您如何使用引號字符,以下代碼仍然容易受到注入攻擊:
def current_user(id)
User.where("id = " + id)
end
清理輸入是所有應用程序的好習慣。在我們的 示例 hack中,用戶提供了一個密碼 as ' or 1=1--,這看起來很可疑作為密碼選擇。
開發人員應始終努力拒絕看起來可疑的輸入,同時注意不要意外懲罰合法用戶。例如,您的應用程序可以通過以下方式清除GET 和POST請求中提供的參數:
檢查提供的字段(如電子郵件地址)是否與正則表達式匹配。
確保數字或字母數字字段不包含符號字符。
在不合適的地方拒絕(或去除)空格和換行符。
客戶端驗證(即在 JavaScript 中)對于在填寫表單時為用戶提供即時反饋很有用,但不能防御嚴重的黑客。大多數黑客嘗試都是使用腳本執行的,而不是瀏覽器本身。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習