Web框架安全

模板引擎與XSS防禦

XSS攻擊是在用戶的瀏覽器上執行的,其形成過程則是在服務器端頁面渲染時,注入了惡意的HTML代碼導致的。從MVC架構來說,是發生在View層,因此使用“輸出編碼”的防禦方法更加合理,這意味着需要針對不同上下文的XSS攻擊場景,使用不同的編碼方式。

“輸出編碼”的防禦方法有以下幾種:

  • 在HTML標籤中輸出變量
  • 在HTML屬性中輸出變量
  • 在script標籤中輸出變量
  • 在事件中輸出變量
  • 在CSS中輸出變量
  • 在URL中輸出變量

針對不同的情況,使用不同的編碼函數。那麼現在流行的MVC框架是否符合這樣的設計呢?答案是否定的。

在當前流行的MVC框架中,View層常用的技術是使用模板引擎對頁面進行渲染,模板引擎本身可能會提供一些編碼方法,比如,Django Templetes中,使用filters中的escape作爲HtmlEncode的方法:

<h1>Hello, {{name|escape}}!</h1>

最好的XSS防禦方案,在不同的場景需要使用不同的編碼函數,如果統一使用者5個字符的HtmlEncode,則很有可能被攻擊者繞過。在模板引擎中,可以實現自定義的編碼函數,應用於不同場景。在Django中是使用自定義filters,在Velocity中則可以使用“宏”(velocimacro)。

 

 

Web框架與CSRF防禦

CSRF攻擊的目標,一般都會產生“寫數據”操作的URL,比如“增”、“刪”、“改”;而“讀數據”操作並不是CSRF攻擊的目標,因爲在CSRF的攻擊過程中攻擊者無法獲取到服務器端返回的數據,攻擊者只是借用用戶之手觸發服務器動作,所以讀取數據對於CSRF來說並無直接的意義。

因此,在Web應用開發中,有必要對“讀操作”和“寫操作”予以區分,比如要求所有“寫操作”都使用HTTP POST。但實際上POST本身並不足以對抗CSRF,因爲POST也是可以自動提交的。但是POST的使用,對於保護token有着積極的意義,而security token的私密性(不可預測性原則),是防禦CSRF攻擊的基礎。

對於Web框架來說,可以自動地在所有涉及POST的代碼中添加token,這些地方包括所有的form表單、所有的Ajax POST請求等。

完整的CSRF防禦方案,對於Web框架來說有以下幾點地方需要改動。

  1. 在Session中綁定token。如果不能保存到服務器Session中,則可以代替爲保存到Cookie中。
  2. 在form表單中自動填入token字段,比如 <input type=hidden name="anti_csrf_token" value="$token"/>。
  3. 在Ajax請求中自動添加token,這可能需要已有的Ajax封裝實現的支持。
  4. 在服務器端對比POST提交參數的token與Session中綁定的token是否一致,以驗證CSRF攻擊。

 

 

HTTP Headers管理

在Web框架中,可以對HTTP頭進行全局化的處理,因此一些基於HTTP頭的安全方案可以很好地實施。

比如針對HTTP返回頭的CRLF注入,因爲HTTP實際上可以看成是key-value對,比如:

Location: http://www.a.com
Host: 127.0.0.1

因此對抗CRLF的方案只需要在”value“中編碼所有的\r\n即可。這裏沒有提到在”key"中編碼\r\n,是因爲讓用戶能夠控制“key”是極其危險的事情,在任何情況下都不應該使其發生。

類似的,針對30X返回的HTTP Response,瀏覽器將會跳轉到Location指定的URL,攻擊者往往利用此類功能實施釣魚或詐騙。

HTTP/1.1 302 Moved Temporarily
(...)
Location: http://www.phishing.tld

因此,對於框架來說,管理好跳轉目的地址時很有必要的。一般來說,可以在兩個地方做這件事:

  1. 如果Web框架提供統一的跳轉函數,則可以在跳轉函數內部實現一個白名單,指定跳轉地址只能在白名單中;
  2. 另一個解決方式是控制HTTP的Location字段,限制Location的值只能是哪些地址,也能起到同樣的效果,其本質還是白名單。

有很多與安全相關的Headers,也可以統一在Web框架中配置,比如:用來對抗ClickJacking的X-Frame-Option,Cookie的HttpOnly Flag。

 

 

數據持久層與SQL注入

使用ORM框架對SQL注入是有積極意義的。我們都知道對抗SQL注入的最佳方式就是使用“預編譯綁定變量”。在實際解決SQL注入時,還有一個難點就是益康源複雜後,代碼數量龐大,難以把可能存在SQL注入的地方不遺漏地找出來,而ORM框架爲我們發現問題提供了一個便捷的途徑。

以ORM框架ibatis舉例,它是基於sqlmap的,生成的SQL語句都結構化地寫在XML文件中。ibatis支持動態SQL,可以在SQL語句中插入動態變量:$value$,如果用戶能夠控制這個變量,則會存在一個SQL注入的漏洞。

而靜態變量 #value# 則是安全的,因此在使用ibatis時,只需要搜索所有的sqlmap文件中是否包含動態變量即可。當業務需要使用動態SQL時,可以作爲特例處理,比如在上層的代碼邏輯中針對該變量進行嚴格的控制,以保證不會發生注入問題。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章