如何防止重播攻击?

时间:2023-01-13 10:30:59

This is related to another question I asked. In summary, I have a special case of a URL where, when a form is POSTed to it, I can't rely on cookies for authentication or to maintain the user's session, but I somehow need to know who they are, and I need to know they're logged in!

这和我问的另一个问题有关。总之,我有一个URL的特殊情况,当一个表单被发布到它时,我不能依赖cookie进行身份验证或维护用户会话,但是我需要知道它们是谁,我需要知道它们已经登录了!

I think I came up with a solution to my problem, but it needs fleshing out. Here's what I'm thinking. I create a hidden form field called "username", and place within it the user's username, encrypted. Then, when the form POSTs, even though I don't receive any cookies from the browser, I know they're logged in because I can decrypt the hidden form field and get the username.

我想我想出了一个解决我的问题的办法,但它需要充实。这是我在想什么。我创建了一个名为“username”的隐藏表单字段,并将用户的用户名加密放在其中。然后,当表单发布时,即使我没有从浏览器接收任何cookie,我也知道它们已经登录了,因为我可以解密隐藏的表单字段并获得用户名。

The major security flaw I can see is replay attacks. How do I prevent someone from getting ahold of that encrypted string, and POSTing as that user? I know I can use SSL to make it harder to steal that string, and maybe I can rotate the encryption key on a regular basis to limit the amount of time that the string is good for, but I'd really like to find a bulletproof solution. Anybody have any ideas? Does the ASP.Net ViewState prevent replay? If so, how do they do it?

我能看到的主要安全漏洞是重播攻击。如何防止某人获得加密字符串并作为该用户发布?我知道我可以使用SSL使它更难偷取那个字符串,也许我可以定期旋转加密密钥来限制这个字符串的使用时间,但我真的想找到一个防弹的解决方案。谁有什么好主意吗?ASP。网络视图状态防止重放?如果是的话,他们怎么做呢?

Edit: I'm hoping for a solution that doesn't require anything stored in a database. Application state would be okay, except that it won't survive an IIS restart or work at all in a web farm or garden scenario. I'm accepting Chris's answer, for now, because I'm not convinced it's even possible to secure this without a database. But if someone comes up with an answer that does not involve the database, I'll accept it!

编辑:我希望找到一个不需要在数据库中存储任何东西的解决方案。应用程序状态是可以的,除非它无法在IIS重启或在web farm或garden场景中工作。我现在接受Chris的回答,因为我不相信在没有数据库的情况下就能保证安全。但是如果有人提出一个不涉及数据库的答案,我会接受的!

12 个解决方案

#1


13  

If you hash in a time-stamp along with the user name and password, you can close the window for replay attacks to within a couple of seconds. I don't know if this meets your needs, but it is at least a partial solution.

如果在时间戳中加上用户名和密码,可以在几秒钟内关闭重播攻击的窗口。我不知道这是否满足你的需要,但这至少是部分解决方案。

#2


13  

If you really don't want to store any state, I think the best you can do is limit replay attacks by using timestamps and a short expiration time. For example, server sends:

如果您真的不想存储任何状态,我认为最好的方法是使用时间戳和短过期时间限制重播攻击。例如,服务器发送:

{Ts, U, HMAC({Ts, U}, Ks)}

{Ts, U, HMAC({Ts, U}, Ks})}

Where Ts is the timestamp, U is the username, and Ks is the server's secret key. The user sends this back to the server, and the server validates it by recomputing the HMAC on the supplied values. If it's valid, you know when it was issued, and can choose to ignore it if it's older than, say, 5 minutes.

其中Ts是时间戳,U是用户名,Ks是服务器的密匙。用户将它发送回服务器,服务器通过在提供的值上重新计算HMAC来验证它。如果它是有效的,你知道它是什么时候发出的,如果它比5分钟的时间要长,你可以选择忽略它。

A good resource for this type of development is The Do's and Don'ts of Client Authentication on the Web

对于这种类型的开发来说,一个很好的资源是Web上的客户端身份验证的行为和行为

