def is_authenticated(self, request, **kwargs):
        """
        Checks to make sure the user is logged in & has a Django session.
        """
        # Cargo-culted from Django 1.3/1.4's ``django/middleware/csrf.py``.
        # We can't just use what's there, since the return values will be
        # wrong.
        # We also can't risk accessing ``request.POST``, which will break with
        # the serialized bodies.
        if request.method in ("GET", "HEAD", "OPTIONS", "TRACE"):
            return request.user.is_authenticated()

        if getattr(request, "_dont_enforce_csrf_checks", False):
            return request.user.is_authenticated()

        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ""))

        if request.is_secure():
            referer = request.META.get("HTTP_REFERER")

            if referer is None:
                return False

            good_referer = "https://%s/" % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        request_csrf_token = request.META.get("HTTP_X_CSRFTOKEN", "")
        request_csrf_token = _sanitize_token(request_csrf_token)

        if not constant_time_compare(unsalt_token(request_csrf_token), unsalt_token(csrf_token)):
            return False

        return request.user.is_authenticated()
Example #2
0
    def is_authenticated(self, request, **kwargs):
        '''
        Checks to make sure the user is logged in and has a Django session.
        '''

        if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            return bool(request.user.is_authenticated)

        if getattr(request, '_dont_enforce_csrf_checks', False):
            return bool(request.user.is_authenticated)

        csrf_token = _sanitize_token(
            request.COOKIES.get(settings.CSRF_COOKIE_NAME))
        if csrf_token is None:
            logger.error('authentication rejected: NO CSRF cookie')
            return False
        elif DEBUG_AUTHENTICATION:
            logger.info('Found CSRF cookie: %r: %r',
                settings.CSRF_COOKIE_NAME, csrf_token)

        if request.is_secure():
            if DEBUG_AUTHENTICATION:
                logger.info('perform secure session check.')
            if self._django_csrf_check(request) is not True:
                return False

        # Compare the session CSRF token to the posted CSRF token
        request_csrf_token = ''
        if request.method == 'POST':
            # Use the >1.4 Django Forms token key: "csrfmiddlewaretoken"
            try:
                request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
                if DEBUG_AUTHENTICATION:
                    logger.info(
                        'SessionAuthentication: POST csrf token (%r): %r', 
                        'csrfmiddlewaretoken', request_csrf_token)
            except IOError:
                # Handle a broken connections
                pass

        if request_csrf_token == '':
            # Fall back to X-CSRFToken, used by Ajax clients
            request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
            if DEBUG_AUTHENTICATION:
                logger.info(
                    'SessionAuthentication: POST csrf token (%r): %r', 
                    'HTTP_X_CSRFTOKEN', request_csrf_token)

        request_csrf_token = _sanitize_token(request_csrf_token)

        if not constant_time_compare(unsalt_token(request_csrf_token),
                                     unsalt_token(csrf_token)):
            logger.warn('CSRF tokens do not match: %r', request)
            return False

        return bool(request.user.is_authenticated)
Example #3
0
    def is_authenticated(self, request, **kwargs):
        '''
        Checks to make sure the user is logged in and has a Django session.
        '''

        if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            return bool(request.user.is_authenticated)

        if getattr(request, '_dont_enforce_csrf_checks', False):
            return bool(request.user.is_authenticated)

        csrf_token = _sanitize_token(
            request.COOKIES.get(settings.CSRF_COOKIE_NAME))
        if csrf_token is None:
            logger.error('authentication rejected: NO CSRF cookie')
            return False
        elif DEBUG_AUTHENTICATION:
            logger.info('Found CSRF cookie: %r: %r', settings.CSRF_COOKIE_NAME,
                        csrf_token)

        if request.is_secure():
            if DEBUG_AUTHENTICATION:
                logger.info('perform secure session check.')
            if self._django_csrf_check(request) is not True:
                return False

        # Compare the session CSRF token to the posted CSRF token
        request_csrf_token = ''
        if request.method == 'POST':
            # Use the >1.4 Django Forms token key: "csrfmiddlewaretoken"
            try:
                request_csrf_token = request.POST.get('csrfmiddlewaretoken',
                                                      '')
                if DEBUG_AUTHENTICATION:
                    logger.info(
                        'SessionAuthentication: POST csrf token (%r): %r',
                        'csrfmiddlewaretoken', request_csrf_token)
            except IOError:
                # Handle a broken connections
                pass

        if request_csrf_token == '':
            # Fall back to X-CSRFToken, used by Ajax clients
            request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
            if DEBUG_AUTHENTICATION:
                logger.info('SessionAuthentication: POST csrf token (%r): %r',
                            'HTTP_X_CSRFTOKEN', request_csrf_token)

        request_csrf_token = _sanitize_token(request_csrf_token)

        if not constant_time_compare(unsalt_token(request_csrf_token),
                                     unsalt_token(csrf_token)):
            logger.warn('CSRF tokens do not match: %r', request)
            return False

        return bool(request.user.is_authenticated)
