这是this的后续问题。
我在Python 2.7、Django 1.8和Django REST framework 3.3中使用最新的Django OAuth2 Toolkit (0.10.0)
一些背景:
在进行身份验证时,客户机将收到每次向服务器发出新请求时使用的新AccessToken
。此AccessToken
归客户所有,并根据请求使用Authorization
头进行传输。
我做的一个简单测试是从一个经过身份验证的客户端获取这个访问令牌,并使用来自另一台机器的简单HTTP请求在Authorization header
中发送它。
结果是,这个新的“客户机”现在已经像原来的客户机一样得到了身份验证,他可以随心所欲地发出请求。
所以问题是:
访问令牌未绑定到任何形式的客户端验证(如会话id或客户端IP地址)。任何可以获取/查找/窃取/查找客户端的AccessToken
,都可以是代表此客户端的伪请求。
我研究过这个问题,但找不到任何人来解决这个问题。也许我在认证客户的过程中做错了什么?我想听听你的见解。也许这是一个简单的配置,开箱即用的解决方案,我错过了。
谢谢!
最佳答案
这种攻击方法称为重放攻击。This video by Professor Messer解释重播攻击。
由于web浏览器的透明性,您不能真正实现任何客户端(浏览器)来克服这个问题。
您可以做的是使用nonce实现摘要身份验证。
在密码学中,nonce是一个只能使用一次的任意数字。
基本实现如下所示。
用户请求API服务器。
API服务器使用HTTP 401和WWW-Authenticate
头中的nonce响应[您必须跟踪nonce](带有nonce的JWT设置为在小窗口中过期,可能是2秒或更少,这会更好,而且是无状态的)。
客户机使用接收到的nonce、客户机nonce和密码对请求进行签名,然后再次调用资源。
API服务器验证签名,如果签名有效,则接受请求。
攻击者捕获请求并伪造用户。
由于nonce已过期/“仅使用一次”,攻击者的请求被拒绝。