[Playframework文檔中文翻譯]安全指導

(原文鏈接:http://play-framework.herokuapp.com/zh/security " ) 來自"Playframework中文小站 " )

安全指導

本章譯者:@nixil

雖然Play在設計之初就考慮了安全性問題,但是任何人都無法阻止程序員們自毀長城。以下的嚮導將會涉及web應用常見的安全性問題,以及在Play中該如何避免。

Sessions

你經常會需要保存一些跟用戶有關的信息,比如登錄狀態之類的。如果沒有session,用戶就得在每個請求當中都攜帶認證信息。

所謂session就是一組儲存在用戶瀏覽器的cookie中的數據,用於標識用戶,有時候還會根據應用的需要存儲一些額外信息,比如用戶的語言之類的。

安全第一要素 - 別把祕密公開

session是一組鍵/值的哈希,它帶有數字簽名但是並未加密。這意味着,如果你的簽名是安全的,任何第三方都無法僞造session。

這個數字簽名保存在@conf/application.conf@中. 一定要保證機密(數字簽名)的私有性,絕對不要把它提交到公有代碼庫中。當你安裝了一個由其他人構建的應用時,記得一定要用這個命令@play secret@,來修改原來的數字簽名,。

不在session中儲存關鍵數據

儘管有數字簽名,但由於cookie是未加密的,你還是不應在session當中存儲關鍵性數據。否則可能被通過查看cookie,或者在局域網/wifi的網關截獲http請求等方式暴露。

Play的session是存儲在cookie中的,而cookie的大小被瀏覽器限制爲4KB. 除了空間限制外, cookie中還僅能保存文本值。

跨站腳本攻擊

跨站腳本攻擊是web應用最大的弱點之一。其原理是在使用web應用的表單提交信息時,注入惡意JavaScript腳本. (這就好像送快遞的往你家的郵箱裏塞一個夾帶了竊'聽'器的包裹)

Let’s say you’re writing a blog, and anyone can add a comment. If you blindly include what commenters have written into your HTML page, you’re opening your site to attacks. It can be:

  • Show a popup to your visitors
  • Redirect your visitors to a site controlled by the attacker
  • Steal information supposed to be visible only to the current user, and send it back to the attacker’s site

假設你有一個寫博客的程序,而任何其它人都可以對博文添加評論,而評論最終會被顯示在該。如果你允許評論者們將任何評論信息(比如一段html代碼,其中可能還夾雜了javascript)內容提交到你的頁面中,你的站點就會被攻擊。可能會導致:

  • 你的blog的訪客將會收到一個彈出窗,這可能只是惡搞一下
  • 你的blog的訪客會被重定向到一個在攻擊者控制之下的站點
  • 竊取到本應只有當前用戶才能看到的信息,並將其發送到攻擊者的站點。

因此避開這些攻擊是至關重要的

Play的模板引擎會自動的將文本轉義。如果你確實需要在模板中插入未轉義的HTML,可以使用raw() 這個java擴展方法。但是如果文本是來自用戶的輸入,那你就要謹慎爲之,確保先對這些輸入進行“消毒”。

審查用戶輸入的時候,使用“白名單(只允許某些安全標籤)”比使用“黑名單(禁止某些不安全標籤而允許其他標籤)”來的安全。

更多關於跨站腳本

SQL 注入

SQL注入是一種利用用戶的輸入來執行SQL腳本的攻擊方式。這種攻擊可能摧毀你的數據,也可能使你的數據暴露給攻擊者。

如果你使用高級的“find”方法,你必須考慮到對付SQL注入的問題。當你手工創建查詢語句時,一定要小心不要使用字符串拼接(+ )的方式傳入參數,而應該使用@?@作爲佔位符然後替換。

這種是安全的:

createQuery("SELECT * from Stuff WHERE type= ?1").setParameter(1, theType);



而這一種則是危險的:

createQuery("SELECT * from Stuff WHERE type=" + theType;



CSRF-跨站請求僞造

CSRF-跨站請求僞造(又有戲稱session-riding)也是web應用的一個大問題:

這 種攻擊方法的前提是用戶(在當前或者最近一段時間)登錄了你的應用,瀏覽器中還保留着cookie。此時如果在該用戶訪問的某個頁面(可能是任何一個其他 的網站)中引入一段惡意的代碼或者鏈接,使之向你的應用發起請求。那由於這個用戶的session還沒有過期,該請求就會利用這個“僞造”的 session來通過應用的認證,執行惡意的操作了。

要防止這種攻擊,首先要正確的使用GET和POST方法. 也就是說,POST方法應該僅用於更改應用的狀態. (而相應的GET方法不應該用於更改應用狀態,這裏也就是所謂的GET方法應該具有等冪性,這樣一來攻擊者就無法通過惡意的鏈接來執行惡意操作)。

而對於接受POST請求的controller來說,保證每次收到的請求都是安全的方法之一,就是要求每個請求都提供一個認證口令(這個口令不是存放在cookie中而是作爲隨表單一起提交的一個隱藏字段)。Play提供了一些內置的幫助類和方法來處理這些事情。

  • controller中有一個@checkAuthenticity()@方法,它會檢查包含在請求參數中的口令的合法性,如果發現不對就會返回一個forbidden(403)的響應。
  • session.getAuthenticityToken() 方法會生成一個僅對當前session有效的口令
  • 在html模板的form中使用 #{authenticityToken /} 會生成一個包含口令的隱藏域

So for example:
例如下面的代碼(controller中的一個方法):

public static destroyMyAccount() {
    checkAuthenticity();
    …
}



checkAuthenticity()會進行檢查,只有提交的表單中包含正確的認證口令(模板中要加入如下面的代碼)時纔會執行

<form method="post" action="/account/destroy">
    #{authenticityToken /}
    <input type="submit" value="destroy my account">
</form>



Play的“表單標籤”: tags:#form 當其要提交到的action接受POST方法時會自動生成一個認證口令

#{form @destroyMyAccount()}
    <input type="submit" value="destroy my account">
#{/form}



當然如果你想把對所有controller的訪問都保護起來的話,你可以在增加一個controller的“before filter”: controllers#before,把@checkAuthenticity()@方法加在裏面

更多關於跨站請求僞造的信息

 

(原文鏈接:http://play-framework.herokuapp.com/zh/security " ) 來自"Playframework中文小站 " )

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