Example #4
0
    def try_sessions(self, request, **kwargs):
        """
        Attempt to authenticate with sessions.

        Cribbed from a newer version of Tastypie than we're using.
        """
        csrf_token = _sanitize_token(
            request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))

        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')

            if referer is None:
                return False

            good_referer = 'https://%s/' % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        # Tastypie docstring says accessing POST here isn't safe, but so far it's not causing any problems...
        # This is necessary for downloads that post the csrf token from an iframe
        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN',
                                              '') or request.POST.get(
                                                  'csrfmiddlewaretoken', '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Example #5
0
    def try_sessions(self, request, **kwargs):
        """
        Attempt to authenticate with sessions.

        Cribbed from a newer version of Tastypie than we're using.
        """
        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ""))

        if request.is_secure():
            referer = request.META.get("HTTP_REFERER")

            if referer is None:
                return False

            good_referer = "https://%s/" % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        # Tastypie docstring says accessing POST here isn't safe, but so far it's not causing any problems...
        # This is necessary for downloads that post the csrf token from an iframe
        request_csrf_token = request.META.get("HTTP_X_CSRFTOKEN", "") or request.POST.get("csrfmiddlewaretoken", "")

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Example #6
0
    def is_authenticated(self, request, **kwargs):
        """
        """

        # this is the line i have to override in order to get
        # POST request to successfully authenticate ##
        if request.method in ('GET', 'POST', 'DELETE'):
            return request.user.is_authenticated()

        if getattr(request, '_dont_enforce_csrf_checks', False):
            return request.user.is_authenticated()

        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))

        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')

            if referer is None:
                return False

            good_referer = 'https://%s/' % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Example #7
