55from django .contrib import messages
66from django .contrib .auth .models import User
77from django .db import transaction
8+ from django .urls import reverse
89
910from cl .lib .crypto import md5
1011from cl .users .models import UserProfile
1112
13+ from django .utils .http import is_safe_url
14+
1215
1316def sanitize_redirection (request ):
1417 """Security and sanity checks on redirections.
1518
16- Much of this code was grabbed from Django. The basic idea here is to:
19+ Much of this code was grabbed from Django:
20+
1721 1. Prevent open redirect attacks. Imagine getting an email:
1822
1923 Subject: Your CourtListener account is conformed
@@ -22,28 +26,28 @@ def sanitize_redirection(request):
2226 Without proper redirect sanitation, a user might click that link, and get
2327 redirected to cortlistener.com, which could be a spoof of the real thing.
2428
25- 2. Prevent illogical redirects. Like, don't let people redirect back to
26- the sign-in page, for example.
29+ 1. Prevent illogical redirects. Like, don't let people redirect back to
30+ the sign-in or register page.
31+
32+ 1. Prevent garbage URLs (like empty ones or ones with spaces)
33+
34+ 1. Prevent dangerous URLs (like JavaScript)
2735
2836 :return: Either the value requested or the default LOGIN_REDIRECT_URL, if
2937 a sanity or security check failed.
3038 """
3139 redirect_to = request .GET .get ("next" , "" )
32- if "sign-in" in redirect_to :
33- # thus, we don't redirect people back to the sign-in form
34- redirect_to = ""
35-
36- # Light security check -- make sure redirect_to isn't garbage.
37- if not redirect_to or " " in redirect_to :
38- redirect_to = settings .LOGIN_REDIRECT_URL
39-
40- # Heavier security check -- redirects to http://example.com should
41- # not be allowed, but things like /view/?param=http://example.com
42- # should be allowed. This regex checks if there is a '//' *before* a
43- # question mark.
44- elif "//" in redirect_to and re .match (r"[^?]*//" , redirect_to ):
45- redirect_to = settings .LOGIN_REDIRECT_URL
46-
40+ sign_in_url = reverse ("sign-in" ) in redirect_to
41+ register_in_url = reverse ("register" ) in redirect_to
42+ garbage_url = " " in redirect_to
43+ no_url = not redirect_to
44+ not_safe_url = not is_safe_url (
45+ redirect_to ,
46+ allowed_hosts = {request .get_host ()},
47+ require_https = request .is_secure (),
48+ )
49+ if any ([sign_in_url , register_in_url , garbage_url , no_url , not_safe_url ]):
50+ return settings .LOGIN_REDIRECT_URL
4751 return redirect_to
4852
4953
0 commit comments