+29
-11
lines changedFilter options
+29
-11
lines changed Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
4
4
import time
5
5
from pprint import pformat
6
6
from urllib import urlencode, quote
7
-
from urlparse import urljoin
7
+
from urlparse import urljoin, urlparse
8
8
try:
9
9
from cStringIO import StringIO
10
10
except ImportError:
@@ -117,6 +117,7 @@ def __init__(self, *args, **kwargs):
117
117
warnings.warn("CompatCookie is deprecated, use django.http.SimpleCookie instead.",
118
118
PendingDeprecationWarning)
119
119
120
+
from django.core.exceptions import SuspiciousOperation
120
121
from django.utils.datastructures import MultiValueDict, ImmutableList
121
122
from django.utils.encoding import smart_str, iri_to_uri, force_unicode
122
123
from django.utils.http import cookie_date
@@ -635,19 +636,21 @@ def tell(self):
635
636
raise Exception("This %s instance cannot tell its position" % self.__class__)
636
637
return sum([len(chunk) for chunk in self._container])
637
638
638
-
class HttpResponseRedirect(HttpResponse):
639
-
status_code = 302
639
+
class HttpResponseRedirectBase(HttpResponse):
640
+
allowed_schemes = ['http', 'https', 'ftp']
640
641
641
642
def __init__(self, redirect_to):
642
-
super(HttpResponseRedirect, self).__init__()
643
+
super(HttpResponseRedirectBase, self).__init__()
644
+
parsed = urlparse(redirect_to)
645
+
if parsed.scheme and parsed.scheme not in self.allowed_schemes:
646
+
raise SuspiciousOperation("Unsafe redirect to URL with scheme '%s'" % parsed.scheme)
643
647
self['Location'] = iri_to_uri(redirect_to)
644
648
645
-
class HttpResponsePermanentRedirect(HttpResponse):
646
-
status_code = 301
649
+
class HttpResponseRedirect(HttpResponseRedirectBase):
650
+
status_code = 302
647
651
648
-
def __init__(self, redirect_to):
649
-
super(HttpResponsePermanentRedirect, self).__init__()
650
-
self['Location'] = iri_to_uri(redirect_to)
652
+
class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
653
+
status_code = 301
651
654
652
655
class HttpResponseNotModified(HttpResponse):
653
656
status_code = 304
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
1
1
import copy
2
2
import pickle
3
3
4
-
from django.http import (QueryDict, HttpResponse, SimpleCookie, BadHeaderError,
5
-
parse_cookie)
4
+
from django.core.exceptions import SuspiciousOperation
5
+
from django.http import (QueryDict, HttpResponse, HttpResponseRedirect,
6
+
HttpResponsePermanentRedirect,
7
+
SimpleCookie, BadHeaderError,
8
+
parse_cookie)
6
9
from django.utils import unittest
7
10
8
11
class QueryDictTests(unittest.TestCase):
@@ -243,6 +246,18 @@ def test_newlines_in_headers(self):
243
246
self.assertRaises(BadHeaderError, r.__setitem__, 'test\rstr', 'test')
244
247
self.assertRaises(BadHeaderError, r.__setitem__, 'test\nstr', 'test')
245
248
249
+
def test_unsafe_redirects(self):
250
+
bad_urls = [
251
+
'data:text/html,<script>window.alert("xss")</script>',
252
+
'mailto:test@example.com',
253
+
'file:///etc/passwd',
254
+
]
255
+
for url in bad_urls:
256
+
self.assertRaises(SuspiciousOperation,
257
+
HttpResponseRedirect, url)
258
+
self.assertRaises(SuspiciousOperation,
259
+
HttpResponsePermanentRedirect, url)
260
+
246
261
class CookieTests(unittest.TestCase):
247
262
def test_encode(self):
248
263
"""
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4