0
    def is_authenticated(self, request, **kwargs):
        """
        """

        # this is the line i have to override in order to get
        # POST request to successfully authenticate ##
        if request.method in ("GET", "POST", "DELETE"):
            return request.user.is_authenticated()

        if getattr(request, "_dont_enforce_csrf_checks", False):
            return request.user.is_authenticated()

        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ""))

        if request.is_secure():
            referer = request.META.get("HTTP_REFERER")

            if referer is None:
                return False

            good_referer = "https://%s/" % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        request_csrf_token = request.META.get("HTTP_X_CSRFTOKEN", "")

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
    def is_authenticated(self, request, **kwargs):
        """
        Checks to make sure the user is logged in & has a Django session.
        """
        # Cargo-culted from Django 1.3/1.4's ``django/middleware/csrf.py``.
        # We can't just use what's there, since the return values will be
        # wrong.
        # We also can't risk accessing ``request.POST``, which will break with
        # the serialized bodies.
        if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            return request.user.is_authenticated()

        if getattr(request, '_dont_enforce_csrf_checks', False):
            return request.user.is_authenticated()

        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))

        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')

            if referer is None:
                return False

            good_referer = 'https://%s/' % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
    def is_authenticated(self, request, **kwargs):
        """
        Checks to make sure the user is logged in & has a Django session.
        """
        # Cargo-culted from Django 1.3/1.4's ``django/middleware/csrf.py``.
        # We can't just use what's there, since the return values will be
        # wrong.
        # We also can't risk accessing ``request.POST``, which will break with
        # the serialized bodies.
        if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            return request.user.is_authenticated()

        if getattr(request, '_dont_enforce_csrf_checks', False):
            return request.user.is_authenticated()

        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))

        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')

            if referer is None:
                return False

            good_referer = 'https://%s/' % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        csrf_meta_name = getattr(settings, 'CSRF_META_NAME', 'HTTP_X_CSRFTOKEN')
        request_csrf_token = request.META.get(csrf_meta_name, '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Example #10
0
def upload_status(request):
    if request.method == 'GET':
        if request.GET['key']:
            csrftoken = request.META.get(
                "CSRF_COOKIE") if "CSRF_COOKIE" in request.META else None
            cache_exist = cache.get(csrftoken)
            request_csrftoken = request.GET['key']
            match = True
            try:
                from django.middleware.csrf import _sanitize_token, _compare_salted_tokens
                request_csrftoken = _sanitize_token(request_csrftoken)
                match = _compare_salted_tokens(request_csrftoken, csrftoken)
            except:
                pass
            if cache_exist and match:
                value = cache.get(csrftoken)
                return HttpResponse(json.dumps(value),
                                    content_type="application/json")
            elif not _compare_salted_tokens(key, csrftoken):
                return HttpResponse(json.dumps(
                    {'error': "csrf value not match"}),
                                    content_type="application/json")
            else:
                return HttpResponse(json.dumps(
                    {'error': "No csrf value in cache"}),
                                    content_type="application/json")
        else:
            return HttpResponse(json.dumps(
                {'error': 'No parameter key in GET request'}),
                                content_type="application/json")
    else:
        return HttpResponse(json.dumps({'error': 'No GET request'}),
                            content_type="application/json")
    def is_authenticated(self, request, **kwargs):

        # this is the line i have to override in order to get
        # POST request to successfully authenticate ##
        if request.method in ['GET', 'POST', 'PATCH', 'DELETE']:
            return request.user.is_authenticated()

        if getattr(request, '_dont_enforce_csrf_checks', False):
            return request.user.is_authenticated()

        csrf_token = _sanitize_token(
            request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))

        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')

            if referer is None:
                return False

            good_referer = 'https://%s/' % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Example #12
0
 def check_csrf_token(request, *args, **kwargs):
     csrf_token = _sanitize_token(request.GET.get(token_key, ''))
     match = _compare_salted_tokens(
         csrf_token, request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))
     if not match:
         raise PermissionDenied
     else:
         return view_func(request, *args, **kwargs)
Example #13
0
 def check_csrf_token(request, *args, **kwargs):
     csrf_token = _sanitize_token(request.GET.get(token_key, ""))
     match = _compare_salted_tokens(
         csrf_token, request.COOKIES.get(settings.CSRF_COOKIE_NAME, ""))
     if not match and getattr(settings, "CSRF_VERIFY_TOKEN", True):
         raise PermissionDenied
     else:
         return view_func(request, *args, **kwargs)
Example #14
0
def _get_token():
    try:
        cookie_token = request.cookies[api_settings.CSRF_COOKIE_NAME]
    except KeyError:
        return None

    csrf_token = _sanitize_token(cookie_token)
    if csrf_token != cookie_token:
        # Cookie token needed to be replaced;
        # the cookie needs to be reset.
        g.csrf_cookie_needs_reset = True
    return csrf_token
Example #15
0
def get_or_create_csrf_token(request):
    try:
        csrf_token = _sanitize_token(
            request.COOKIES[django_settings.CSRF_COOKIE_NAME])
        # Use same token next time
    except KeyError:
        csrf_token = _get_new_csrf_key()
        # Generate token and store it in the request, so it's
        # available to the view.
    request.META['CSRF_COOKIE'] = csrf_token
    request.META['CSRF_COOKIE_USED'] = True
    return csrf_token
Example #16
0
def _get_token():
    try:
        cookie_token = request.cookies[api_settings.CSRF_COOKIE_NAME]
    except KeyError:
        return None

    csrf_token = _sanitize_token(cookie_token)
    if csrf_token != cookie_token:
        # Cookie token needed to be replaced;
        # the cookie needs to be reset.
        g.csrf_cookie_needs_reset = True
    return csrf_token