#3


11  

There are several good answers here and putting them all together is where the answer ultimately lies:

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

  1. Block-cipher encrypt (with AES-256+) and hash (with SHA-2+) all state/nonce related information that is sent to a client. Hackers with otherwise just manipulate the data, view it to learn the patterns and circumvent everything else. Remember ... it only takes one open window.

    块密码加密(使用AES-256+)和散列(使用SHA-2+)所有状态/nonce相关信息发送到客户端。黑客只是操纵数据,查看数据以了解模式,并绕过其他一切。记得……只要打开一个窗口。

  2. Generate a one-time random and unique nonce per request that is sent back with the POST request. This does two things: It ensures that the POST response goes with THAT request. It also allows tracking of one-time use of a given set of get/POST pairs (preventing replay).

    生成一个一次性随机和惟一的nonce,每个请求被发送回POST请求。这做了两件事:它确保POST响应与该请求一致。它还允许跟踪一次性使用的一组get/POST对(防止重播)。

  3. Use timestamps to make the nonce pool manageable. Store the time-stamp in an encrypted cookie per #1 above. Throw out any requests older than the maximum response time or session for the application (e.g., an hour).

    使用时间戳使nonce池易于管理。将时间戳存储在上面的#1加密的cookie中。抛出任何超过应用程序的最大响应时间或会话的请求(例如,一个小时)。

  4. Store a "reasonably unique" digital fingerprint of the machine making the request with the encrypted time-stamp data. This will prevent another trick wherein the attacker steals the clients cookies to perform session-hijacking. This will ensure that the request is coming back not only once but from the machine (or close enough proximity to make it virtually impossible for the attacker to copy) the form was sent to.

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

There are ASPNET and Java/J2EE security filter based applications that do all of the above with zero coding. Managing the nonce pool for large systems (like a stock trading company, bank or high volume secure site) is not a trivial undertaking if performance is critical. Would recommend looking at those products versus trying to program this for each web-application.

有基于ASPNET和Java/J2EE安全过滤器的应用程序,它们在零编码的情况下完成上述所有工作。如果性能至关重要,那么为大型系统(如股票交易公司、银行或大容量安全站点)管理nonce池并非易事。建议您查看这些产品,而不是尝试为每个web应用程序编写程序。

#4


4  

You could use some kind of random challenge string that's used along with the username to create the hash. If you store the challenge string on the server in a database you can then ensure that it's only used once, and only for one particular user.

你可以使用一些随机的挑战字符串和用户名一起创建哈希。如果您将挑战字符串存储在数据库中的服务器上,那么您可以确保只对一个特定用户使用一次。

#5


2  

In one of my apps to stop 'replay' attacks I have inserted IP information into my session object. Everytime I access the session object in code I make sure to pass the Request.UserHostAddress with it and then I compare to make sure the IPs match up. If they don't, then obviously someone other than the person made this request, so I return null. It's not the best solution but it is at least one more barrier to stop replay attacks.

在我的一个阻止“重播”攻击的应用程序中,我将IP信息插入到会话对象中。每次在代码中访问会话对象时,我都要确保传递请求。UserHostAddress和它,然后我比较以确保IPs匹配。如果没有,那么显然除了发出请求的人之外还有其他人,所以返回null。这不是最好的解决方案,但至少是阻止重播攻击的一个障碍。

#6


1  

Can you use memory or a database to maintain any information about the user or request at all?

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

If so, then on request for the form, I would include a hidden form field whose contents are a randomly generated number. Save this token to in application context or some sort of store (a database, flat file, etc.) when the request is rendered. When the form is submitted, check the application context or database to see if that randomly generated number is still valid (however you define valid - maybe it can expire after X minutes). If so, remove this token from the list of "allowed tokens".

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

Thus any replayed requests would include this same token which is no longer considered valid on the server.

因此,任何重放的请求都将包含这个在服务器上不再被认为有效的令牌。

#7


1  

