示例#1
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")
示例#2
0
 def _check_csrf(self, state):
     # validate state parameter
     if state is None or \
       not re.search('[a-zA-Z0-9]', state) or \
       not len(state) == CSRF_TOKEN_LENGTH or \
       not _compare_salted_tokens(state, get_token(self.request)):
         self.context['message'] = {'error': 'bad_state'}
示例#3
0
    def get(self, request, **kwargs):
        provider = kwargs.get('provider')

        if provider == 'naver':
            csrf_token = request.GET.get('state')
            code = request.GET.get('code')

            if not _compare_salted_tokens(
                    csrf_token, request.COOKIES.get(
                        'csrftoken')):  # state(csrf_token)이 잘못된 경우
                messages.error(request,
                               '잘못된 경로로 로그인하셨습니다.',
                               extra_tags='social_error')
                return HttpResponseRedirect(self.failure_url)
            is_success, data = self.login_or_create_with_naver(
                csrf_token, code)
            if not is_success:  # 로그인 or 생성 실패
                if type(
                        data
                ) is list:  # profile.confirm 이 False 일때는 data가 리스트형태로 리턴
                    user = data[2]
                    self.send_verification_email(user)
                    messages.error(request, data[0], extra_tags='social_error')
                    return HttpResponseRedirect(data[1])
                else:
                    messages.error(request, data, extra_tags='social_error')
            return HttpResponseRedirect(
                data if is_success else self.failure_url)
        else:
            return HttpResponseRedirect(self.failure_url)
示例#4
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)
示例#5
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)
示例#6
0
文件: views.py 项目: bquadre/tendenci
    def get(self, request):
        code = request.GET.get('code')
        state = request.GET.get('state', None)
        csrf_token = request.META.get("CSRF_COOKIE", None)

        if not code:
            raise Http404
        # if csrf_token doesn't match, raise 403
        if not _compare_salted_tokens(state, csrf_token):
            raise Http403

        # fetch access token
        r = requests.post(STRIPE_TOKEN_URL,
                          data = {'client_secret': settings.STRIPE_SECRET_KEY,
                                 'grant_type': 'authorization_code',
                                 'code': code,
                                 'scope': 'read_only'})
        response_json = r.json()
        if r.ok:
            stripe_user_id = response_json['stripe_user_id']
#             livemode = response_json['livemode']
            sa, created = StripeAccount.objects.get_or_create(stripe_user_id=stripe_user_id)
#             if livemode:
#                 sa.livemode_access_token = response_json['access_token']
#                 sa.livemode_stripe_publishable_key = response_json['stripe_publishable_key']
#             else:
#                 sa.testmode_access_token = response_json['access_token']
#                 sa.testmode_stripe_publishable_key = response_json['stripe_publishable_key']
            sa.scope = response_json['scope']
#             sa.token_type = response_json['token_type']
#             sa.refresh_token = response_json['refresh_token']
            if not sa.creator:
                sa.creator = request.user
                sa.creator_username = request.user.username
            sa.owner = request.user
            sa.owner_username = request.user.username
            sa.status_detail='active'
            sa.save()
            
            # retrieve account info
            stripe.api_key = settings.STRIPE_SECRET_KEY
            stripe.api_version = settings.STRIPE_API_VERSION
            stripe_set_app_info(stripe)
            account = stripe.Account.retrieve(stripe_user_id)
            sa.account_name = account.get('display_name', '')
            sa.email = account.get('email', '')
            sa.default_currency = account.get('default_currency', '')
            sa.country = account.get('country', '')
            sa.save()
        
            msg_string = _('Success!')
        else:
            sa = None
            msg_string = '{0} - {1}'.format(response_json['error'], response_json['error_description'])

        return render(request, self.template_name, {'sa': sa, 'msg_string': msg_string})
    def _check_csrf(self, state):
        # CSRF validation does not work with http
        if config.DEBUG and self.request.scheme == "http":
            return

        # validate state parameter
        if (state is None or not re.search("[a-zA-Z0-9]", state)
                or not len(state) == CSRF_TOKEN_LENGTH
                or not _compare_salted_tokens(state, get_token(self.request))):
            self.context["message"] = {"error": "bad_state"}