Example #17
0
def get_or_create_csrf_token(request):
    try:
        csrf_token = _sanitize_token(
            request.COOKIES[django_settings.CSRF_COOKIE_NAME])
        # Use same token next time
    except KeyError:
        csrf_token = _get_new_csrf_key()
        # Generate token and store it in the request, so it's
        # available to the view.
    request.META['CSRF_COOKIE'] = csrf_token
    request.META['CSRF_COOKIE_USED'] = True
    return csrf_token
Example #18
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        referer = request.META.get('HTTP_REFERER')

        csrf_token = request.META.get('CSRF_COOKIE')
        if csrf_token is None:
            return self._reject(request, REASON_NO_CSRF_COOKIE)

        request_csrf_token = request.GET.get('state', '')
        request_csrf_token = _sanitize_token(request_csrf_token)
        if not _compare_salted_tokens(request_csrf_token, csrf_token):
            return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Example #19
0
def token(request):
    request_csrf_token = ""
    if request.method == "POST":
        try:
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
        except IOError:
            return HttpResponse('e')

    if request_csrf_token == "":
        request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')

    request_csrf_token = _sanitize_token(request_csrf_token)
    if not _compare_salted_tokens(request_csrf_token, csrf_token):
        return HttpResponse(request, REASON_BAD_TOKEN)
Example #20
0
def manual_csrf_check(request):
    """
    Performs a CSRF check for a specific request.

    Useful for in-view CSRF checks.

    Returns an HTTP response in case of CSRF failure.
    """
    try:
        csrf_token = _sanitize_token(
            request.COOKIES[settings.CSRF_COOKIE_NAME]
        )
        request.META['CSRF_COOKIE'] = csrf_token
    except KeyError:
        csrf_token = None
        request.META["CSRF_COOKIE"] = _get_new_csrf_key()

    if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')
            if referer is None:
                return middleware._reject(request, REASON_NO_REFERER)

            good_referer = 'https://%s/' % request.get_host()
            if not same_origin(referer, good_referer):
                reason = REASON_BAD_REFERER % (referer, good_referer)
                return middleware._reject(request, reason)

        if csrf_token is None:
            return middleware._reject(request, REASON_NO_CSRF_COOKIE)

        request_csrf_token = ""
        if request.method == "POST":
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')

        if request_csrf_token == "":
            request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return middleware._reject(request, REASON_BAD_TOKEN)
Example #21
0
def get_csrf_token(request):
    """
    CsrfViewMiddleware.process_view is never called for cached
    responses, and we still need to provide a CSRF token as an
    ssi variable, we must make sure here that the CSRF token
    is in request.META['CSRF_COOKIE'].

    """
    token = get_token(request)
    if token:
        # CSRF token is already in place, just return it.
        return token

    # Mimicking CsrfViewMiddleware.process_view.
    try:
        token = _sanitize_token(request.COOKIES[settings.CSRF_COOKIE_NAME])
        request.META['CSRF_COOKIE'] = token
    except KeyError:
        # Create new CSRF token.
        rotate_token(request)
        token = get_token(request)

    return token
Example #22
0
    def is_authenticated(self, request, **kwargs):
        """Check for valid CSRF token"""
        # Cargo-culted from TastyPie (which itself was cargo-culted from Django)
        # However, we only want CSRF, all our anons are anon.
        if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            return True

        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))

        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')

            if referer is None:
                return False

            good_referer = 'https://%s/' % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

        return constant_time_compare(request_csrf_token, csrf_token)
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            csrf_token = django_csrf._sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META['CSRF_COOKIE'] = csrf_token
        except KeyError:
            csrf_token = None
            # Generate token and store it in the request, so it's
            # available to the view.
            request.META["CSRF_COOKIE"] = django_csrf._get_new_csrf_key()

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC2616 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # nonce we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = force_text(request.META.get('HTTP_REFERER'),
                                     strings_only=True,
                                     errors='replace')
                if referer is None:
                    return self._reject(request, django_csrf.REASON_NO_REFERER)

                # Here we generate a list of all acceptable HTTP referers,
                # including the current host since that has been validated
                # upstream.
                good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
                # Note that request.get_host() includes the port.
                good_hosts.append(request.get_host())
                good_referers = [
                    'https://{0}/'.format(host) for host in good_hosts
                ]
                if not any(
                        same_origin(referer, host) for host in good_referers):
                    reason = REASON_BAD_REFERER % referer
                    return self._reject(request, reason)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, django_csrf.REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    request_csrf_token = request.POST.get(
                        'csrfmiddlewaretoken', '')
                except IOError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                return self._reject(request, django_csrf.REASON_BAD_TOKEN)

        return self._accept(request)