I am new to some aspects of web programming but I was reading up on this the other day. I believe you need to use a Nonce.

我对web编程的某些方面还不熟悉,但前几天我读过这方面的文章。我相信你需要用一次。

#8


1  

(Replay attacks can easily be all about an IP/MAC spoofing, plus you're challenged on dynamic IPs )

(重播攻击很容易就是IP/MAC的欺骗,而且你还会受到动态IP的挑战)

It is not just replay you are after here, in isolation it is meaningless. Just use SSL and avoid handcrafting anything..

这不仅仅是你在这里的重复,孤立地说,这是没有意义的。只要使用SSL,避免手工制作任何东西。

ASP.Net ViewState is a mess, avoid it. While PKI is heavyweight and bloated, at least it works without inventing your own security 'schemes'. So if I could, I'd use it and always go for mutual authent. Server-only authentification is quite useless.

ASP。Net ViewState是一个混乱的状态,避免它。虽然PKI是重量级的、臃肿的,但它至少可以在不发明你自己的安全“计划”的情况下工作。如果可以的话,我就会用它,并且总是相互信任。只有服务器验证是非常无用的。

#9


1  

The ViewState includes security functionality. See this article about some of the build-in security features in ASP.NET . It does validation against the server machineKey in the machine.config on the server, which ensures that each postback is valid.

ViewState包含安全功能。请参阅本文,了解ASP中的一些内置安全特性。网。它对机器中的服务器机关键进行验证。在服务器上配置,确保每个回发都是有效的。

Further down in the article, you also see that if you want to store values in your own hidden fields, you can use the LosFormatter class to encode the value in the same way that the ViewState uses for encryption.

在本文的进一步下面,您还可以看到,如果您想在自己的隐藏字段中存储值,您可以使用LosFormatter类以同样的方式对值进行编码,这与ViewState用于加密的方式相同。

private string EncodeText(string text) {
  StringWriter writer = new StringWriter();
  LosFormatter formatter = new LosFormatter();
  formatter.Serialize(writer, text);
  return writer.ToString();
}

#10


0  

If you only accept each key once (say, make the key a GUID, and then check when it comes back), that would prevent replays. Of course, if the attacker responds first, then you have a new problem...

如果您只接受每个键一次(例如,将键设置为GUID,然后在它返回时检查),就可以防止重播。当然,如果攻击者先做出反应,那么你就有了一个新问题……

#11


0  

Is this WebForms or MVC? If it's MVC you could utilize the AntiForgery token. This seems like it's similar to the approach you mention except it uses basically a GUID and sets a cookie with the guid value for that post. For more on that see Steve Sanderson's blog: http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/

这是WebForms还是MVC?如果是MVC,可以使用反伪造令牌。这似乎与您提到的方法相似,但它基本上使用GUID并为该帖子设置一个具有GUID值的cookie。更多相关信息请参见Steve Sanderson的博客:http://blog.codeville.net/2008/09/01/ prevgete -request- forgery-- csrf- usrf - usrf -aspnet-mvcs-antiforgerytoken-helper/

Another thing, have you considered checking the referrer on the postback? This is not bulletproof but it may help.

还有一件事,你有没有考虑过在回执上检查推荐人?这不是防弹的,但可能会有帮助。

#12


0  

Use https... it has replay protection built in.

使用https……它内置回放保护。

#1


13  

If you hash in a time-stamp along with the user name and password, you can close the window for replay attacks to within a couple of seconds. I don't know if this meets your needs, but it is at least a partial solution.

如果在时间戳中加上用户名和密码,可以在几秒钟内关闭重播攻击的窗口。我不知道这是否满足你的需要,但这至少是部分解决方案。

#2


13  

If you really don't want to store any state, I think the best you can do is limit replay attacks by using timestamps and a short expiration time. For example, server sends:

如果您真的不想存储任何状态,我认为最好的方法是使用时间戳和短过期时间限制重播攻击。例如,服务器发送:

{Ts, U, HMAC({Ts, U}, Ks)}

{Ts, U, HMAC({Ts, U}, Ks})}