示例#8
0
 def clean_csrf_token(cls, csrf_token, payload):
     is_valid = _compare_salted_tokens(csrf_token, payload["csrfToken"])
     if not is_valid:
         raise ValidationError({
             "csrfToken":
             ValidationError(
                 "Invalid csrf token",
                 code=AccountErrorCode.JWT_INVALID_CSRF_TOKEN.value,
             )
         })
    def test_login_example(self):
        """
        Example of successful login as user would do for real,
        starting at base url and getting all other urls and info from there.
        """
        # Create test user and get username & password for use below
        user = self.new_user()
        username = password = user.getOmeName().val

        # Django client, not logged in yet
        django_client = Client()
        # Start at the /api/ url to list versions...
        request_url = reverse('api_versions')
        rsp = get_json(django_client, request_url)
        # Pick the last version
        version = rsp['data'][-1]
        base_url = version['url:base']
        # Base url will give a bunch of other urls
        base_rsp = get_json(django_client, base_url)
        login_url = base_rsp['url:login']
        servers_url = base_rsp['url:servers']
        login_url = base_rsp['url:login']
        token_url = base_rsp['url:token']
        # See what servers we can log in to
        servers_rsp = get_json(django_client, servers_url)
        server_id = servers_rsp['data'][0]['id']
        # Need a CSRF token
        token_rsp = get_json(django_client, token_url)
        token = token_rsp['data']

        # Can also get this from our session cookies
        csrf_token = django_client.cookies['csrftoken'].value
        assert csrf._compare_salted_tokens(token, csrf_token) is True
        # Now we have all info we need for login.
        # Set the header, so we don't need to do this for every POST/PUT/DELETE
        # OR we could add it to each POST as 'csrfmiddlewaretoken'
        django_client = Client(HTTP_X_CSRFTOKEN=token)
        data = {
            'username': username,
            'password': password,
            'server': server_id,
            # 'csrfmiddlewaretoken': token,
        }
        login_rsp = django_client.post(login_url, data)
        login_json = json.loads(login_rsp.content)
        assert login_json['success']
        event_context = login_json['eventContext']
        # eventContext gives a bunch of info
        member_of_groups = event_context['memberOfGroups']
        current_group = event_context['groupId']
        user_id = event_context['userId']
        assert len(member_of_groups) == 2  # includes 'user' group
        assert current_group in member_of_groups
        assert user_id > 0
示例#10
0
    def authenticate_client(self, msg: Dict[str, Any]) -> None:
        if self.authenticated:
            self.session.send_message({'req_id': msg['req_id'], 'type': 'response',
                                       'response': {'result': 'error',
                                                    'msg': 'Already authenticated'}})
            return

        user_profile = get_user_profile(self.browser_session_id)
        if user_profile is None:
            raise JsonableError(_('Unknown or missing session'))
        self.session.user_profile = user_profile

        if 'csrf_token' not in msg['request']:
            # Debugging code to help with understanding #6961
            logging.error("Invalid websockets auth request: %s" % (msg['request'],))
            raise JsonableError(_('CSRF token entry missing from request'))
        if not _compare_salted_tokens(msg['request']['csrf_token'], self.csrf_token):
            raise JsonableError(_('CSRF token does not match that in cookie'))

        if 'queue_id' not in msg['request']:
            raise JsonableError(_("Missing 'queue_id' argument"))

        queue_id = msg['request']['queue_id']
        client = get_client_descriptor(queue_id)
        if client is None:
            raise BadEventQueueIdError(queue_id)

        if user_profile.id != client.user_profile_id:
            raise JsonableError(_("You are not the owner of the queue with id '%s'") % (queue_id,))

        self.authenticated = True
        register_connection(queue_id, self)

        response = {'req_id': msg['req_id'], 'type': 'response',
                    'response': {'result': 'success', 'msg': ''}}

        status_inquiries = msg['request'].get('status_inquiries')
        if status_inquiries is not None:
            results = {}  # type: Dict[str, Dict[str, str]]
            for inquiry in status_inquiries:
                status = redis_client.hgetall(req_redis_key(inquiry))  # type: Dict[bytes, bytes]
                if len(status) == 0:
                    result = {'status': 'not_received'}
                elif b'response' not in status:
                    result = {'status': status[b'status'].decode('utf-8')}
                else:
                    result = {'status': status[b'status'].decode('utf-8'),
                              'response': ujson.loads(status[b'response'])}
                results[str(inquiry)] = result
            response['response']['status_inquiries'] = results

        self.session.send_message(response)
        ioloop = tornado.ioloop.IOLoop.instance()
        ioloop.remove_timeout(self.timeout_handle)