Example #24
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            csrf_token = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META['CSRF_COOKIE'] = csrf_token
        except KeyError:
            csrf_token = None
            # Generate token and store it in the request, so it's
            # available to the view.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC2616 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                logger.warning('Forbidden (%s): %s',
                               REASON_NO_CSRF_COOKIE, request.path,
                    extra={
                        'status_code': 403,
                        'request': request,
                    }
                )
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                logger.warning('Forbidden (%s): %s',
                               REASON_BAD_TOKEN, request.path,
                    extra={
                        'status_code': 403,
                        'request': request,
                    }
                )
                return self._reject(request, REASON_BAD_TOKEN)

        resp = self._accept(request)

        request.META["CSRF_COOKIE_USED"] = True
        return resp
Example #25
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            csrf_token = django_csrf._sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META['CSRF_COOKIE'] = csrf_token
        except KeyError:
            csrf_token = None
            # Generate token and store it in the request, so it's
            # available to the view.
            request.META["CSRF_COOKIE"] = django_csrf._get_new_csrf_key()

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC2616 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # nonce we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = force_text(
                    request.META.get('HTTP_REFERER'),
                    strings_only=True,
                    errors='replace'
                )
                if referer is None:
                    return self._reject(request, django_csrf.REASON_NO_REFERER)

                # Here we generate a list of all acceptable HTTP referers,
                # including the current host since that has been validated
                # upstream.
                good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
                # Note that request.get_host() includes the port.
                good_hosts.append(request.get_host())
                good_referers = ['https://{0}/'.format(host) for host in good_hosts]
                if not any(same_origin(referer, host) for host in good_referers):
                    reason = REASON_BAD_REFERER % referer
                    return self._reject(request, reason)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, django_csrf.REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
                except IOError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                return self._reject(request, django_csrf.REASON_BAD_TOKEN)

        return self._accept(request)
