播放关于cookie和session框架安全问题(Play framework security i

2019-09-02 17:44发布

对于我的应用我采取相同的安全如图所示zentask。

public class Secured extends Authenticator {

@Override
public String getUsername(Context ctx) {
    return ctx.session().get("email");

}

@Override
public Result onUnauthorized(Context ctx) {
    ctx.flash().put("error", "please login to proceed");
    return redirect(routes.Application.index());
}

}

当用户通过验证isuser session().put("email", email) ;

我有两个问题。 首先:当用户离开应用程序,而无需使用注销你如何失效的会话? 第二个更严重的是,我使用的Firefox插件检查饼干cookies manager+ ,我可以复制一个cookie,后来粘贴这样我可以访问方法,而无需首先登录,基本上我可以窃取会话

Answer 1:

玩框架使用无状态的会话。 没有存储在服务器端的状态,而所有的状态存储在会话cookie。 为了验证会话,播放签名使用密钥对会话,并且当与一个会话cookie的请求到达验证签名。 如果用户是与会话,篡改数据,例如,如果他们在会议到别人的邮箱地址被更改的电子邮件地址,那么签名将不匹配等起到将拒绝会话cookie。

是的,你可以复制的cookie,并在以后使用。 但是你不能更改cookie。 这意味着你可以“偷”是自己唯一的cookie,而是从自己偷是不是真的偷窃。 所以,不,你不能偷的会议,除了通过利用其他漏洞,如XSS,但会话令牌很容易受到这件事的。

默认情况下,播放被配置为创建“会话”饼干,也就是说,当你关闭浏览器的cookie到期。 因此,如果用户退出了他们的浏览器,浏览器会删除所有的会话cookie,用户将不会在再登录。 这是会话令牌相同。

还有一个考虑是知道的,那就是会话令牌还服务器上到期,因为服务器保存状态。 无状态会话签署,如在游戏中使用,不要。 但是,你可以实现自己的到期机制,通过存储时间戳会话内创建时,并验证该时间戳不比在getUsername()方法配置的到期时间更旧。 由于时间戳存储在会话中,这是签署,时间戳不能与不改变签名篡改,所以这种简单的机制是相当安全的。 更先进的解决方案可能是实现每一个请求进来的时候更新了时间戳的过滤器,从而使过期可以基于最后一次访问,而不是当用户登录。



Answer 2:

你的假设是完全正确的,你不能按照Zentask例如在服务器上无效的会话。 虽然会话cookie与配置文件中的私钥签名,相同的值产生相同的签署的cookie。 正如你已经想通了,如果有人偷了从用户既没有用户,也没有你(服务器)的cookie可以防止小偷从“登录到”用户帐户。

基本上有两种选择现在:

  1. 商店,你已经有关于在只有你和用户知道和不定期更改cookie中的用户信息的波动。 一个例子是密码哈希的一部分。 一旦用户更改密码时,信息不再有效,并且所有旧的会话cookie是无效的。 这种方法的一个缺点:如果用户不改变存储的信息,该cookie的有效期过了很久​​,甚至永远。
  2. 创建一个服务器端的会话管理。 对于这一点,你必须有一个数据库,一个键值缓存或类似的东西。 在那里你存储会话,用户名/ ID和当该会话将被自动失效之日起随机生成的(加密保护)键。 您还可以将IP地址,以提高对cookie的盗窃的安全性。 然后,会话密钥必须被写入cookie中。 当用户点击退出按钮你无效当前会话(或可替代所有会话该用户)。


Answer 3:

在cookie中简单地把用户ID是不是安全的。 正如你所指出的,任何人都可以创造一个cookie的值。

会议:相反,你需要把任意的(例如,随机)值在cookie中,然后在服务器上查找用户的身份映射表。 将任意值必须经常改变,所以你通常有一个登录会话持久,比方说,30分钟。 每个登录提供了一种新的任意值,并且该值被称为会话ID。

无效:会话通过去除从所述查找表中的一段时间内,没有任何请求(例如30分钟)后该条目(在服务器端)无效。 与会话ID不在表中的任何要求,将被视作未认证的请求,并再次提示登录。 如果用户忘记退出没关系。

黑客:由于该值是任意的,没有办法黑客事先知道未来的会话ID是什么。 你仍然受到会话偷窃,但它是更难:黑客只有在正在使用它的时间来寻找一个会话ID,然后可以用它仅适用于一定的时间。 你可以采取一些措施来防止这种情况,如特定会话来自一个特定的IP地址只允许请求。 您还可以快速循环的会话ID,甚至每一个要求,但也有负两侧。 在一般情况下,提供了一个独特的会话ID为每个登录,特别是当这是通过HTTPS完成的,对于大多数的身份认证需求不够好。

持久性:如果并发用户的数量超过任何给定的会议时间(如30分钟)较小,则不一定需要把这个数据库中。 在内存中保持这种低开销,但有一个缺点,如果你重启服务器,所有用户需要重新登录。 如果你把会话ID在数据库中,你需要确保当服务器启动时,它可以清理掉所有的旧会话。

用户信息:目前仍然是一个价值的把用户的电子邮件地址在cookie中,但只用作“默认”用户ID登录为。 这应被视为仅仅是为了方便用户,而不是作为一个指示用户被认证。



Answer 4:

  • 我建议有一个模块,这将产生会话ID为您服务。 在这个模块中,你可以有一个像createSessionId()或某种东西的方法。 生成会话ID的逻辑您将这个方法。

  • 我想创建的会话ID为(用户ID + providerId(脸谱/谷歌式的情况下的OAuth / UsernamePassword /任何提供商)+当前时间戳+ UUID)的组合,创造这个会话ID之后,我将与一些算法加密。 这会给我的会话ID

  • 优势与这将是:

    • 虽然产生的会话ID需要一定的时间,没有身体会使它的意义。
    • 另一个好处是,你可以更改createSessionId随时创建会话ID()方法,你的加密逻辑/策略 。

  • 在Playframework会议的另一个问题是没有过期的会话:
    • 为了解决这个问题,只要用户登录时,我们可以在会话即只是在饼干(通过加密可能?)存储时间戳
    • 现在,在会话的每个请求检查时间戳。 如果时间戳大于说30分钟的时候,无效的会话。 如果时间戳不大于30分钟时,更新会话时间戳作为当前时间戳


文章来源: Play framework security issue regarding cookies and sessions