示例#11
0
    def authenticate_client(self, msg: Dict[str, Any]) -> None:
        if self.authenticated:
            self.session.send_message({'req_id': msg['req_id'], 'type': 'response',
                                       'response': {'result': 'error',
                                                    'msg': 'Already authenticated'}})
            return

        user_profile = get_user_profile(self.browser_session_id)
        if user_profile is None:
            raise JsonableError(_('Unknown or missing session'))
        self.session.user_profile = user_profile

        if 'csrf_token' not in msg['request']:
            # Debugging code to help with understanding #6961
            logging.error("CSRF token missing from websockets auth request: %s" % (msg['request'],))
            raise JsonableError(_('CSRF token entry missing from request'))
        if not _compare_salted_tokens(msg['request']['csrf_token'], self.csrf_token):
            raise JsonableError(_('CSRF token does not match that in cookie'))

        if 'queue_id' not in msg['request']:
            raise JsonableError(_("Missing 'queue_id' argument"))

        queue_id = msg['request']['queue_id']
        client = get_client_descriptor(queue_id)
        if client is None:
            raise BadEventQueueIdError(queue_id)

        if user_profile.id != client.user_profile_id:
            raise JsonableError(_("You are not the owner of the queue with id '%s'") % (queue_id,))

        self.authenticated = True
        register_connection(queue_id, self)

        response = {'req_id': msg['req_id'], 'type': 'response',
                    'response': {'result': 'success', 'msg': ''}}

        status_inquiries = msg['request'].get('status_inquiries')
        if status_inquiries is not None:
            results = {}  # type: Dict[str, Dict[str, str]]
            for inquiry in status_inquiries:
                status = redis_client.hgetall(req_redis_key(inquiry))  # type: Dict[bytes, bytes]
                if len(status) == 0:
                    result = {'status': 'not_received'}
                elif b'response' not in status:
                    result = {'status': status[b'status'].decode('utf-8')}
                else:
                    result = {'status': status[b'status'].decode('utf-8'),
                              'response': ujson.loads(status[b'response'])}
                results[str(inquiry)] = result
            response['response']['status_inquiries'] = results

        self.session.send_message(response)
        ioloop = tornado.ioloop.IOLoop.instance()
        ioloop.remove_timeout(self.timeout_handle)
示例#12
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)
示例#13
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)
示例#14
0
    def get(self, request, *args, **kwargs):

        provider = kwargs.get('provider')

        if provider == 'naver': # 프로바이더가 naver 일 경우
            csrf_token = request.GET.get('state')
            code = request.GET.get('code')
            if not _compare_salted_tokens(csrf_token, request.COOKIES.get('csrftoken')): # state(csrf_token)이 잘못된 경우
                messages.error(request, '잘못된 경로로 로그인하셨습니다.', extra_tags='danger')
                return HttpResponseRedirect(self.failure_url)
            is_success, error = self.login_with_naver(csrf_token, code)
            if not is_success: # 로그인 실패할 경우
                messages.error(request, error, extra_tags='danger')
            return HttpResponseRedirect(self.success_url if is_success else self.failure_url)

        return HttpResponseRedirect(self.failure_url)
