2015-04-07 76 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和随机数”,而不是猜测这里产生的令牌。

因此,简而言之,只需使用随机令牌并完成:-)