IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Django logout function Denial-of-service

    阿多发表于 2015-08-27 08:47:19
    love 0
    • Security releases issued: 1.8.4, 1.7.10, 1.4.22
    • CVE: 2015-5963
    • Fix: Update/1.8.4/1.7.10/1.4.22/Add @login_required()

    Django 官方在八月十八号发布多个版本更新,修复几个安全问题,其中便包括一个由编码不当导致的 DoS 漏洞,测试一些网站均存在此问题。

    Detail

    django.contrib.auth.views.logout 视图用于开发者实现用户注销退出功能,正常情况下对于 logout 视图应使用官方提供的 django.contrib.auth.decorators.login_required 修饰器方法来判断用户是否已经登录。由于不少开发人员忽略使用修饰器进行判断,导致攻击者可以匿名访问视图,不断创建会话阻塞导致拒绝服务攻击。

    django/contrib/sessions/middleware.py:

    try:
            accessed = request.session.accessed
            modified = request.session.modified
        except AttributeError:
            pass
        else:
            if accessed:
                patch_vary_headers(response, ('Cookie',))
            if modified or settings.SESSION_SAVE_EVERY_REQUEST:
                if request.session.get_expire_at_browser_close():
                    max_age = None
                    expires = None
                else:
                    max_age = request.session.get_expiry_age()
                    expires_time = time.time() + max_age
                    expires = cookie_date(expires_time)
                # Save the session data and refresh the client cookie.
                # Skip session save for 500 responses, refs #3881.
                if response.status_code != 500:
                    request.session.save()
                    response.set_cookie(.....

    在对 settings.SESSION_SAVE_EVERY_REQUEST 的判断条件中,middleware 中间件未对 session 的状态进行判断,导致可能绕过进入判断体创建空会话。

    c334041bgw1evg3rysahaj20h40bajv7

    这意味着我们能够发送大量的请求对目标网站进行会话阻塞从而达到拒绝服务攻击:

    c334041bgw1evg3xircexj20i2036aab

    Fix

    django/contrib/sessions/middleware.py:

    try:
            accessed = request.session.accessed
            modified = request.session.modified
            empty = request.session.is_empty()
        except AttributeError:
            pass
        else:
            # First check if we need to delete this cookie.
            # The session should be deleted only if the session is entirely empty
            if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
                response.delete_cookie(settings.SESSION_COOKIE_NAME,
                    domain=settings.SESSION_COOKIE_DOMAIN)
            else:
                if accessed:
                    patch_vary_headers(response, ('Cookie',))
                if (modified or settings.SESSION_SAVE_EVERY_REQUEST) and not empty:

     sessions/backends/base.py & sessions/backends/cached_db.py:

    def is_empty(self):
        "Returns True when there is no session_key and the session is empty"
        try:
            return not bool(self._session_key) and not self._session_cache
        except AttributeError:
            return True
            
    def flush(self):
        """
        Removes the current session data from the database and regenerates the
        key.
        """
        self.clear()
        self.delete()
        self._session_key = None

    虽然严格意义上来讲它是个 DoS 漏洞,但另一方面它完全是由开发者不严谨导致的问题(官方背锅),修复版本将 flush() 的 create() 方法修改以避免创建新的空会话,增加 is_empty() 以用来进行会话判断。

    如果你实在不想升级版本,那么记得在必要的视图层增加 @login_required('/') 修饰器。



沪ICP备19023445号-2号
友情链接