Example #26
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if getattr(request, "csrf_processing_done", False):
            return None

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, "csrf_exempt", False):
            return None

        # Assume that anything not defined as 'safe' by RFC7231 needs protection
        if request.method not in ("GET", "HEAD", "OPTIONS", "TRACE"):
            if getattr(request, "_dont_enforce_csrf_checks", False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # secret we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = request.META.get("HTTP_REFERER")

                # -- Change from original here -- #
                # Only checks referer if it is present.
                # It's not a failure condition if the referer is not present.
                # Our site is HTTPS-only which does not need to rely on
                # referer checking. Above example does not apply.
                if referer is not None:
                    referer = urlparse(referer)

                    # Make sure we have a valid URL for Referer.
                    if "" in (referer.scheme, referer.netloc):
                        return self._reject(request, REASON_MALFORMED_REFERER)

                    # Ensure that our Referer is also secure.
                    if referer.scheme != "https" and not referer.netloc.endswith(
                            ".onion"):
                        return self._reject(request, REASON_INSECURE_REFERER)

                    # If there isn't a CSRF_COOKIE_DOMAIN, require an exact match
                    # match on host:port. If not, obey the cookie rules (or those
                    # for the session cookie, if CSRF_USE_SESSIONS).
                    good_referer = (settings.SESSION_COOKIE_DOMAIN
                                    if settings.CSRF_USE_SESSIONS else
                                    settings.CSRF_COOKIE_DOMAIN)
                    if good_referer is not None:
                        server_port = request.get_port()
                        if server_port not in ("443", "80"):
                            good_referer = "%s:%s" % (good_referer,
                                                      server_port)
                    else:
                        try:
                            # request.get_host() includes the port.
                            good_referer = request.get_host()
                        except DisallowedHost:
                            pass

                    # Create a list of all acceptable HTTP referers, including the
                    # current host if it's permitted by ALLOWED_HOSTS.
                    good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
                    if good_referer is not None:
                        good_hosts.append(good_referer)

                    if not any(
                            is_same_domain(referer.netloc, host)
                            for host in good_hosts):
                        reason = REASON_BAD_REFERER % referer.geturl()
                        return self._reject(request, reason)

            csrf_token = self._get_token(request)
            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    request_csrf_token = request.POST.get(
                        "csrfmiddlewaretoken", "")
                except OSError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get(
                    settings.CSRF_HEADER_NAME, "")

            request_csrf_token = _sanitize_token(request_csrf_token)
            if not _compare_masked_tokens(request_csrf_token, csrf_token):
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Example #27
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if getattr(request, 'csrf_processing_done', False):
            return None

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC7231 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # secret we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = request.META.get('HTTP_REFERER')

                # -- Change from original here -- #
                # Only checks referer if it is present.
                # It's not a failure condition if the referer is not present.
                # Our site is HTTPS-only which does not need to rely on
                # referer checking. Above example does not apply.
                if referer is not None:
                    referer = urlparse(referer)

                    # Make sure we have a valid URL for Referer.
                    if '' in (referer.scheme, referer.netloc):
                        return self._reject(request, REASON_MALFORMED_REFERER)

                    # Ensure that our Referer is also secure.
                    if referer.scheme != 'https':
                        return self._reject(request, REASON_INSECURE_REFERER)

                    # If there isn't a CSRF_COOKIE_DOMAIN, require an exact match
                    # match on host:port. If not, obey the cookie rules (or those
                    # for the session cookie, if CSRF_USE_SESSIONS).
                    good_referer = (
                        settings.SESSION_COOKIE_DOMAIN
                        if settings.CSRF_USE_SESSIONS
                        else settings.CSRF_COOKIE_DOMAIN
                    )
                    if good_referer is not None:
                        server_port = request.get_port()
                        if server_port not in ('443', '80'):
                            good_referer = '%s:%s' % (good_referer, server_port)
                    else:
                        try:
                            # request.get_host() includes the port.
                            good_referer = request.get_host()
                        except DisallowedHost:
                            pass

                    # Create a list of all acceptable HTTP referers, including the
                    # current host if it's permitted by ALLOWED_HOSTS.
                    good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
                    if good_referer is not None:
                        good_hosts.append(good_referer)

                    if not any(is_same_domain(referer.netloc, host) for host in good_hosts):
                        reason = REASON_BAD_REFERER % referer.geturl()
                        return self._reject(request, reason)

            csrf_token = request.META.get('CSRF_COOKIE')
            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
                except IOError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')

            request_csrf_token = _sanitize_token(request_csrf_token)
            if not _compare_salted_tokens(request_csrf_token, csrf_token):
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Example #28
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            cookie_token = request.COOKIES[settings.CSRF_COOKIE_NAME]
        except KeyError:
            csrf_token = None
        else:
            csrf_token = _sanitize_token(cookie_token)
            if csrf_token != cookie_token:
                # Cookie token needed to be replaced;
                # the cookie needs to be reset.
                request.csrf_cookie_needs_reset = True
            # Use same token next time.
            request.META['CSRF_COOKIE'] = csrf_token

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC7231 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # secret we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = force_text(request.META.get('HTTP_REFERER'),
                                     strings_only=True,
                                     errors='replace')
                if referer is not None:
                    referer = urlparse(referer)

                    # Make sure we have a valid URL for Referer.
                    if '' in (referer.scheme, referer.netloc):
                        return self._reject(request, REASON_MALFORMED_REFERER)

                    # Ensure that our Referer is also secure.
                    if referer.scheme != 'https':
                        return self._reject(request, REASON_INSECURE_REFERER)

                    # If there isn't a CSRF_COOKIE_DOMAIN, assume we need an exact
                    # match on host:port. If not, obey the cookie rules.
                    if settings.CSRF_COOKIE_DOMAIN is None:
                        # request.get_host() includes the port.
                        good_referer = request.get_host()
                    else:
                        good_referer = settings.CSRF_COOKIE_DOMAIN
                        server_port = request.get_port()
                        if server_port not in ('443', '80'):
                            good_referer = '%s:%s' % (good_referer,
                                                      server_port)

                    # Here we generate a list of all acceptable HTTP referers,
                    # including the current host since that has been validated
                    # upstream.
                    good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
                    good_hosts.append(good_referer)

                    if not any(
                            is_same_domain(referer.netloc, host)
                            for host in good_hosts):
                        reason = REASON_BAD_REFERER % referer.geturl()
                        return self._reject(request, reason)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    request_csrf_token = request.POST.get(
                        'csrfmiddlewaretoken', '')
                except IOError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get(
                    settings.CSRF_HEADER_NAME, '')

            request_csrf_token = _sanitize_token(request_csrf_token)
            if not _compare_salted_tokens(request_csrf_token, csrf_token):
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Example #29
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            csrf_token = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META['CSRF_COOKIE'] = csrf_token
        except KeyError:
            csrf_token = None
            # Generate token and store it in the request, so it's
            # available to the view.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC2616 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # nonce we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = request.META.get('HTTP_REFERER')
                if referer is None:
                    logger.warning('Forbidden (%s): %s',
                                   REASON_NO_REFERER, request.path,
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port.
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    logger.warning('Forbidden (%s): %s', reason, request.path,
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, reason)
            
            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                logger.warning('Forbidden (%s): %s',
                               REASON_NO_CSRF_COOKIE, request.path,
                    extra={
                        'status_code': 403,
                        'request': request,
                    }
                )
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get('HTTP_X_XSRF_TOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                logger.warning('Forbidden (%s): %s',
                               REASON_BAD_TOKEN, request.path,
                    extra={
                        'status_code': 403,
                        'request': request,
                    }
                )
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            csrf_token = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META['CSRF_COOKIE'] = csrf_token
        except KeyError:
            csrf_token = None
            # Generate token and store it in the request, so it's
            # available to the view.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC2616 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                logger.warning('Forbidden (%s): %s',
                               REASON_NO_CSRF_COOKIE,
                               request.path,
                               extra={
                                   'status_code': 403,
                                   'request': request,
                               })
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                request_csrf_token = request.POST.get('csrfmiddlewaretoken',
                                                      '')

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                logger.warning('Forbidden (%s): %s',
                               REASON_BAD_TOKEN,
                               request.path,
                               extra={
                                   'status_code': 403,
                                   'request': request,
                               })
                return self._reject(request, REASON_BAD_TOKEN)

        resp = self._accept(request)

        request.META["CSRF_COOKIE_USED"] = True
        return resp
