2008-09-04 157 views
16

这与another question I asked相关。总之,我有一个URL的特例,当一个表单发布给它时,我不能依靠Cookie来进行身份验证或维护用户的会话,但我需要知道他们是谁,而且我需要知道他们已经登录!如何防止重播攻击?

我想我想出了一个解决我的问题,但它需要充实。这就是我的想法。我创建了一个名为“username”的隐藏表单域,并在其中放置用户的用户名,加密。然后,当表单POST时,即使我没有收到来自浏览器的任何cookies,我知道他们已经登录,因为我可以解密隐藏的表单字段并获取用户名。

我能看到的主要安全漏洞是重播攻击。如何阻止某人获取该加密字符串,并以该用户的身份进行发布?我知道我可以使用SSL来窃取该字符串,也许我可以定期旋转加密密钥,以限制字符串适合的时间长度,但我真的很想找到防弹解。任何人有任何想法? ASP.Net ViewState是否阻止重放?如果是这样,他们是如何做到的?

编辑:我希望有一个解决方案,不需要存储在数据库中的任何东西。应用程序状态是可以的,除非它不能在IIS重新启动或在Web场或花园场景中工作。现在我接受克里斯的回答,因为我不相信甚至可以在没有数据库的情况下保证这一点。但如果有人想出一个不涉及数据库的答案,我会接受它!

回答

13

如果哈希与用户名和密码的时间标记,你可以关闭的重放攻击窗口几秒钟之内。我不知道这是否符合您的需求,但至少是部分解决方案。

+0

我问这个问题后,我实际上决定做这件事。伟大的思想家都认为一样:) – 2008-09-21 02:55:54

+0

请注意,如果时间戳/ cookie未加密或者在用户代理层可以进行欺骗,那么这对黑客只会操纵时间戳值无效。 – 2014-07-21 18:37:04

4

您可以使用某种与用户名一起使用的随机挑战字符串来创建散列。如果您将挑战字符串存储在服务器上的数据库中,那么您可以确保它仅使用一次,并且仅限于一个特定用户。

0

如果您只接受一次每个密钥(例如,将密钥设为GUID,然后检查它何时返回),则会阻止重放。当然,如果攻击者回应第一个,那么你有一个新问题...

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/

另一件事,您是否考虑在回发中检查引用链接?这不是防弹的,但可能有帮助。

+0

该问题指出,他不能依靠cookie进行身份验证。 MVC Anti-Forgery令牌实际上依赖于cookie,因此这不太可能适用于问题的场景。此外,我们应该小心“重播攻击”的含义 - 防伪令牌旨在防止CSRF攻击。重播攻击可能以各种方式出现 - 包括来自初始用户的攻击 - 在这种情况下,防伪标记将毫无用处。 – Nathan 2009-05-06 22:18:32

1

你可以使用内存或数据库来维护关于用户或请求的任何信息吗?

如果是这样,那么在请求表单时,我会包含一个隐藏表单域,其内容是一个随机生成的数字。请求呈现时,将此令牌保存到应用程序上下文或某种存储(数据库,平面文件等)中。提交表单时,检查应用程序上下文或数据库以查看该随机生成的数字是否仍然有效(但是,您定义的有效 - 也许它可能会在X分钟后过期)。如果是这样,请从“允许令牌”列表中删除此令牌。

因此,任何重播的请求都会包含此服务器上不再认为有效的相同令牌。

1

我对网络编程的某些方面很陌生,但前几天我正在阅读。我相信你需要使用Nonce

13

如果你真的不想存储任何状态,我认为你可以做的最好的事情是通过使用时间戳和短的到期时间来限制重放攻击。例如,服务器发送:

{TS,U,HMAC({TS,U},KS)}

Ts是时间戳,U是用户名,和KS是服务器的密钥。用户将其发送回服务器,服务器通过在提供的值上重新计算HMAC来验证它。如果它是有效的,你知道它何时发布,并且如果它比5分钟更早,可以选择忽略它。

一个很好的资源,这种类型的开发The Do's and Don'ts of Client Authentication on the Web

2

在我的一个停止“重放”攻击的应用程序中,我已将IP信息插入到会话对象中。每次我在代码中访问会话对象时,都要确保通过Request.UserHostAddress,然后比较以确保IP匹配。如果他们不这样做,那么显然有人提出这个请求,所以我返回null。这不是最好的解决方案,但它至少是阻止重播攻击的另一个障碍。

1

(重放攻击可以很容易地将所有关于IP/MAC欺骗,再加上你所遇到的挑战在动态IP)

它不仅是重播你是这里后,在隔离是没有意义的。只需使用SSL,并避免手工制作任何东西..

ASP.Net ViewState是一团糟,避免它。尽管PKI重量级和臃肿,但至少它没有发明自己的安全“方案”。所以如果可能的话,我会使用它,并始终为相互认证。仅服务器验证是无用的。

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(); 
} 
11

这里有几个很好的答案,并把它们放在一起就是答案最终在于:

  1. 块密码加密(使用AES-256 +)和哈希(与SHA-2 +)发送给客户端的所有状态/随机数相关信息。否则黑客只是操纵数据,查看它来学习模式并规避其他一切。记住......它只需要一个开放的窗口。

  2. 生成一次性随机且唯一的随机数,每个请求通过POST请求发回。这样做有两件事:它确保POST响应与THAT请求一致。它还允许跟踪一组get/POST对的一次性使用(防止重播)。

  3. 使用时间戳使临时池可管理。将时间戳存储在上面#1的加密cookie中。抛出比应用程序的最大响应时间或会话更早的任何请求(例如,一个小时)。

  4. 将请求的机器的“合理唯一”的数字指纹与加密的时间戳数据一起存储。这将防止攻击者窃取客户端cookie执行会话劫持的另一个窍门。这将确保该请求不仅会返回一次,而且会从机器返回(或者距离足够近以使攻击者几乎不可能复制)。

有ASPNET和基于Java/J2EE安全过滤器的应用程序可以完成上述所有的零编码。对于大型系统(如股票交易公司,银行或大批量安全站点)来说,管理随机池并不是一项微不足道的工作,只要性能至关重要。建议看看这些产品,而不是为每个Web应用程序编写这个程序。

0

使用https ...它具有内置的重播保护。