Where Ts is the timestamp, U is the username, and Ks is the server's secret key. The user sends this back to the server, and the server validates it by recomputing the HMAC on the supplied values. If it's valid, you know when it was issued, and can choose to ignore it if it's older than, say, 5 minutes.

其中Ts是时间戳,U是用户名,Ks是服务器的密匙。用户将它发送回服务器,服务器通过在提供的值上重新计算HMAC来验证它。如果它是有效的,你知道它是什么时候发出的,如果它比5分钟的时间要长,你可以选择忽略它。

A good resource for this type of development is The Do's and Don'ts of Client Authentication on the Web

对于这种类型的开发来说,一个很好的资源是Web上的客户端身份验证的行为和行为

#3


11  

There are several good answers here and putting them all together is where the answer ultimately lies:

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

  1. Block-cipher encrypt (with AES-256+) and hash (with SHA-2+) all state/nonce related information that is sent to a client. Hackers with otherwise just manipulate the data, view it to learn the patterns and circumvent everything else. Remember ... it only takes one open window.

    块密码加密(使用AES-256+)和散列(使用SHA-2+)所有状态/nonce相关信息发送到客户端。黑客只是操纵数据,查看数据以了解模式,并绕过其他一切。记得……只要打开一个窗口。

  2. Generate a one-time random and unique nonce per request that is sent back with the POST request. This does two things: It ensures that the POST response goes with THAT request. It also allows tracking of one-time use of a given set of get/POST pairs (preventing replay).

    生成一个一次性随机和惟一的nonce,每个请求被发送回POST请求。这做了两件事:它确保POST响应与该请求一致。它还允许跟踪一次性使用的一组get/POST对(防止重播)。

  3. Use timestamps to make the nonce pool manageable. Store the time-stamp in an encrypted cookie per #1 above. Throw out any requests older than the maximum response time or session for the application (e.g., an hour).

    使用时间戳使nonce池易于管理。将时间戳存储在上面的#1加密的cookie中。抛出任何超过应用程序的最大响应时间或会话的请求(例如,一个小时)。

  4. Store a "reasonably unique" digital fingerprint of the machine making the request with the encrypted time-stamp data. This will prevent another trick wherein the attacker steals the clients cookies to perform session-hijacking. This will ensure that the request is coming back not only once but from the machine (or close enough proximity to make it virtually impossible for the attacker to copy) the form was sent to.

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

There are ASPNET and Java/J2EE security filter based applications that do all of the above with zero coding. Managing the nonce pool for large systems (like a stock trading company, bank or high volume secure site) is not a trivial undertaking if performance is critical. Would recommend looking at those products versus trying to program this for each web-application.

有基于ASPNET和Java/J2EE安全过滤器的应用程序,它们在零编码的情况下完成上述所有工作。如果性能至关重要,那么为大型系统(如股票交易公司、银行或大容量安全站点)管理nonce池并非易事。建议您查看这些产品,而不是尝试为每个web应用程序编写程序。

#4


4  

You could use some kind of random challenge string that's used along with the username to create the hash. If you store the challenge string on the server in a database you can then ensure that it's only used once, and only for one particular user.

你可以使用一些随机的挑战字符串和用户名一起创建哈希。如果您将挑战字符串存储在数据库中的服务器上,那么您可以确保只对一个特定用户使用一次。

#5


2  

In one of my apps to stop 'replay' attacks I have inserted IP information into my session object. Everytime I access the session object in code I make sure to pass the Request.UserHostAddress with it and then I compare to make sure the IPs match up. If they don't, then obviously someone other than the person made this request, so I return null. It's not the best solution but it is at least one more barrier to stop replay attacks.

在我的一个阻止“重播”攻击的应用程序中,我将IP信息插入到会话对象中。每次在代码中访问会话对象时,我都要确保传递请求。UserHostAddress和它,然后我比较以确保IPs匹配。如果没有,那么显然除了发出请求的人之外还有其他人,所以返回null。这不是最好的解决方案,但至少是阻止重播攻击的一个障碍。