Example #31
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            request.META["CSRF_COOKIE"] = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            cookie_is_new = False
        except KeyError:
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()
            cookie_is_new = True

        if getattr(callback, 'csrf_exempt', False):
            return None

        if request.method == 'POST':
            if getattr(request, '_dont_enforce_csrf_checks', False):
                return self._accept(request)
            # let initial signed requests pass
            if 'signed_request' in request.POST:
                post = request.POST.copy()
                post.pop('signed_request')
                if len(post) == 0:
                    return self._accept(request)

            if request.is_secure() and getattr(settings,
                                               'HTTPS_REFERER_REQUIRED', True):
                referer = request.META.get('HTTP_REFERER')
                if referer is None:
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_NO_REFERER, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    logger.warning('Forbidden (%s): %s' %
                                   (reason, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, reason)

            if cookie_is_new:
                try:
                    session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
                    csrf_token = _make_legacy_session_token(session_id)
                except KeyError:
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_NO_COOKIE, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_NO_COOKIE)
            else:
                csrf_token = request.META["CSRF_COOKIE"]

            # check incoming token
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', None)
            if not request_csrf_token:
                request_csrf_token = request.POST.get('state', '')
            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                if cookie_is_new:
                    # probably a problem setting the CSRF cookie
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_NO_CSRF_COOKIE, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_NO_CSRF_COOKIE)
                else:
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_BAD_TOKEN, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Example #32
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            request.META["CSRF_COOKIE"] = _sanitize_token(request.COOKIES[settings.CSRF_COOKIE_NAME])
            cookie_is_new = False
        except KeyError:
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()
            cookie_is_new = True

        if getattr(callback, 'csrf_exempt', False):
            return None

        if request.method == 'POST':
            if getattr(request, '_dont_enforce_csrf_checks', False):
                return self._accept(request)

            if request.is_secure() and getattr(settings, 'HTTPS_REFERER_REQUIRED', True):
                referer = request.META.get('HTTP_REFERER')
                if referer is None :
                    logger.warning('Forbidden (%s): %s' % (REASON_NO_REFERER, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    logger.warning('Forbidden (%s): %s' % (reason, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, reason)

            if cookie_is_new:
                try:
                    session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
                    csrf_token = _make_legacy_session_token(session_id)
                except KeyError:
                    logger.warning('Forbidden (%s): %s' % (REASON_NO_COOKIE, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_COOKIE)
            else:
                csrf_token = request.META["CSRF_COOKIE"]

            # check incoming token
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', None) 
            if not request_csrf_token:
                request_csrf_token = request.POST.get('state', '')
            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                if cookie_is_new:
                    # probably a problem setting the CSRF cookie
                    logger.warning('Forbidden (%s): %s' % (REASON_NO_CSRF_COOKIE, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_CSRF_COOKIE)
                else:
                    logger.warning('Forbidden (%s): %s' % (REASON_BAD_TOKEN, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Example #33
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if getattr(request, "csrf_processing_done", False):
            return None

        try:
            cookie_token = request.COOKIES[settings.CSRF_COOKIE_NAME]
        except KeyError:
            csrf_token = None
        else:
            csrf_token = _sanitize_token(cookie_token)
            if csrf_token != cookie_token:
                # Cookie token needed to be replaced;
                # the cookie needs to be reset.
                request.csrf_cookie_needs_reset = True
            # Use same token next time.
            request.META["CSRF_COOKIE"] = csrf_token

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, "csrf_exempt", False):
            return None

        # Assume that anything not defined as 'safe' by RFC7231 needs protection
        if request.method not in ("GET", "HEAD", "OPTIONS", "TRACE"):
            if getattr(request, "_dont_enforce_csrf_checks", False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # secret we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = force_text(request.META.get("HTTP_REFERER"), strings_only=True, errors="replace")
                if referer is not None:
                    referer = urlparse(referer)

                    # Make sure we have a valid URL for Referer.
                    if "" in (referer.scheme, referer.netloc):
                        return self._reject(request, REASON_MALFORMED_REFERER)

                    # Ensure that our Referer is also secure.
                    if referer.scheme != "https":
                        return self._reject(request, REASON_INSECURE_REFERER)

                    # If there isn't a CSRF_COOKIE_DOMAIN, assume we need an exact
                    # match on host:port. If not, obey the cookie rules.
                    if settings.CSRF_COOKIE_DOMAIN is None:
                        # request.get_host() includes the port.
                        good_referer = request.get_host()
                    else:
                        good_referer = settings.CSRF_COOKIE_DOMAIN
                        server_port = request.get_port()
                        if server_port not in ("443", "80"):
                            good_referer = "%s:%s" % (good_referer, server_port)

                    # Here we generate a list of all acceptable HTTP referers,
                    # including the current host since that has been validated
                    # upstream.
                    good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
                    good_hosts.append(good_referer)

                    if not any(is_same_domain(referer.netloc, host) for host in good_hosts):
                        reason = REASON_BAD_REFERER % referer.geturl()
                        return self._reject(request, reason)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    request_csrf_token = request.POST.get("csrfmiddlewaretoken", "")
                except IOError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, "")

            request_csrf_token = _sanitize_token(request_csrf_token)
            if not _compare_salted_tokens(request_csrf_token, csrf_token):
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)