示例#15
0
    def authenticate_client(self, msg):
        # type: (Dict[str, Any]) -> None
        if self.authenticated:
            self.session.send_message({'req_id': msg['req_id'], 'type': 'response',
                                       'response': {'result': 'error', 'msg': 'Already authenticated'}})
            return

        user_profile = get_user_profile(self.browser_session_id)
        if user_profile is None:
            raise SocketAuthError('Unknown or missing session')
        self.session.user_profile = user_profile

        if not _compare_salted_tokens(msg['request']['csrf_token'], self.csrf_token):
            raise SocketAuthError('CSRF token does not match that in cookie')

        if 'queue_id' not in msg['request']:
            raise SocketAuthError("Missing 'queue_id' argument")

        queue_id = msg['request']['queue_id']
        client = get_client_descriptor(queue_id)
        if client is None:
            raise SocketAuthError('Bad event queue id: %s' % (queue_id,))

        if user_profile.id != client.user_profile_id:
            raise SocketAuthError("You are not the owner of the queue with id '%s'" % (queue_id,))

        self.authenticated = True
        register_connection(queue_id, self)

        response = {'req_id': msg['req_id'], 'type': 'response',
                    'response': {'result': 'success', 'msg': ''}}

        status_inquiries = msg['request'].get('status_inquiries')
        if status_inquiries is not None:
            results = {}
            for inquiry in status_inquiries:
                status = redis_client.hgetall(req_redis_key(inquiry))
                if len(status) == 0:
                    status['status'] = 'not_received'
                if 'response' in status:
                    status['response'] = ujson.loads(status['response'])
                results[str(inquiry)] = status
            response['response']['status_inquiries'] = results

        self.session.send_message(response)
        ioloop = tornado.ioloop.IOLoop.instance()
        ioloop.remove_timeout(self.timeout_handle)
示例#16
0
    def authenticate_client(self, msg):
        # type: (Dict[str, Any]) -> None
        if self.authenticated:
            self.session.send_message({'req_id': msg['req_id'], 'type': 'response',
                                       'response': {'result': 'error', 'msg': 'Already authenticated'}})
            return

        user_profile = get_user_profile(self.browser_session_id)
        if user_profile is None:
            raise SocketAuthError('Unknown or missing session')
        self.session.user_profile = user_profile

        if not _compare_salted_tokens(msg['request']['csrf_token'], self.csrf_token):
            raise SocketAuthError('CSRF token does not match that in cookie')

        if 'queue_id' not in msg['request']:
            raise SocketAuthError("Missing 'queue_id' argument")

        queue_id = msg['request']['queue_id']
        client = get_client_descriptor(queue_id)
        if client is None:
            raise SocketAuthError('Bad event queue id: %s' % (queue_id,))

        if user_profile.id != client.user_profile_id:
            raise SocketAuthError("You are not the owner of the queue with id '%s'" % (queue_id,))

        self.authenticated = True
        register_connection(queue_id, self)

        response = {'req_id': msg['req_id'], 'type': 'response',
                    'response': {'result': 'success', 'msg': ''}}

        status_inquiries = msg['request'].get('status_inquiries')
        if status_inquiries is not None:
            results = {}
            for inquiry in status_inquiries:
                status = redis_client.hgetall(req_redis_key(inquiry))
                if len(status) == 0:
                    status['status'] = 'not_received'
                if 'response' in status:
                    status['response'] = ujson.loads(status['response'])
                results[str(inquiry)] = status
            response['response']['status_inquiries'] = results

        self.session.send_message(response)
        ioloop = tornado.ioloop.IOLoop.instance()
        ioloop.remove_timeout(self.timeout_handle)
示例#17
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)
示例#18
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)
示例#19
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)