django - Django 签名 cookie 会话存储、重放攻击和 SESSION_COOKIE_AGE
问题描述
根据Django 文档,签名的 cookie 会话存储容易受到重放攻击:
另请注意,虽然 MAC 可以保证数据的真实性(它是由您的站点生成的,而不是其他人生成的)和数据的完整性(它都在那里并且正确),但它不能保证新鲜度,即您将被退回您发送给客户的最后一件事。这意味着对于会话数据的某些用途,cookie 后端可能会使您面临重放攻击。与保留每个会话的服务器端记录并在用户注销时使其失效的其他会话后端不同,基于 cookie 的会话在用户注销时不会失效。因此,如果攻击者窃取了用户的 cookie,即使用户注销,他们也可以使用该 cookie 以该用户身份登录。只有当 Cookie 早于您的 SESSION_COOKIE_AGE 时,它们才会被检测为“陈旧”。
这是否意味着:
- 我们依靠 cookie 的客户端过期来确保会话数据被销毁(因此,如果在浏览器删除 cookie 之前捕获 cookie 内容,仍然可能发生重放攻击),或者
SESSION_COOKIE_AGE
服务器检测数据的陈旧性(与它认为陈旧的数据进行比较并明确拒绝。
从技术上讲,Django 能够确定会话的“旧”程度似乎在技术上是可能的,而无需在服务器端持久保存此数据,但文档似乎不清楚这是否正在完成,或者 Django 是否依赖/信任用户的浏览器杀死旧的 cookie(因此如果数据在过期之前被捕获,会话仍然可以重播)。
解决方案
Django 通过SessionMiddleware
确实将HTTP cookie 过期时间设置为SESSION_COOKIE_AGE
. 这告诉浏览器cookie什么时候应该被认为“太旧”和过期。这是很好的家政服务。此外,如果浏览器检测到不应再使用 cookie,它将不会使用它,这样 Django 就不会花时间检查 cookie can't be used Anyway。
然而,Django 并不依赖浏览器来确保过期的 cookie 永远不会被再次使用。流氓代理可以获取 cookie 的副本,然后在过期后重新使用它。Django 通过将 cookie 发送到格式如下的浏览器来防止这种情况:
<payload>:<creation stamp>:<signature>
冒号是出现在数据中的分隔符。<payload>
是实际的会话数据。<creation stamp>
是创建cookie时添加的时间戳,<signature>
是对payload和创建时间戳进行签名的MAC签名。
您可以在 中查看相关代码django.core.signing
。文件顶部的注释为您提供了使用Signer
该类的基本签名方案。这个类不知道时间戳。但是,在签署 cookie 时,Django 使用TimestampSigner
,它知道时间戳并生成我上面显示的格式。
TimestampSigner
取消签名cookie时,它会检查时间戳,如果太旧则引发异常:
def unsign(self, value, max_age=None):
"""
Retrieve original value and check it wasn't signed more
than max_age seconds ago.
"""
result = super().unsign(value)
value, timestamp = result.rsplit(self.sep, 1)
timestamp = baseconv.base62.decode(timestamp)
if max_age is not None:
if isinstance(max_age, datetime.timedelta):
max_age = max_age.total_seconds()
# Check timestamp is not older than max_age
age = time.time() - timestamp
if age > max_age:
raise SignatureExpired(
'Signature age %s > %s seconds' % (age, max_age))
return value
推荐阅读
- angularjs - 在 Chrome 中选择标签选项边框蓝色并悬停在蓝色背景上 [重复但在任何地方都没有找到解决方案]
- vb.net - VB:动态创建文件 - 然后写入文件
- sql - SYSDATE - 检索最近 2 分钟订单的时间戳
- javascript - 如何从另一个页面链接到 jQuery 过滤视图并选择默认过滤器?
- php - 在 php 上下载时重命名 zip 中的文件
- java - 即使有偏差,感知器也找不到正确的线(处理)
- sql - 如何在 teradata 中实现延迟功能。
- google-cloud-platform - 在构建触发器上使用 base64 编码值时,cloudbuil.yaml 不会解组
- mysql - Kubernetes Docker/MySQL 一个服务中的多个数据库
- css - 背景颜色在带有引导 col 类的 div 内可见