mirror of
https://github.com/github/codeql.git
synced 2025-12-18 01:33:15 +01:00
Python: Mention more sanitisation options in py/url-redirection qhelp.
This commit is contained in:
@@ -16,6 +16,10 @@ To guard against untrusted URL redirection, it is advisable to avoid putting use
|
||||
directly into a redirect URL. Instead, maintain a list of authorized
|
||||
redirects on the server; then choose from that list based on the user input provided.
|
||||
</p>
|
||||
<p>
|
||||
If this is not possible, then the user input should be validated in some other way,
|
||||
for example, by verifying that the target URL does not include an explicit host name.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
@@ -27,11 +31,29 @@ without validating the input, which facilitates phishing attacks:
|
||||
<sample src="examples/redirect_bad.py"/>
|
||||
|
||||
<p>
|
||||
One way to remedy the problem is to validate the user input against a known fixed string
|
||||
before doing the redirection:
|
||||
If you know the set of valid redirect targets, you can maintain a list of them on the server
|
||||
and check that the user input is in that list:
|
||||
</p>
|
||||
|
||||
<sample src="examples/redirect_good.py"/>
|
||||
|
||||
<p>
|
||||
Often this is not possible, so an alternative is to check that the target URL does not
|
||||
specify an explicit host name. For example, the Django framework provides a
|
||||
function <code>url_has_allowed_host_and_scheme</code> that can be used to check that a
|
||||
URL is safe to redirect to, as shown in the following example:
|
||||
</p>
|
||||
|
||||
<sample src="examples/redirect_good2.py"/>
|
||||
|
||||
<p>
|
||||
Note that many browsers accept backslash characters (<code>\</code>) as equivalent to
|
||||
forward slash characters (<code>/</code>) in URLs, so it is important to account for this
|
||||
when validating the URL, for example by first replacing all backslashes with forward
|
||||
slashes. Django's <code>url_has_allowed_host_and_scheme</code> function
|
||||
does this automatically, but other libraries may not.
|
||||
</p>
|
||||
|
||||
</example>
|
||||
|
||||
<references>
|
||||
|
||||
@@ -10,4 +10,5 @@ def hello():
|
||||
if target == VALID_REDIRECT:
|
||||
return redirect(target, code=302)
|
||||
else:
|
||||
... # Error
|
||||
# ignore the target and redirect to the home page
|
||||
return redirect('/', code=302)
|
||||
|
||||
13
python/ql/src/Security/CWE-601/examples/redirect_good2.py
Normal file
13
python/ql/src/Security/CWE-601/examples/redirect_good2.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
from django.views import View
|
||||
|
||||
class RedirectView(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
target = request.GET.get('target', '')
|
||||
if url_has_allowed_host_and_scheme(target, allowed_hosts=None):
|
||||
return HttpResponseRedirect(target)
|
||||
else:
|
||||
# ignore the target and redirect to the home page
|
||||
return redirect('/')
|
||||
Reference in New Issue
Block a user