#6


1  

Can you use memory or a database to maintain any information about the user or request at all?

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

If so, then on request for the form, I would include a hidden form field whose contents are a randomly generated number. Save this token to in application context or some sort of store (a database, flat file, etc.) when the request is rendered. When the form is submitted, check the application context or database to see if that randomly generated number is still valid (however you define valid - maybe it can expire after X minutes). If so, remove this token from the list of "allowed tokens".

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

Thus any replayed requests would include this same token which is no longer considered valid on the server.

因此,任何重放的请求都将包含这个在服务器上不再被认为有效的令牌。

#7


1  

I am new to some aspects of web programming but I was reading up on this the other day. I believe you need to use a Nonce.

我对web编程的某些方面还不熟悉,但前几天我读过这方面的文章。我相信你需要用一次。

#8


1  

(Replay attacks can easily be all about an IP/MAC spoofing, plus you're challenged on dynamic IPs )

(重播攻击很容易就是IP/MAC的欺骗,而且你还会受到动态IP的挑战)

It is not just replay you are after here, in isolation it is meaningless. Just use SSL and avoid handcrafting anything..

这不仅仅是你在这里的重复,孤立地说,这是没有意义的。只要使用SSL,避免手工制作任何东西。

ASP.Net ViewState is a mess, avoid it. While PKI is heavyweight and bloated, at least it works without inventing your own security 'schemes'. So if I could, I'd use it and always go for mutual authent. Server-only authentification is quite useless.

ASP。Net ViewState是一个混乱的状态,避免它。虽然PKI是重量级的、臃肿的,但它至少可以在不发明你自己的安全“计划”的情况下工作。如果可以的话,我就会用它,并且总是相互信任。只有服务器验证是非常无用的。

#9


1  

The ViewState includes security functionality. See this article about some of the build-in security features in ASP.NET . It does validation against the server machineKey in the machine.config on the server, which ensures that each postback is valid.

ViewState包含安全功能。请参阅本文,了解ASP中的一些内置安全特性。网。它对机器中的服务器机关键进行验证。在服务器上配置,确保每个回发都是有效的。

Further down in the article, you also see that if you want to store values in your own hidden fields, you can use the LosFormatter class to encode the value in the same way that the ViewState uses for encryption.

在本文的进一步下面,您还可以看到,如果您想在自己的隐藏字段中存储值,您可以使用LosFormatter类以同样的方式对值进行编码,这与ViewState用于加密的方式相同。

private string EncodeText(string text) {
  StringWriter writer = new StringWriter();
  LosFormatter formatter = new LosFormatter();
  formatter.Serialize(writer, text);
  return writer.ToString();
}

#10


0  

If you only accept each key once (say, make the key a GUID, and then check when it comes back), that would prevent replays. Of course, if the attacker responds first, then you have a new problem...

如果您只接受每个键一次(例如,将键设置为GUID,然后在它返回时检查),就可以防止重播。当然,如果攻击者先做出反应,那么你就有了一个新问题……

#11


0  

Is this WebForms or MVC? If it's MVC you could utilize the AntiForgery token. This seems like it's similar to the approach you mention except it uses basically a GUID and sets a cookie with the guid value for that post. For more on that see Steve Sanderson's blog: http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/

这是WebForms还是MVC?如果是MVC,可以使用反伪造令牌。这似乎与您提到的方法相似,但它基本上使用GUID并为该帖子设置一个具有GUID值的cookie。更多相关信息请参见Steve Sanderson的博客:http://blog.codeville.net/2008/09/01/ prevgete -request- forgery-- csrf- usrf - usrf -aspnet-mvcs-antiforgerytoken-helper/

Another thing, have you considered checking the referrer on the postback? This is not bulletproof but it may help.

还有一件事,你有没有考虑过在回执上检查推荐人?这不是防弹的,但可能会有帮助。

#12


0  

Use https... it has replay protection built in.

使用https……它内置回放保护。