这与another question I asked有关。总而言之,我有一个URL的特殊情况,当一个表单发布到它时,我不能依赖cookie进行身份验证或维护用户的会话,但我不知何故需要知道他们是谁,我需要知道他们已经登录了!
我想我想出了解决问题的方法,但需要充实。这就是我在想的。我创建一个名为“username”的隐藏表单字段,并在其中放置用户的用户名加密。然后,当表单POST时,即使我没有从浏览器收到任何cookie,我知道他们已经登录,因为我可以解密隐藏的表单字段并获取用户名。
我能看到的主要安全漏洞是重播攻击。如何阻止某人获取该加密字符串,并以该用户身份进行POST?我知道我可以使用SSL来更难以窃取该字符串,也许我可以定期轮换加密密钥来限制字符串有用的时间,但我真的很想找到一个防弹解。有人有什么想法吗? ASP.Net ViewState是否阻止重播?如果是这样,他们是如何做到的?
编辑:我希望解决方案不需要存储在数据库中的任何内容。应用程序状态是可以的,除了它将无法在IIS重新启动或在Web场或园林场景中完全工作。我现在接受克里斯的回答,因为我不相信它甚至可以在没有数据库的情况下保证这一点。但如果有人想出一个不涉及数据库的答案,我会接受它!
答案 0 :(得分:13)
如果您确实不想存储任何状态,我认为您可以做的最好的事情是使用时间戳和短暂的到期时间来限制重播攻击。例如,服务器发送:
{Ts,U,HMAC({Ts,U},Ks)}
其中Ts是时间戳,U是用户名,Ks是服务器的密钥。用户将其发送回服务器,服务器通过重新计算提供的值上的HMAC来验证它。如果它有效,你就会知道它何时发出,并且如果比它早5分钟就可以选择忽略它。
此类开发的良好资源是The Do's and Don'ts of Client Authentication on the Web
答案 1 :(得分:13)
如果您使用用户名和密码在时间戳中哈希,则可以在几秒钟内关闭重播攻击窗口。我不知道这是否符合您的需求,但它至少是部分解决方案。
答案 2 :(得分:11)
这里有几个很好的答案,把它们放在一起就是答案最终的答案:
阻止密码加密(使用AES-256 +)和散列(使用SHA-2 +)发送到客户端的所有状态/随机数相关信息。否则黑客只是操纵数据,查看它以学习模式并规避其他一切。请记住......它只需要一个打开的窗口。
为每个请求生成一次性随机且唯一的随机数,并通过POST请求发回。这样做有两件事:它确保POST响应符合THAT请求。它还允许跟踪一组给定的get / POST对的一次性使用(防止重放)。
使用时间戳使nonce池可管理。按照上述#1将时间戳存储在加密的cookie中。丢弃任何早于应用程序最长响应时间或会话的请求(例如,一小时)。
存储"相当独特的"使用加密时间戳数据发出请求的机器的数字指纹。这将阻止攻击者窃取客户端cookie以执行会话劫持的另一个技巧。这将确保请求不仅返回一次,而是从机器返回(或者足够接近以使攻击者几乎不可能复制),表单已被发送到。
基于ASPNET和Java / J2EE安全过滤器的应用程序可以完成上述所有操作,无需编码。如果性能至关重要,那么管理大型系统的nonce池(如股票交易公司,银行或高容量安全站点)并非易事。建议查看这些产品,而不是尝试为每个Web应用程序编程。
答案 3 :(得分:4)
您可以使用与用户名一起使用的某种随机挑战字符串来创建哈希。如果您将挑战字符串存储在数据库中的服务器上,则可以确保它仅使用一次,并且仅针对一个特定用户。
答案 4 :(得分:2)
在我的一个停止'重播'攻击的应用中,我已将IP信息插入到我的会话对象中。每次我在代码中访问会话对象时,请确保使用它传递Request.UserHostAddress,然后进行比较以确保IP匹配。如果他们没有,那么显然除了这个人之外的其他人提出了这个请求,所以我返回null。这不是最好的解决方案,但至少还有一个阻止重播攻击的障碍。
答案 5 :(得分:1)
您是否可以使用内存或数据库来维护有关用户或请求的任何信息?
如果是这样,那么在请求表单时,我会包含一个隐藏的表单字段,其内容是随机生成的数字。在呈现请求时,将此标记保存到应用程序上下文或某种存储(数据库,平面文件等)中。提交表单时,请检查应用程序上下文或数据库,以查看该随机生成的数字是否仍然有效(但是您定义的有效 - 也许它可以在X分钟后过期)。如果是这样,请从“允许令牌”列表中删除此令牌。
因此,任何重播的请求都将包含在服务器上不再被视为有效的相同令牌。
答案 6 :(得分:1)
我是网络编程的某些方面的新手,但我前几天正在阅读这篇文章。我相信你需要使用Nonce。
答案 7 :(得分:1)
(重播攻击很容易就是IP / MAC欺骗,加上你对动态IP的挑战)
这不仅仅是重播你在这里,孤立无知。只需使用SSL并避免手工制作任何东西..
ASP.Net ViewState是一团糟,避免它。虽然PKI是重量级和臃肿的,但至少它不会发明你自己的安全“方案”。所以,如果可以的话,我会使用它,并始终寻求相互认可。仅服务器验证是没用的。
答案 8 :(得分:1)
ViewState包含安全功能。有关ASP.NET中的一些内置安全功能,请参阅this article。它对服务器上的machine.config中的服务器machineKey进行验证,确保每个回发都有效。
Further down in the article,您还会看到,如果要将值存储在自己的隐藏字段中,可以使用LosFormatter
类对ViewState用于加密的方式进行编码。
private string EncodeText(string text) {
StringWriter writer = new StringWriter();
LosFormatter formatter = new LosFormatter();
formatter.Serialize(writer, text);
return writer.ToString();
}
答案 9 :(得分:0)
如果您只接受每个密钥一次(例如,将密钥设为GUID,然后检查它何时返回),则会阻止重放。当然,如果攻击者首先回应,那么你就会遇到新的问题......
答案 10 :(得分:0)
这是WebForms还是MVC?如果是MVC,您可以使用AntiForgery令牌。这似乎与您提到的方法类似,除了它基本上使用GUID并使用该帖子的guid值设置cookie。有关更多内容,请参阅Steve Sanderson的博客:http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/
另一件事,您是否考虑过在回发时检查推荐人?这不是防弹,但可能有所帮助。
答案 11 :(得分:0)
使用https ...它内置了重放保护。