1 | #!/usr/bin/env python
|
---|
2 | import re
|
---|
3 | import logging
|
---|
4 |
|
---|
5 | from urlparse import urlparse
|
---|
6 |
|
---|
7 | import django.http
|
---|
8 | from django.conf import settings
|
---|
9 |
|
---|
10 | class HttpResponseSafeRedirect(django.http.HttpResponse):
|
---|
11 | status_code = 302
|
---|
12 |
|
---|
13 | def __init__(self, redirect_to, whitelist=[], fallback_to=None):
|
---|
14 | django.http.HttpResponse.__init__(self)
|
---|
15 |
|
---|
16 | self['Location'] = redirect_to
|
---|
17 |
|
---|
18 | if urlparse(self['Location']).scheme:
|
---|
19 | effective_whitelist = set(whitelist + getattr(settings, 'REDIRECT_WHITELIST', []))
|
---|
20 |
|
---|
21 | matched = False
|
---|
22 |
|
---|
23 | for pattern in effective_whitelist:
|
---|
24 | matched = re.compile(pattern).match(self['Location'])
|
---|
25 |
|
---|
26 | if matched:
|
---|
27 | break
|
---|
28 |
|
---|
29 | if not matched:
|
---|
30 | logging.warn("found open redirect attack to %s", self['Location'])
|
---|
31 |
|
---|
32 | self['Location'] = fallback_to or settings.LOGIN_REDIRECT_URL
|
---|
33 |
|
---|
34 | def hack_django(cls, *args, **kwds):
|
---|
35 | if hasattr(settings, 'REDIRECT_WHITELIST'):
|
---|
36 | return HttpResponseSafeRedirect(*args, **kwds)
|
---|
37 | else:
|
---|
38 | print "WARN: Use REDIRECT_WHITELIST setting and protect your end user " \
|
---|
39 | "from the open redirect vulnerability. <http://www.owasp.org/index.php/Open_redirect>"
|
---|
40 |
|
---|
41 | return object.__new__(cls, *args, **kwds)
|
---|
42 |
|
---|
43 | django.http.HttpResponseRedirect.__new__ = staticmethod(hack_django)
|
---|