Projet

Général

Profil

0001-wcs-disallow-redirects-to-unknown-services-after-tra.patch

Frédéric Péters, 27 novembre 2019 14:18

Télécharger (3,86 ko)

Voir les différences:

Subject: [PATCH] wcs: disallow redirects to unknown services after tracking
 code error (#37996)

 combo/apps/wcs/views.py |  6 +++++-
 combo/utils/misc.py     | 14 ++++++++++++++
 tests/test_wcs.py       | 14 ++++++++++----
 3 files changed, 29 insertions(+), 5 deletions(-)
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
-