2010-03-29 70 views
6

我正在編寫自己的會話控制器,它在登錄後向用戶發出唯一的ID,然後在每次加載頁面時驗證並驗證該唯一ID。什麼是最安全的方式來生成這樣的ID?該獨特的ID應該完全隨機?將用戶ID作爲唯一ID的一部分包含在內是否有缺點?最安全的方式來爲cookie生成隨機會話ID?

+1

將用戶標識作爲唯一標識的一部分使用時,會從整個「隨機」事物中取走。即使它不公開,也會有更多一致的數字提供給同一用戶,這是不太安全的。 – 2010-03-29 22:46:04

回答

4

如果cookie中唯一的信息是一個標識符,本質上就是一個標籤,你試圖保護的唯一攻擊是攻擊者猜測它是什麼。所以使用一些隨機字節。足夠的隨機字節,它是「不可猜測的」。

然後將隨機字節擠成適合您可以在HTTP Cookie中使用的字符範圍內的內容。 base64爲此工作。這不是絕對最佳的,因爲有超過64個cookie安全字符,並且往往會留下尾隨==字符,這些字符會將字節添加到標題中,但不是隨機性,但這很好。它的工作原理和Python可能比我們能想到的任何其他方式更快地完成base64編碼。

如果您還希望將用戶標識添加到該標識中,那將更容易進行跟蹤和調試,這可能會讓您的生活更輕鬆,因此請繼續。它不會給攻擊者任何顯着的優勢。 (除非他們設法偷取一個,否則他們無法確定他們偷了哪些用戶,這看起來不太可能。)

+3

使100%確定cookie *永遠不會超過純HTTP;如果可以攔截,「不可猜測」不再是一個因素。再次,我建議在這個話題上做一些真正的閱讀...... – retracile 2010-03-30 01:21:38

+1

很大程度上屬實。但是世界上只有一小部分人能夠攔截數據包。而你可以在世界的任何地方使用一個完整的僵屍網絡來猜測。但是,是的,如果你不想讓任何人使用一個安全性較差的wifi熱點,請獲取HTTPS和有效的證書。 但是,這些對cookie的生成沒有任何特別的影響。 – keturn 2010-03-30 02:25:27

-1

的最佳方式將generate a UUID,使用uuid.uuid1功能:

生成從主機ID,序列號,和當前時間的UUID。

+0

這是腳本運行的機器的主機ID嗎?或者連接用戶?如何指定主機ID?謝謝。 – ensnare 2010-03-29 22:54:01

+3

具有恆定的因素(如主機ID)或可預測的因素(如序列號)不是您想要的此應用程序。根據實施情況,uuid.uuid4可能更合適。此外,UUID是以十六進制表示的字符串,如果您使用更廣泛的字符,則可以更多地使用每字節熵。 – keturn 2010-03-30 00:24:51

4

在2.5和更高版本中使用UUID模塊。這樣他們不能被猜測,因爲他們不是連續的。如果你想讓它們變得非常安全,你可以用它們的用戶id來標記它們,然後用SHA1對它們進行哈希處理,Base64對結果進行編碼,然後用它作爲值。通過這種方式,您可以在服務器端驗證它們確實是您的Cookie,而不僅僅是某些垃圾郵件發送者正在生成並拋出服務器的內容。爲了使它們更安全,請確保它們只在服務器和客戶端上保持一段時間。 Python 2.6.5內置了HMAC實現,您也可以在生成的UUID上使用它。

+0

你如何做這個散列的服務器端驗證?那又是什麼讓你買了?這似乎是一個錯誤複雜的方式來提出一些隨機字節。 – keturn 2010-03-30 00:33:14

+3

使用HMAC允許服務器驗證它是否生成隨機值,而不必存儲該隨機值。它還可以包含時間戳以允許令牌到期,並且客戶端無法修改該時間戳而不使HMAC無效。這*更復雜,但允許您在不碰到數據庫的情況下驗證該令牌。 – retracile 2010-03-30 01:04:43

+2

我也許應該提到,在HMAC的情況下,隨機值只需要是一個隨機數。但是,這就是書的目的所在 - 它比我所能做到的要好得多。 :) – retracile 2010-03-30 01:27:53

7

去購買布魯斯·施奈爾的Secrets and Lies和他的Practical Cryptography。繼續前進,然後點你羅斯安德森的Security Engineering 2nd Ed.。現在,閱讀祕密和謊言 - 相信我,這是一個有趣的閱讀。 :)然後閱讀Practical Cryptography。此時,您應該更好地理解在實施需要某種安全性的軟件時需要執行的操作。繼續做你的草稿實施。現在你的安全工程的副本已經到來,請閱讀它...雖然你可能想慢慢消化它,這是一個相當沉重的約書。

還有一個whitepaper on web authentication dos and don'ts這是值得閱讀和更直接適用於你在做什麼。我仍然推薦上面的書。

another timely article from LWN.net其中列出了許多您需要避免的陷阱。 (順便說一句,LWN.net非常值得訂閱,我強烈推薦它。上面的鏈接允許免費訪問該文章,否則該文章將不會提供給非用戶)。

4

可以使用os.urandom

os.urandom(N)

返回的適於密碼使用n個隨機字節的字符串。

該函數從OS特定的隨機源中返回隨機字節。 返回的數據對於加密應用程序來說應該是不可預知的,儘管它的確切質量取決於實施的操作系統 。在類UNIX系統上,它將查詢/ dev/urandom, ,在Windows上它將使用CryptGenRandom。如果沒有找到隨機性來源 ,則會引發NotImplementedError。

版本2.4中的新功能。

+1

請注意,這會返回隨機的「字節」,而不是字符。您可能想要通過[base64.b64encode](https://docs.python.org/3/library/base64.html#base64.b64encode)運行結果並將其用作會話ID。 – WhyNotHugo 2015-05-01 14:42:12

0

http://docs.python.org/2/library/random.html

「警告:本[隨機]模塊的僞隨機生成不應該用於安全目的,如果你需要加密安全僞隨機使用os.urandom()或SystemRandom。號碼發生器「。

「os.urandom函數從特定於操作系統的隨機源中返回隨機字節返回的數據對於加密應用程序來說應該是不可預知的,儘管它的確切質量取決於操作系統的實現。/dev/urandom,並且在Windows上它將使用CryptGenRandom()。如果沒有找到隨機數,則會產生NotImplementedError。

對於一個易於使用的平臺提供的隨機數生成器接口,請參閱random.SystemRandom。「

0

我會完全避免隨機因素。我通常做的是:

  • 生成連續session_id(我本地存儲)。
  • 當用戶登錄時,用一個私鑰對session_id簽名(我爲此使用itsdangerous)。
  • 當我收到請求時,如果session_id的簽名完好無損,我繼續,否則,403(400也有意義)。

請注意,我在本地存儲session_id,因爲我希望能夠提前結束會話。

如果你的會議總是最後一個固定的時間量,而你並不需要過早結束這些,你可以簡單地籤user_id + datetime.now()。這允許完全無狀態的會話管理。

1

如果你正在使用Python 3.6及更高版本,可以使用新的庫secrets

from secrets import token_urlsafe 

token = token_urlsafe(64) # something like Drmhze6EPcv0fN_81Bj-nA....