Django签署了Cookie会话存储,重播攻击和SESSION_COOKIE_AGE

时间:2019-02-22 02:37:05

标签: django session cookies

根据the Django documentation,签名的cookie会话存储很容易受到重放攻击:

  

还请注意,尽管MAC可以保证   数据(它是由您的网站而非其他人生成的),并且   数据的完整性(所有数据都正确无误),   无法保证新鲜度,即您将被送回最后   你发送给客户的东西。这意味着对于会话的某些用途   数据,Cookie后端可能会让您重播攻击。不像   其他会话后端,这些后端保留每个会话的服务器端记录   并在用户注销时使其无效,但基于cookie的会话不会   用户注销时无效。因此,如果攻击者窃取了用户的   Cookie,他们可以使用该Cookie以该用户身份登录,即使   用户注销。 Cookies只会被检测为“陈旧”   比您的SESSION_COOKIE_AGE大。

这是否意味着:

  1. 我们依靠cookie的客户端有效期来确保会话数据被销毁(因此,如果在浏览器删除cookie之前捕获了cookie的内容,则仍然可以进行重放攻击),或者
  2. 服务器检测到数据是否陈旧(与SESSION_COOKIE_AGE相比,并明确拒绝它认为过时的数据。

从技术上讲,Django可以在不持久化数据服务器端的情况下确定会话的“旧”程度,但是文档似乎不清楚这是否在做,还是Django依赖/信任用户的浏览器杀死旧的Cookie(因此,如果数据在过期之前被捕获,则会话仍可以重播)。

2 个答案:

答案 0 :(得分:3)

Django通过SessionMiddlewareHTTP cookie expiration设置为SESSION_COOKIE_AGE。这告诉浏览器何时应将cookie视为“太旧”并过期。这很好另外,如果浏览器检测到不应再使用Cookie,则它将不再使用它,从而使Django不必花费时间检查仍然无法使用Cookie的时间。

但是, Django不依赖浏览器来确保不再使用过期的Cookie 。流氓代理可以获取Cookie的副本,然后在其过期日期之后重新使用它。 Django通过将Cookie发送到以下格式的浏览器来防止这种情况:

<payload>:<creation stamp>:<signature>

冒号是按字面意义出现在数据中的分隔符。 <payload>是实际的会话数据。 <creation stamp>是创建cookie时添加的时间戳,<signature>是用于标记有效负载和创建戳记的MAC签名。

您可以在django.core.signing中查看相关代码。文件顶部的注释为您提供了使用Signer类的基本签名方案。此类不了解时间戳。但是,在签署cookie时,Django使用TimestampSigner,它确实了解时间戳并生成上面显示的格式。

TimestampSigner unsigns一个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

答案 1 :(得分:-2)

长话短说,您需要设置一个简短的SESSION_COOKIE_AGE,以确保恶意用户不会利用您的网站。

这可能实现如下:

  1. cookie数据存储发布cookie的时间戳
  2. 在服务器端读取cookie时,它将获得此时间戳并将其与SESSION_COOKIE_AGE进行比较。
  3. 如果cookie的时间戳早于SESSION_COOKIE_AGE,它将拒绝请求