Rails安全导读【一】
生活随笔
收集整理的這篇文章主要介紹了
Rails安全导读【一】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文地址:[url]http://guides.rubyonrails.org/security.html[/url]
--------翻譯分割線 ,翻譯的不好,請多多指正--------
Ruby On Rails? 安全導讀
這個指南描述的是在web應用里普遍的安全問題,同時也給出了在Rails里如何避免這些問題。如果你有任何問題,請mail作者,Heiko Webers, at 42 {et} rorsecurity.info.?? 讀完此文后,你應該會了解:
?1.所有的對策已經被高亮顯示了
?2.在Rails里session的概念, 該放什么在session里,以及一些流行的***方法
?3.只是瀏覽一個站點,怎么就有安全問題呢?(with CSRF)
?4.當你使用files或提供一個管理界面的時候需要注意些什么
?5.The Rails-specific mass assignment problem
?6.如何管理用戶:登陸,注銷以及對所有層面的***方法。
?7.以及最流行的注入***方法。
一? 介紹
web application框架幫助開發者建立種種web應用,某些框架在安全方面也幫你省心不少。事實上,一個框架并不比另一個安全。對于大多數的框架來說,如果你正確使用它,可以建立安全的應用。Ruby on Rails有許多聰明的helper方法,例如防止注入***的方法,這讓sql注入變成了困難的事情。很高興看到我審定的所有rails app都有一個良好的安全級別。
一般沒有這種即插即用的安全,安全依賴于正在使用的框架,有時候也依賴于開發方式。它取決于web應用的所有環境:后端存儲,網絡服務器和網絡應用程序本身(以及可能的其他層或應用程序) 。
Gartner組織估計大約75%的***都是在web應用,并且在300個調查的web應用里,97%都是容易被***的。這是因為web應用容易***,因為它們易于理解和操作,甚至是懶人。
在受到威脅的web應用中,包括用戶帳戶劫持,繞開訪問控制,閱讀或修改敏感數據,或出示虛假的內容。或***者可以安裝一個特洛伊***程序或不請自來的電子郵件發送軟件,目的是在金融活動或造成損害品牌名稱,修改公司的資源。為了防止***,最大限度地減少其影響和消除***點,首先,你必須充分了解***方法,以便找到正確的對策。這正是該指南的目的。
為了開發安全的Web應用你必須不斷更新的所有層次和了解你的敵人。要不斷更新訂閱的安全郵件列表,請閱讀安全博客,并更新和安全檢查的習慣。我手工做這些,因為這你才能找到討厭的合乎邏輯的安全問題。
二 Sessions
我們的安全之旅最好是從最易受到特別***的sessions開始。
2.1?? 什么是sessions
— HTTP is a stateless protocol Sessions make it stateful.
- HTTP是一個無狀態協議,Sessions使它有狀態。
大多數的應用需要對一個特別用戶的某些狀態進行跟蹤。比如,一個購物車的內容,一的當前登陸用戶的id,如果沒有sessions這個好主意,用戶必須在每一個請求都得去標識驗證身份。如果一個新用戶訪問這個應用,Rails會自動創建一個新的session。如果用戶之前使用過這個應用,它會自動加載一個存在的session。
一個session通常是一個hash和一個session id(通常是一個32個字符的字符串)來標識這個hash。Rails里你可以用如下方式保存和使用session:
session[:user_id] = @current_user.id
User.find(session[:user_id])
2.2? session id
— The session id is a 32 byte long MD5 hash value.
- session id就是個一32位的md5 hash值。
一個session id由一個隨機字符串的hash值組成。這個隨機字符串是當前的時間,一個0和1之間的隨機數字,一個ruby解釋器進程id數字和一個常量字符串組成。
2.3? session劫持
- 竊取用戶session id的***者可以在一個web應用里使用受害者的名字。
許多web應用都有一個驗證系統:一個用戶提供一個用戶名和密碼,web應用檢查并且存儲相應的user id到session的這個hash里。從現在開始,session是有效的。在每個http請求里, 應用會加載這些在session里用user id來標識的用戶,并不需要新的驗證。這個session id是放在cookie里用來標識這個session的。
因此cookie作為web應用的臨時驗證。任何人得到一個別人的cookie,他就可以偽裝為這個人使用對應的web應用-可能會有嚴重的后果。這里有一些session劫持的方法,以及對策:
1.在不安全的網絡進行嗅探cookie。無線局域網就是這樣一個例子。在這樣的一個網絡里,特別容易去監聽所有鏈接的客戶端, 這就是不去咖啡店工作的原因(某些sb就喜歡去星巴克打開本本裝比)。對于web應用開發者,這就意味著去提供一個安全的ssl連接。
2.大多數的人在公共場所工作之后不清除cookie,所以如果是最后一個沒有在web應用注銷的用戶,你有可能偽裝成這個用戶。在web應用里提供給用戶一個注銷按鈕,并且放在醒目的位置。
3.許多跨站點腳本( XSS )***的目的是獲得用戶的cookie 。你之后會看到關于xss的更多內容。
4.Session定制,之后會讀到.
大多數***者的目的是為了錢,失竊的銀行登陸帳號的價格范圍從$10 - $1000不等(取決于可用的資金數額),信用卡號碼是$0.40-$20,在線拍賣網站的帳號為$1-$8,email密碼為$4-$30 ,參考賽門鐵克的網絡安全威脅報告。
2.4 session 準則
-這里有一些session的一般準則
1.不要在session里存儲大的對象。相反,你應該把它們存儲在數據庫里,把它們的id保存在session里。這將消除同步的麻煩,而且也不會占用你session的存儲空間(取決于你選擇的session的存儲)
2.關鍵的數據不應該被存儲在session里。如果用戶清除了cookie或者關閉了瀏覽器,它們都將丟失,用一個客戶端session存儲,用戶可以讀取數據。
2.5 session存儲
- Rails為session提供了很多存儲機制,最重要的是ActiveRecordStore和CookieStore。
大多數實際生活的應用選擇ActiveRecordStore (或其衍生物)的文件存儲由于性能和維修的原因。 ActiveRecordStore保持session ID和散列在一個數據庫表,在每次請求里都保存和檢索這個hash。
Rails2介紹了一種新的session存儲機制, CookieStore. 它直接在客戶端的cookie里保存這個session hash。服務端從cookie里檢索這個session hash,無須session id。這將大大增加速度的應用,但它是一個有爭議的存儲選項,你必須思考安全的影響:
1.cookie意味著嚴格的大小限制,4k。 這點是好的,本身就不應該存儲大的數據在session里,前面也說過。存儲一個當前用戶的數據庫id一般是沒有問題的。
2.客戶端能看到你存儲在session里的一切。因為是明文的(實際是base64編碼的),所以,你別想在這里存儲任何秘密。為了防止session hash被篡改,會從服務端加一個secret到cookie的末尾。
這就意味著,這個安全存儲取決于這個scret(digest算法,默認是sha512,至今沒有被破解),所以不要用一個簡單的scret,例如字典里的一個單詞,或者比30個字符短的任意字符串。把這個scret放在environment.rb里:
config.action_controller.session = {
????:session_key => ‘_app_session’,
????:secret????????????=> ‘0x0dkfj3927dkc7djdh36rkckdfzsg...’
}
但是也有經過加密session hash的CookieStore派生存儲機制,為了客戶端不能看到它。
2.6?? 針對于CookieStore sessions的重放***
- 另一種必須要知道的***是針對于cookiestore***是重放***。
它的運作方式如下:
?1.用戶收到貸款,金額是儲存在一個session里,(這是壞主意,但是我們做這些只是示范)
?2.這個用戶買了一些東西
?3.他的new,lower credit將要被存儲在session里。
?4.邪惡的用戶得到了他的cookie并且覆蓋了當前的cookie。
?5.這個用戶有了他的credit, 就可以進行重放***了。
在session里加一個(nonce)暫時標志(隨機值)可以解決重放***這個問題。一個nonce僅有效一次,并且服務端保持對所有有效nonce的跟蹤,如果你有多個應用服務器,它可能甚至會更復雜,避免把nonce存儲在數據庫里,這樣會破壞整個CookieStore。
最好的解決方法是不要存放這種數據在session里,而是在數據庫里。這個例子,存儲credit在數據庫里,logged in user id 放在session里。
2.7 session 定制***
- 除了竊取用戶的session id,***者還可能去定制一個session id來偽裝,這就是所謂的session定制。
這個***的重點是定制一個用戶的可以識別他的session id,并且強制用戶的瀏覽器用這個id。因此后來***者也不需要去竊取一個session id了。來看看***是如何展開的:
1.***者創建一個有效的session id: 他登陸想定制session的那個web應用的登陸頁面,這時就通過response在cookie里有一個session id了(圖中的1,2)
2.他可能保持這次會話(session)。session是會過期的,比如每隔20分鐘,這會大大的減少了***者的時間。因此,他會不斷的訪問這個web應用以便于保持session可用。
3.現在,***者會強迫用戶來使用這個session id(看圖里的3),因為你不能改變另一個域的cookie,***者不得不在目標web應用里運行一個javascript腳本。通過往目標web應用注入javascript代碼來完成這次***。下面是一個例子:
??? <script>?document.cookie="_session_id=16d5b78abb28e3d6206b60f22a03c8d9";?</script>
4. ***者引誘受害人向被感染的網頁上的JavaScript代碼。通過查看網頁時,受害者的瀏覽器將把session id改變成***者定制好的session id。
5.因為這個陷進session id沒有被用,web應用會需要用戶去驗證。
6.從現在開始,受害者和***者都會共有一個相同的session在這個web應用里。此時受害者并沒有注意到這次***。
2.8? session 定制 --- 對策
- 一行代碼就保護你不被session定制侵害。
(我的這篇文章也寫了一些對策:[url]http://blackanger.blog.51cto.com/140924/91764[/url])
最有效的對策就是在成功登陸以后,創建一個新的session id,并且宣告舊的session id失效。那樣,***者就不能用固定的session id了。這是一個對方session劫持的好的對策。Rails里我們可以這樣來產生一個新的session:
reset_session
如果你用流行的rails插件,RestfulAuthentication,請在SessionsController#create action里加 reset_session.? 注意,這個行為消除了原session里存儲的所有值,你必須把這些值得轉移到新的session里。
另一個有效的對策是,在session里保存用戶的特定屬性,在每次請求進來的時候驗證他們,如果信息不匹配,則拒絕訪問。可以用遠程ip地址,或者是訪問瀏覽器名稱,盡管后者是不常用的。當保持ip的時候要注意,應該保持用戶真實ip,而不是互聯網服務供應商或大型組織的ip,如果這些變化以后,某些用戶可能無法使用這個web應用,或者會有限制。
2.9 session 過期
- 永不過期的session會更加方便這些session***。
session過期時間在服務端設置更加安全。下面是一個例子, 如何在數據庫里設置session的過期時間。如果超過20分鐘就調用Session.swap(20m):
class Session < ActiveRecord::Base
def self.sweep(time_ago = nil)
???????? time = case time_ago
???????????? when /^(\d+)m$/ then Time.now - $1.to_i.minute
???????????? when /^(\d+)h$/ then Time.now - $1.to_i.hour
???????????? when /^(\d+)d$/ then Time.now - $1.to_i.day
???????????? else Time.now - 1.hour
???????? end
???????? self.delete_all "updated_at < '#{time.to_s(:db)}'"
???? end
?end
這節講述了session定制需要保持連接。雖然你有過期時間,但***者也不傻, 他會保持每隔五分鐘使session可用,不過期。一個簡單的解決方法是,增加一個created_at到你的session表里。現在你可以刪除被創建了很久的那些session,用下面的這行替換上面swap方法的:
self.delete_all "updated_at < '#{time.to_s(:db)}' OR created_at < '#{2.days.ago.to_s(:db)}'"
--------翻譯分割線 ,翻譯的不好,請多多指正--------
Ruby On Rails? 安全導讀
這個指南描述的是在web應用里普遍的安全問題,同時也給出了在Rails里如何避免這些問題。如果你有任何問題,請mail作者,Heiko Webers, at 42 {et} rorsecurity.info.?? 讀完此文后,你應該會了解:
?1.所有的對策已經被高亮顯示了
?2.在Rails里session的概念, 該放什么在session里,以及一些流行的***方法
?3.只是瀏覽一個站點,怎么就有安全問題呢?(with CSRF)
?4.當你使用files或提供一個管理界面的時候需要注意些什么
?5.The Rails-specific mass assignment problem
?6.如何管理用戶:登陸,注銷以及對所有層面的***方法。
?7.以及最流行的注入***方法。
一? 介紹
web application框架幫助開發者建立種種web應用,某些框架在安全方面也幫你省心不少。事實上,一個框架并不比另一個安全。對于大多數的框架來說,如果你正確使用它,可以建立安全的應用。Ruby on Rails有許多聰明的helper方法,例如防止注入***的方法,這讓sql注入變成了困難的事情。很高興看到我審定的所有rails app都有一個良好的安全級別。
一般沒有這種即插即用的安全,安全依賴于正在使用的框架,有時候也依賴于開發方式。它取決于web應用的所有環境:后端存儲,網絡服務器和網絡應用程序本身(以及可能的其他層或應用程序) 。
Gartner組織估計大約75%的***都是在web應用,并且在300個調查的web應用里,97%都是容易被***的。這是因為web應用容易***,因為它們易于理解和操作,甚至是懶人。
在受到威脅的web應用中,包括用戶帳戶劫持,繞開訪問控制,閱讀或修改敏感數據,或出示虛假的內容。或***者可以安裝一個特洛伊***程序或不請自來的電子郵件發送軟件,目的是在金融活動或造成損害品牌名稱,修改公司的資源。為了防止***,最大限度地減少其影響和消除***點,首先,你必須充分了解***方法,以便找到正確的對策。這正是該指南的目的。
為了開發安全的Web應用你必須不斷更新的所有層次和了解你的敵人。要不斷更新訂閱的安全郵件列表,請閱讀安全博客,并更新和安全檢查的習慣。我手工做這些,因為這你才能找到討厭的合乎邏輯的安全問題。
二 Sessions
我們的安全之旅最好是從最易受到特別***的sessions開始。
2.1?? 什么是sessions
— HTTP is a stateless protocol Sessions make it stateful.
- HTTP是一個無狀態協議,Sessions使它有狀態。
大多數的應用需要對一個特別用戶的某些狀態進行跟蹤。比如,一個購物車的內容,一的當前登陸用戶的id,如果沒有sessions這個好主意,用戶必須在每一個請求都得去標識驗證身份。如果一個新用戶訪問這個應用,Rails會自動創建一個新的session。如果用戶之前使用過這個應用,它會自動加載一個存在的session。
一個session通常是一個hash和一個session id(通常是一個32個字符的字符串)來標識這個hash。Rails里你可以用如下方式保存和使用session:
session[:user_id] = @current_user.id
User.find(session[:user_id])
2.2? session id
— The session id is a 32 byte long MD5 hash value.
- session id就是個一32位的md5 hash值。
一個session id由一個隨機字符串的hash值組成。這個隨機字符串是當前的時間,一個0和1之間的隨機數字,一個ruby解釋器進程id數字和一個常量字符串組成。
2.3? session劫持
- 竊取用戶session id的***者可以在一個web應用里使用受害者的名字。
許多web應用都有一個驗證系統:一個用戶提供一個用戶名和密碼,web應用檢查并且存儲相應的user id到session的這個hash里。從現在開始,session是有效的。在每個http請求里, 應用會加載這些在session里用user id來標識的用戶,并不需要新的驗證。這個session id是放在cookie里用來標識這個session的。
因此cookie作為web應用的臨時驗證。任何人得到一個別人的cookie,他就可以偽裝為這個人使用對應的web應用-可能會有嚴重的后果。這里有一些session劫持的方法,以及對策:
1.在不安全的網絡進行嗅探cookie。無線局域網就是這樣一個例子。在這樣的一個網絡里,特別容易去監聽所有鏈接的客戶端, 這就是不去咖啡店工作的原因(某些sb就喜歡去星巴克打開本本裝比)。對于web應用開發者,這就意味著去提供一個安全的ssl連接。
2.大多數的人在公共場所工作之后不清除cookie,所以如果是最后一個沒有在web應用注銷的用戶,你有可能偽裝成這個用戶。在web應用里提供給用戶一個注銷按鈕,并且放在醒目的位置。
3.許多跨站點腳本( XSS )***的目的是獲得用戶的cookie 。你之后會看到關于xss的更多內容。
4.Session定制,之后會讀到.
大多數***者的目的是為了錢,失竊的銀行登陸帳號的價格范圍從$10 - $1000不等(取決于可用的資金數額),信用卡號碼是$0.40-$20,在線拍賣網站的帳號為$1-$8,email密碼為$4-$30 ,參考賽門鐵克的網絡安全威脅報告。
2.4 session 準則
-這里有一些session的一般準則
1.不要在session里存儲大的對象。相反,你應該把它們存儲在數據庫里,把它們的id保存在session里。這將消除同步的麻煩,而且也不會占用你session的存儲空間(取決于你選擇的session的存儲)
2.關鍵的數據不應該被存儲在session里。如果用戶清除了cookie或者關閉了瀏覽器,它們都將丟失,用一個客戶端session存儲,用戶可以讀取數據。
2.5 session存儲
- Rails為session提供了很多存儲機制,最重要的是ActiveRecordStore和CookieStore。
大多數實際生活的應用選擇ActiveRecordStore (或其衍生物)的文件存儲由于性能和維修的原因。 ActiveRecordStore保持session ID和散列在一個數據庫表,在每次請求里都保存和檢索這個hash。
Rails2介紹了一種新的session存儲機制, CookieStore. 它直接在客戶端的cookie里保存這個session hash。服務端從cookie里檢索這個session hash,無須session id。這將大大增加速度的應用,但它是一個有爭議的存儲選項,你必須思考安全的影響:
1.cookie意味著嚴格的大小限制,4k。 這點是好的,本身就不應該存儲大的數據在session里,前面也說過。存儲一個當前用戶的數據庫id一般是沒有問題的。
2.客戶端能看到你存儲在session里的一切。因為是明文的(實際是base64編碼的),所以,你別想在這里存儲任何秘密。為了防止session hash被篡改,會從服務端加一個secret到cookie的末尾。
這就意味著,這個安全存儲取決于這個scret(digest算法,默認是sha512,至今沒有被破解),所以不要用一個簡單的scret,例如字典里的一個單詞,或者比30個字符短的任意字符串。把這個scret放在environment.rb里:
config.action_controller.session = {
????:session_key => ‘_app_session’,
????:secret????????????=> ‘0x0dkfj3927dkc7djdh36rkckdfzsg...’
}
但是也有經過加密session hash的CookieStore派生存儲機制,為了客戶端不能看到它。
2.6?? 針對于CookieStore sessions的重放***
- 另一種必須要知道的***是針對于cookiestore***是重放***。
它的運作方式如下:
?1.用戶收到貸款,金額是儲存在一個session里,(這是壞主意,但是我們做這些只是示范)
?2.這個用戶買了一些東西
?3.他的new,lower credit將要被存儲在session里。
?4.邪惡的用戶得到了他的cookie并且覆蓋了當前的cookie。
?5.這個用戶有了他的credit, 就可以進行重放***了。
在session里加一個(nonce)暫時標志(隨機值)可以解決重放***這個問題。一個nonce僅有效一次,并且服務端保持對所有有效nonce的跟蹤,如果你有多個應用服務器,它可能甚至會更復雜,避免把nonce存儲在數據庫里,這樣會破壞整個CookieStore。
最好的解決方法是不要存放這種數據在session里,而是在數據庫里。這個例子,存儲credit在數據庫里,logged in user id 放在session里。
2.7 session 定制***
- 除了竊取用戶的session id,***者還可能去定制一個session id來偽裝,這就是所謂的session定制。
這個***的重點是定制一個用戶的可以識別他的session id,并且強制用戶的瀏覽器用這個id。因此后來***者也不需要去竊取一個session id了。來看看***是如何展開的:
1.***者創建一個有效的session id: 他登陸想定制session的那個web應用的登陸頁面,這時就通過response在cookie里有一個session id了(圖中的1,2)
2.他可能保持這次會話(session)。session是會過期的,比如每隔20分鐘,這會大大的減少了***者的時間。因此,他會不斷的訪問這個web應用以便于保持session可用。
3.現在,***者會強迫用戶來使用這個session id(看圖里的3),因為你不能改變另一個域的cookie,***者不得不在目標web應用里運行一個javascript腳本。通過往目標web應用注入javascript代碼來完成這次***。下面是一個例子:
??? <script>?document.cookie="_session_id=16d5b78abb28e3d6206b60f22a03c8d9";?</script>
4. ***者引誘受害人向被感染的網頁上的JavaScript代碼。通過查看網頁時,受害者的瀏覽器將把session id改變成***者定制好的session id。
5.因為這個陷進session id沒有被用,web應用會需要用戶去驗證。
6.從現在開始,受害者和***者都會共有一個相同的session在這個web應用里。此時受害者并沒有注意到這次***。
2.8? session 定制 --- 對策
- 一行代碼就保護你不被session定制侵害。
(我的這篇文章也寫了一些對策:[url]http://blackanger.blog.51cto.com/140924/91764[/url])
最有效的對策就是在成功登陸以后,創建一個新的session id,并且宣告舊的session id失效。那樣,***者就不能用固定的session id了。這是一個對方session劫持的好的對策。Rails里我們可以這樣來產生一個新的session:
reset_session
如果你用流行的rails插件,RestfulAuthentication,請在SessionsController#create action里加 reset_session.? 注意,這個行為消除了原session里存儲的所有值,你必須把這些值得轉移到新的session里。
另一個有效的對策是,在session里保存用戶的特定屬性,在每次請求進來的時候驗證他們,如果信息不匹配,則拒絕訪問。可以用遠程ip地址,或者是訪問瀏覽器名稱,盡管后者是不常用的。當保持ip的時候要注意,應該保持用戶真實ip,而不是互聯網服務供應商或大型組織的ip,如果這些變化以后,某些用戶可能無法使用這個web應用,或者會有限制。
2.9 session 過期
- 永不過期的session會更加方便這些session***。
session過期時間在服務端設置更加安全。下面是一個例子, 如何在數據庫里設置session的過期時間。如果超過20分鐘就調用Session.swap(20m):
class Session < ActiveRecord::Base
def self.sweep(time_ago = nil)
???????? time = case time_ago
???????????? when /^(\d+)m$/ then Time.now - $1.to_i.minute
???????????? when /^(\d+)h$/ then Time.now - $1.to_i.hour
???????????? when /^(\d+)d$/ then Time.now - $1.to_i.day
???????????? else Time.now - 1.hour
???????? end
???????? self.delete_all "updated_at < '#{time.to_s(:db)}'"
???? end
?end
這節講述了session定制需要保持連接。雖然你有過期時間,但***者也不傻, 他會保持每隔五分鐘使session可用,不過期。一個簡單的解決方法是,增加一個created_at到你的session表里。現在你可以刪除被創建了很久的那些session,用下面的這行替換上面swap方法的:
self.delete_all "updated_at < '#{time.to_s(:db)}' OR created_at < '#{2.days.ago.to_s(:db)}'"
總結
以上是生活随笔為你收集整理的Rails安全导读【一】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第2本书:CCIE Practical
- 下一篇: [蛋蛋の插画日记]囧...居然漏了一期《