防止请求重放攻击
Preventing request replay attack
我有一个简单的 REST API 来防止请求重放攻击。我在请求中添加了 UTC 时间戳,如果秒数差异不超过 60 秒,则允许请求。
API 由 Android 和 iOS 应用程序使用。将应用程序投入生产后,我们意识到大多数用户的时间和时区不准确,这阻碍了他们使用该应用程序。
如何改进缓解措施?
无论 phone 的时间和时区如何,我都可以获得 UTC 时间吗?
您不应依赖设备发送的时间戳,因为它很容易被篡改。
如果(且仅当)您能够识别来自同一用户或设备的请求,那么您可以使用服务器上的时间戳并执行相同的缓解策略,但这次您有一个统一的时间度量. (您需要在 per-user 或 per-device 的基础上保存“最后”访问时间戳。)
一种识别用户或设备的方法可以是创建第一次使用的哈希值(例如第一次 运行 + IP 地址 + ...),并将其一起发送REST API 请求所有后续时间。
如果用户需要 log-in,那么您可以将此值与用户信息一起保存;否则你可以类似地“识别”设备。
编辑:此编辑是根据您的评论进行的,其中添加了之前不清楚的信息
I want to check if the originating time of the request and the receiving time on server should not have large interval (say more than 1 minute).*
换句话说,您想根据生成时间(不超过 60 秒)使请求无效。如果现在我正确地解释它,这个想法很可能需要不到 60 秒的时间来回答客户的请求,所以假设 too-old 一条消息很可能已经被正确使用了——它可能是一个回复攻击。
不幸的是,您的解决方案只会(可以预见)减少攻击者可用于执行回复攻击的 space 消息,因此远未 阻止 ,即使有同步的时间戳。此外,如果消息可以被篡改,即攻击者可以刷新具有较新时间戳的旧消息,则缓解措施将完全无效。
无论如何,如果您的目的不是防止回复攻击,而是简单地丢弃过期消息,那么您可以通过提供两个 REST API 来实现您的目标小号:
- 一个用于“准备”(您甚至不需要收集回复)
- 另一个用于实际的“请求”
并且都具有客户端的时间戳并且具有相同的请求标识符。
因此您将在服务器端看到两对 timestamp-requestID:(t,ID)
和 (t',ID)
。
这将允许您简单地对时间戳进行区分,t' - t
,即独立于他们设置的时移或时区。
您还可以为请求计时 server-side 以丢弃与其相应的“准备”相关的太晚到达的“请求”。
此外,为了提高安全性,您可以让客户端 App 对消息(包括时间戳和请求 ID)进行签名以保证完整性 - 消息不会在不知不觉中被篡改,因此您可以依赖发送到的时间戳APIs。一种方法是使用 public-key 密码术,但要小心分发 public 密钥的方式。
(这样你就可以限制攻击者只回复最近的请求)。
我有一个简单的 REST API 来防止请求重放攻击。我在请求中添加了 UTC 时间戳,如果秒数差异不超过 60 秒,则允许请求。
API 由 Android 和 iOS 应用程序使用。将应用程序投入生产后,我们意识到大多数用户的时间和时区不准确,这阻碍了他们使用该应用程序。
如何改进缓解措施?
无论 phone 的时间和时区如何,我都可以获得 UTC 时间吗?
您不应依赖设备发送的时间戳,因为它很容易被篡改。
如果(且仅当)您能够识别来自同一用户或设备的请求,那么您可以使用服务器上的时间戳并执行相同的缓解策略,但这次您有一个统一的时间度量. (您需要在 per-user 或 per-device 的基础上保存“最后”访问时间戳。)
一种识别用户或设备的方法可以是创建第一次使用的哈希值(例如第一次 运行 + IP 地址 + ...),并将其一起发送REST API 请求所有后续时间。 如果用户需要 log-in,那么您可以将此值与用户信息一起保存;否则你可以类似地“识别”设备。
编辑:此编辑是根据您的评论进行的,其中添加了之前不清楚的信息
I want to check if the originating time of the request and the receiving time on server should not have large interval (say more than 1 minute).*
换句话说,您想根据生成时间(不超过 60 秒)使请求无效。如果现在我正确地解释它,这个想法很可能需要不到 60 秒的时间来回答客户的请求,所以假设 too-old 一条消息很可能已经被正确使用了——它可能是一个回复攻击。
不幸的是,您的解决方案只会(可以预见)减少攻击者可用于执行回复攻击的 space 消息,因此远未 阻止 ,即使有同步的时间戳。此外,如果消息可以被篡改,即攻击者可以刷新具有较新时间戳的旧消息,则缓解措施将完全无效。
无论如何,如果您的目的不是防止回复攻击,而是简单地丢弃过期消息,那么您可以通过提供两个 REST API 来实现您的目标小号:
- 一个用于“准备”(您甚至不需要收集回复)
- 另一个用于实际的“请求”
并且都具有客户端的时间戳并且具有相同的请求标识符。
因此您将在服务器端看到两对 timestamp-requestID:(t,ID)
和 (t',ID)
。
这将允许您简单地对时间戳进行区分,t' - t
,即独立于他们设置的时移或时区。
您还可以为请求计时 server-side 以丢弃与其相应的“准备”相关的太晚到达的“请求”。
此外,为了提高安全性,您可以让客户端 App 对消息(包括时间戳和请求 ID)进行签名以保证完整性 - 消息不会在不知不觉中被篡改,因此您可以依赖发送到的时间戳APIs。一种方法是使用 public-key 密码术,但要小心分发 public 密钥的方式。 (这样你就可以限制攻击者只回复最近的请求)。