-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathUrlRedirect.qhelp
More file actions
86 lines (69 loc) · 2.89 KB
/
UrlRedirect.qhelp
File metadata and controls
86 lines (69 loc) · 2.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
Directly incorporating user input into a URL redirect request without validating the input
can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a
malicious site that looks very similar to the real site they intend to visit, but which is
controlled by the attacker.
</p>
</overview>
<recommendation>
<p>
To guard against untrusted URL redirection, it is advisable to avoid putting user input
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>
<p>
The following example shows an HTTP request parameter being used directly in a URL redirect
without validating the input, which facilitates phishing attacks:
</p>
<sample src="examples/redirect_bad.py"/>
<p>
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, you can use the <code>urlparse</code> function
from the Python standard library to parse the URL and check that the <code>netloc</code>
attribute is empty.
</p>
<p>
Note, however, that some cases are not handled as we desire out-of-the-box by <code>urlparse</code>, so we need to adjust two things, as shown in the example below:
</p>
<ul>
<li>
Many browsers accept backslash characters (<code>\</code>) as equivalent
to forward slash characters (<code>/</code>) in URLs, but the <code>urlparse</code> function
does not.
</li>
<li>
Mistyped URLs such as <code>https:/example.com</code> or <code>https:///example.com</code> are parsed as having an empty <code>netloc</code> attribute, while browsers will still redirect to the correct site.
</li>
</ul>
<sample src="examples/redirect_good2.py"/>
<p>
For Django application, you can use the function <code>url_has_allowed_host_and_scheme</code>
to check that a URL is safe to redirect to, as shown in the following example:
</p>
<sample src="examples/redirect_good3.py"/>
<p>
Note that <code>url_has_allowed_host_and_scheme</code> handles backslashes correctly, so no
additional processing is required.
</p>
</example>
<references>
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html">
XSS Unvalidated Redirects and Forwards Cheat Sheet</a>.</li>
<li>Python standard library: <a href="https://docs.python.org/3/library/urllib.parse.html">
urllib.parse</a>.</li>
</references>
</qhelp>