1
0
mirror of https://github.com/django/django.git synced 2025-10-29 00:26:07 +00:00

Fixed #15617 - CSRF referer checking too strict

Thanks to adam for the report.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15840 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Luke Plant
2011-03-15 20:37:09 +00:00
parent ad4118be44
commit 243d0bec19
5 changed files with 58 additions and 3 deletions

View File

@@ -13,6 +13,7 @@ from django.conf import settings
from django.core.urlresolvers import get_callable
from django.utils.cache import patch_vary_headers
from django.utils.hashcompat import md5_constructor
from django.utils.http import same_origin
from django.utils.log import getLogger
from django.utils.safestring import mark_safe
from django.utils.crypto import constant_time_compare
@@ -161,10 +162,9 @@ class CsrfViewMiddleware(object):
)
return self._reject(request, REASON_NO_REFERER)
# The following check ensures that the referer is HTTPS,
# the domains match and the ports match - the same origin policy.
# Note that request.get_host() includes the port
good_referer = 'https://%s/' % request.get_host()
if not referer.startswith(good_referer):
if not same_origin(referer, good_referer):
reason = REASON_BAD_REFERER % (referer, good_referer)
logger.warning('Forbidden (%s): %s' % (reason, request.path),
extra={

View File

@@ -3,6 +3,7 @@ import datetime
import re
import sys
import urllib
import urlparse
from email.Utils import formatdate
from django.utils.encoding import smart_str, force_unicode
@@ -186,3 +187,20 @@ def quote_etag(etag):
"""
return '"%s"' % etag.replace('\\', '\\\\').replace('"', '\\"')
if sys.version_info >= (2, 6):
def same_origin(url1, url2):
"""
Checks if two URLs are 'same-origin'
"""
p1, p2 = urlparse.urlparse(url1), urlparse.urlparse(url2)
return (p1.scheme, p1.hostname, p1.port) == (p2.scheme, p2.hostname, p2.port)
else:
# Python 2.4, 2.5 compatibility. This actually works for Python 2.6 and
# above, but the above definition is much more obviously correct and so is
# preferred going forward.
def same_origin(url1, url2):
"""
Checks if two URLs are 'same-origin'
"""
p1, p2 = urlparse.urlparse(url1), urlparse.urlparse(url2)
return p1[0:2] == p2[0:2]