2015-04-07 75 views
2

我有一個應用程序向用戶發送電子郵件,每封電子郵件都包含用戶必須訪問的頁面的鏈接。如何使此登錄/重定向方法更安全

該鏈接是唯一ID +隨機數的md5。

鏈接看起來像:www.domain.com/index.php?id_page=<the md5>

在索引頁我保存$_GET["id_page"]會話變量中,$_SESSION["id_page"]我將用戶重定向到頁面,他必須看到(用戶被重定向到該頁面只有當該鏈接包含id_page)。

如何改進此方法並使其更安全?我如何保證用戶進入指定給他們的頁面 - 並且不能進入任何其他頁面?

+0

他們在查看該頁面時是否已登錄? – ambe5960

+0

你特別擔心什麼樣的利用/規避? – Harvtronix

+0

@ ambe5960是的,登錄過程發生在它們被重定向到相應的頁面之前。該過程類似於:登錄 - >驗證鏈接是否包含id_page - >如果它確實將用戶重定向到相應的頁面 –

回答

1

你在這裏關心的是一個時間問題,而不是安全問題:)。如果你允許任何人猜測無限數量的id_page值,那麼給予足夠的時間,最終有人會發生隨機有效的id_page值。

您唯一的real針對此問題的防範是增加您的散列長度,導致它需要(平均)更多的時間在隨機有效的id_page(大約幾個月或幾年)上發生。這可以通過使用sha256或sha512而不是md5來完成。

另一種方法是將某人鎖定一段時間,例如,如果他們有一個id_page值連續錯誤3次猜測。這將大大減少它們在給定時間段內嘗試的值的數量。

最後,如果用戶在重定向時已經登錄,那麼您還可以將生成的散列存儲在數據庫表中。這樣你就可以將一個特定的散列映射到表中的一個userid。如果用戶試圖訪問他們在數據庫中不對應的哈希頁面,那麼您可以將它們重定向到其他地方。

1

您可以在URL中添加他們的電子郵件。有人猜測別人的電子郵件和相關散列的概率僅爲0.

1

一種可以很好地防止猜測ID號的方法是向ID添加某種填充,然後將其轉換爲base32。當然,這並不能消除完全猜測身份的能力,但對於任何正在窺探的人來說,這確實會讓它更費時。

如果有網址www.domain.com/index.php?id_page=1,您可以將ID轉換的東西在你的應用程序唯一的,例如:

填充ID = ID×9 - 2

7 = 1 x 9 - 2 
16 = 2 x 9 -2 
25 = 3 x 9 - 2 

然後,你可以轉換新的填充ID到基座32,這將是

7 = G4 
16 = GE3A 
25 = GI2Q 

新的URL將被(爲1一個id ):

www.domain.com/index.php?id_page = G4

使用這種方法,如果有人猜測1-6的基數32,它將返回404,因爲你的ID爲1實際上被填充爲7,猜測8-15不會返回一個解析的ID,因爲2的下一個ID填充爲16,依此類推。

這不僅使查詢字符串的大小更小,而且它也不使用明顯的MD5哈希,它可以非常容易地按字典順序瀏覽。

如果您希望將頁面鏈接到特定的用戶,那麼沒有理由不能將更多值添加到新的padded_id(我們稱之爲散列)。

例如,如果您有一個ID爲12的用戶,並且您只希望該用戶能夠訪問ID爲10的頁面,則需要創建一個包含這兩個值的散列:

PAGE_ID(10)-user_id(12),使用上述示例中,這將產生:

(10 x 9 - 2) (12 x 9 - 2) 
88-106 
HA4A-GEYDM 

現在具有可以固定到一個單一的用戶ID的漂亮的小散列鏈接。上述示例中的填充方法相當簡單,但它提供瞭如何解決問題的總體思路。

1

不要打擾哈希或創建唯一的ID或任何東西。複雜性不會幫助你。

而是簡單地生成一個隨機令牌,然後使用它。一個256位隨機令牌應該足以滿足你需要做的任何事情。

因此,使用mcrypt(核心擴展名):

$token = strtr(
    base64_encode(mcrypt_create_iv(256/8, MCRYPT_DEV_URANDOM)), 
    '+/', 
    '-_' 
); 

這會給你包含隨機熵的256位字母a-zA-Z0-9-_的44字符的結果。

沒有必要散列結果或任何東西。隨機數據就夠了。

要理解爲什麼,您需要了解The Birthday Problem

基本上用一個256位的隨機值,有2%的機會碰撞2個標記,你需要生成4.8e37個標記(48個,後面36個0)。

爲了獲得10e-18的碰撞機會(通常被認爲是安全的),您需要生成4.8e29令牌。

由於這些數字比您曾經產生過的數量更多,因此2個令牌碰撞的機會無限小。

另一個問題是人們猜測令牌。那麼,MCRYPT_DEV_URANDOM使用底層操作系統的隨機池。這意味着人們更有可能猜出你的「唯一的ID和隨機數」,而不是猜測這裏產生的令牌。

因此,簡而言之,只需使用隨機令牌並完成:-)