wcs: disallow redirects to unknown services after tracking code error (#37996)

This commit is contained in:
Frédéric Péters 2019-11-27 14:18:13 +01:00
parent fd93d0b904
commit 35e910d2aa
3 changed files with 29 additions and 5 deletions

View File

@ -18,7 +18,7 @@ import re
from django.contrib import messages
from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.core.exceptions import DisallowedRedirect, PermissionDenied
from django.core.urlresolvers import reverse
from django.http import JsonResponse, HttpResponseRedirect, HttpResponseBadRequest
from django.utils.http import urlquote
@ -33,6 +33,7 @@ from .models import TrackingCodeInputCell
from .utils import get_wcs_services
from combo.utils import requests
from combo.utils.misc import is_url_from_known_service
class TrackingCodeView(View):
@ -86,6 +87,9 @@ class TrackingCodeView(View):
redirect_to_other_domain = bool(
next_netloc and next_netloc != urlparse.urlparse(request.build_absolute_uri()).netloc)
if redirect_to_other_domain and not is_url_from_known_service(next_url):
raise DisallowedRedirect('Unsafe redirect to unknown host')
try:
url = self.search(code, request, wcs_site=cell.wcs_site)
except PermissionDenied:

View File

@ -15,7 +15,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.utils.six.moves.html_parser import HTMLParser
from django.utils.six.moves.urllib import parse as urlparse
from django.conf import settings
from django.template.context import BaseContext
from django.utils.html import strip_tags
@ -37,3 +39,15 @@ def flatten_context(context):
else:
flat_context.update(context)
return flat_context
def is_url_from_known_service(url):
netloc = urlparse.urlparse(url).netloc
if not netloc:
return True
for service_id in settings.KNOWN_SERVICES or {}:
for service_key in settings.KNOWN_SERVICES[service_id]:
service = settings.KNOWN_SERVICES[service_id][service_key]
if urlparse.urlparse(service.get('url')).netloc == netloc:
return True
return False

View File

@ -756,16 +756,22 @@ def test_tracking_code_cell(app, nocache):
# simulate cell being displayed on a different site
resp = app.get('/')
resp.form['url'] = 'http://example.net/'
resp.form['url'] = 'http://example.org/'
resp.form['code'] = 'CNPHNTFB'
resp = resp.form.submit()
assert resp.location == 'http://example.net/?unknown-tracking-code'
assert resp.location == 'http://example.org/?unknown-tracking-code'
resp = app.get('/')
resp.form['url'] = 'http://example.net/?foo=bar'
resp.form['url'] = 'http://example.org/?foo=bar'
resp.form['code'] = 'CNPHNTFB'
resp = resp.form.submit()
assert resp.location == 'http://example.net/?foo=bar&unknown-tracking-code'
assert resp.location == 'http://example.org/?foo=bar&unknown-tracking-code'
# redirect to an unknown site
resp = app.get('/')
resp.form['url'] = 'http://example.net/'
resp.form['code'] = 'CNPHNTFB'
resp = resp.form.submit(status=400)
# error handling
resp = app.get('/')