0001-wcs-disallow-redirects-to-unknown-services-after-tra.patch
combo/apps/wcs/views.py | ||
---|---|---|
18 | 18 | |
19 | 19 |
from django.contrib import messages |
20 | 20 |
from django.conf import settings |
21 |
from django.core.exceptions import PermissionDenied |
|
21 |
from django.core.exceptions import DisallowedRedirect, PermissionDenied
|
|
22 | 22 |
from django.core.urlresolvers import reverse |
23 | 23 |
from django.http import JsonResponse, HttpResponseRedirect, HttpResponseBadRequest |
24 | 24 |
from django.utils.http import urlquote |
... | ... | |
33 | 33 |
from .utils import get_wcs_services |
34 | 34 | |
35 | 35 |
from combo.utils import requests |
36 |
from combo.utils.misc import is_url_from_known_service |
|
36 | 37 | |
37 | 38 | |
38 | 39 |
class TrackingCodeView(View): |
... | ... | |
86 | 87 |
redirect_to_other_domain = bool( |
87 | 88 |
next_netloc and next_netloc != urlparse.urlparse(request.build_absolute_uri()).netloc) |
88 | 89 | |
90 |
if redirect_to_other_domain and not is_url_from_known_service(next_url): |
|
91 |
raise DisallowedRedirect('Unsafe redirect to unknown host') |
|
92 | ||
89 | 93 |
try: |
90 | 94 |
url = self.search(code, request, wcs_site=cell.wcs_site) |
91 | 95 |
except PermissionDenied: |
combo/utils/misc.py | ||
---|---|---|
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 | 17 |
from django.utils.six.moves.html_parser import HTMLParser |
18 |
from django.utils.six.moves.urllib import parse as urlparse |
|
18 | 19 | |
20 |
from django.conf import settings |
|
19 | 21 |
from django.template.context import BaseContext |
20 | 22 |
from django.utils.html import strip_tags |
21 | 23 | |
... | ... | |
37 | 39 |
else: |
38 | 40 |
flat_context.update(context) |
39 | 41 |
return flat_context |
42 | ||
43 | ||
44 |
def is_url_from_known_service(url): |
|
45 |
netloc = urlparse.urlparse(url).netloc |
|
46 |
if not netloc: |
|
47 |
return True |
|
48 |
for service_id in settings.KNOWN_SERVICES or {}: |
|
49 |
for service_key in settings.KNOWN_SERVICES[service_id]: |
|
50 |
service = settings.KNOWN_SERVICES[service_id][service_key] |
|
51 |
if urlparse.urlparse(service.get('url')).netloc == netloc: |
|
52 |
return True |
|
53 |
return False |
tests/test_wcs.py | ||
---|---|---|
756 | 756 | |
757 | 757 |
# simulate cell being displayed on a different site |
758 | 758 |
resp = app.get('/') |
759 |
resp.form['url'] = 'http://example.net/'
|
|
759 |
resp.form['url'] = 'http://example.org/'
|
|
760 | 760 |
resp.form['code'] = 'CNPHNTFB' |
761 | 761 |
resp = resp.form.submit() |
762 |
assert resp.location == 'http://example.net/?unknown-tracking-code'
|
|
762 |
assert resp.location == 'http://example.org/?unknown-tracking-code'
|
|
763 | 763 | |
764 | 764 |
resp = app.get('/') |
765 |
resp.form['url'] = 'http://example.net/?foo=bar'
|
|
765 |
resp.form['url'] = 'http://example.org/?foo=bar'
|
|
766 | 766 |
resp.form['code'] = 'CNPHNTFB' |
767 | 767 |
resp = resp.form.submit() |
768 |
assert resp.location == 'http://example.net/?foo=bar&unknown-tracking-code' |
|
768 |
assert resp.location == 'http://example.org/?foo=bar&unknown-tracking-code' |
|
769 | ||
770 |
# redirect to an unknown site |
|
771 |
resp = app.get('/') |
|
772 |
resp.form['url'] = 'http://example.net/' |
|
773 |
resp.form['code'] = 'CNPHNTFB' |
|
774 |
resp = resp.form.submit(status=400) |
|
769 | 775 | |
770 | 776 |
# error handling |
771 | 777 |
resp = app.get('/') |
772 |
- |