安全設計原則:數據與代碼分離。
注入攻擊的本質:把用戶的輸入數據當作代碼來執行。
關鍵條件:
- 用戶能夠控制輸入。
- 程序要執行的代碼拼接了用戶輸入的數據。
1 SQL 注入
1.1 概述
因爲 98 年黑客雜誌的一篇文章, SQL 注入第一次爲人熟知。
var sql="select * from area where city ='" + city +"'";
正常場景(傳入 Shanghai),執行的 SQL 語句:
select * from area where city = 'Shanghai';
黑客傳入有語義的參數:
Shanghai'; drop table area--
這時,執行的 SQL 語句爲:
select * from area where city = 'Shanghai'; drop table area--
這樣的話,查詢語句執行後,相應的表也被惡意刪除了!
1.2 防禦誤區
使用那些基於黑名單的方法,比如過濾字符。存在如下問題:
方法 | 攻擊 |
---|---|
過濾空格 |
select/**/city/**/from/**/area 或 select(city)from(area)
|
過濾括號與引號 | 0x61646D696E |
過濾 SQL 保留字 | having、order by 可能出現在自然語言中,會造成誤殺。 |
1.3 有效防禦
1、預編譯語句
這是防禦 SQL 注入攻擊的最佳方法,因爲輸入的參數不會改變 SQL 語句的語義。
2、存儲過程
使用存儲過程的效果與預編譯語句相似。但應該儘量避免在內部動態生成 SQL 語句。
如果某些場合,無法使用預編譯語句或存儲過程,那麼可以考慮以下方法:
3、檢查數據類型
檢查數據類型可以在一定程度上對抗注入攻擊。但不是萬能的,比如字符串類型,就需要依賴其他防禦方法。
4、安全函數
5.數據庫
最小權限原則:Web 應用應該避免使用 root 等最高權限賬戶(因爲這些賬戶可以創建自定義函數、操作本地文件權限)。
2 其它類型注入
它們的相同特點:都是違反了數據與代碼分離。
2.1 XML 注入
注入方式上與 HTML 類似。
2.2 代碼注入
都是由一些不安全的函數或者方法引起的。
比如 js 的 eval()
。eval()
函數可計算某個字符串,並執行其中的的 JavaScript 代碼。
在 Java 中可以利用腳本引擎實施 js 代碼注入。
安全設計原則:數據與代碼分離。