Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9d8925a

Browse files
committed
Python: Extend url-redirect tests
Specifically to show how it currently handles prefixing user-input with known constant. I changed test to be Python 3 only since I wanted to use f-string.
1 parent ab607b8 commit 9d8925a

3 files changed

Lines changed: 107 additions & 4 deletions

File tree

python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,50 @@ edges
33
| test.py:7:14:7:25 | dict of externally controlled string | test.py:7:14:7:43 | externally controlled string |
44
| test.py:7:14:7:43 | externally controlled string | test.py:8:21:8:26 | externally controlled string |
55
| test.py:7:14:7:43 | externally controlled string | test.py:8:21:8:26 | externally controlled string |
6+
| test.py:30:17:30:28 | dict of externally controlled string | test.py:30:17:30:46 | externally controlled string |
7+
| test.py:30:17:30:28 | dict of externally controlled string | test.py:30:17:30:46 | externally controlled string |
8+
| test.py:30:17:30:46 | externally controlled string | test.py:31:41:31:49 | externally controlled string |
9+
| test.py:30:17:30:46 | externally controlled string | test.py:31:41:31:49 | externally controlled string |
10+
| test.py:31:12:31:50 | externally controlled string | test.py:32:21:32:24 | externally controlled string |
11+
| test.py:31:12:31:50 | externally controlled string | test.py:32:21:32:24 | externally controlled string |
12+
| test.py:31:41:31:49 | externally controlled string | test.py:31:12:31:50 | externally controlled string |
13+
| test.py:31:41:31:49 | externally controlled string | test.py:31:12:31:50 | externally controlled string |
14+
| test.py:37:17:37:28 | dict of externally controlled string | test.py:37:17:37:46 | externally controlled string |
15+
| test.py:37:17:37:28 | dict of externally controlled string | test.py:37:17:37:46 | externally controlled string |
16+
| test.py:37:17:37:46 | externally controlled string | test.py:38:32:38:40 | externally controlled string |
17+
| test.py:37:17:37:46 | externally controlled string | test.py:38:32:38:40 | externally controlled string |
18+
| test.py:38:12:38:42 | externally controlled string | test.py:39:21:39:24 | externally controlled string |
19+
| test.py:38:12:38:42 | externally controlled string | test.py:39:21:39:24 | externally controlled string |
20+
| test.py:38:32:38:40 | externally controlled string | test.py:38:12:38:42 | externally controlled string |
21+
| test.py:38:32:38:40 | externally controlled string | test.py:38:12:38:42 | externally controlled string |
22+
| test.py:53:17:53:28 | dict of externally controlled string | test.py:53:17:53:46 | externally controlled string |
23+
| test.py:53:17:53:28 | dict of externally controlled string | test.py:53:17:53:46 | externally controlled string |
24+
| test.py:53:17:53:46 | externally controlled string | test.py:54:14:54:22 | externally controlled string |
25+
| test.py:53:17:53:46 | externally controlled string | test.py:54:14:54:22 | externally controlled string |
26+
| test.py:54:14:54:22 | externally controlled string | test.py:54:14:54:41 | externally controlled string |
27+
| test.py:54:14:54:22 | externally controlled string | test.py:54:14:54:41 | externally controlled string |
28+
| test.py:54:14:54:41 | externally controlled string | test.py:55:21:55:26 | externally controlled string |
29+
| test.py:54:14:54:41 | externally controlled string | test.py:55:21:55:26 | externally controlled string |
30+
| test.py:60:17:60:28 | dict of externally controlled string | test.py:60:17:60:46 | externally controlled string |
31+
| test.py:60:17:60:28 | dict of externally controlled string | test.py:60:17:60:46 | externally controlled string |
32+
| test.py:60:17:60:46 | externally controlled string | test.py:61:40:61:48 | externally controlled string |
33+
| test.py:60:17:60:46 | externally controlled string | test.py:61:40:61:48 | externally controlled string |
34+
| test.py:61:14:61:49 | externally controlled string | test.py:62:21:62:26 | externally controlled string |
35+
| test.py:61:14:61:49 | externally controlled string | test.py:62:21:62:26 | externally controlled string |
36+
| test.py:61:40:61:48 | externally controlled string | test.py:61:14:61:49 | externally controlled string |
37+
| test.py:61:40:61:48 | externally controlled string | test.py:61:14:61:49 | externally controlled string |
38+
| test.py:67:17:67:28 | dict of externally controlled string | test.py:67:17:67:46 | externally controlled string |
39+
| test.py:67:17:67:28 | dict of externally controlled string | test.py:67:17:67:46 | externally controlled string |
40+
| test.py:67:17:67:46 | externally controlled string | test.py:68:17:68:25 | externally controlled string |
41+
| test.py:67:17:67:46 | externally controlled string | test.py:68:17:68:25 | externally controlled string |
42+
| test.py:68:14:68:41 | externally controlled string | test.py:69:21:69:26 | externally controlled string |
43+
| test.py:68:14:68:41 | externally controlled string | test.py:69:21:69:26 | externally controlled string |
44+
| test.py:68:17:68:25 | externally controlled string | test.py:68:14:68:41 | externally controlled string |
45+
| test.py:68:17:68:25 | externally controlled string | test.py:68:14:68:41 | externally controlled string |
646
#select
747
| test.py:8:21:8:26 | target | test.py:7:14:7:25 | dict of externally controlled string | test.py:8:21:8:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:7:14:7:25 | Attribute | a user-provided value |
48+
| test.py:32:21:32:24 | safe | test.py:30:17:30:28 | dict of externally controlled string | test.py:32:21:32:24 | externally controlled string | Untrusted URL redirection due to $@. | test.py:30:17:30:28 | Attribute | a user-provided value |
49+
| test.py:39:21:39:24 | safe | test.py:37:17:37:28 | dict of externally controlled string | test.py:39:21:39:24 | externally controlled string | Untrusted URL redirection due to $@. | test.py:37:17:37:28 | Attribute | a user-provided value |
50+
| test.py:55:21:55:26 | unsafe | test.py:53:17:53:28 | dict of externally controlled string | test.py:55:21:55:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:53:17:53:28 | Attribute | a user-provided value |
51+
| test.py:62:21:62:26 | unsafe | test.py:60:17:60:28 | dict of externally controlled string | test.py:62:21:62:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:60:17:60:28 | Attribute | a user-provided value |
52+
| test.py:69:21:69:26 | unsafe | test.py:67:17:67:28 | dict of externally controlled string | test.py:69:21:69:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:67:17:67:28 | Attribute | a user-provided value |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
semmle-extractor-options: --max-import-depth=2 -p ../lib
1+
semmle-extractor-options: --lang=3 --max-import-depth=2 -p ../lib

python/ql/test/query-tests/Security/CWE-601/test.py

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,69 @@ def hello():
88
return redirect(target, code=302)
99

1010

11-
#Check for safe prefixes
11+
# Check for safe prefixes
1212

1313
@app.route('/ok')
1414
def ok():
15-
untrusted = request.args.get('ok', '')
16-
safe = "safe"
15+
untrusted = request.args.get('target', '')
16+
safe = "https://safe.com/"
1717
safe += untrusted
1818
return redirect(safe, code=302)
19+
20+
21+
@app.route('/ok2')
22+
def ok2():
23+
untrusted = request.args.get('target', '')
24+
safe = "https://safe.com/" + untrusted
25+
return redirect(safe, code=302)
26+
27+
28+
@app.route('/ok3')
29+
def ok3():
30+
untrusted = request.args.get('target', '')
31+
safe = "https://safe.com/{}".format(untrusted)
32+
return redirect(safe, code=302) # FP
33+
34+
35+
@app.route('/ok4')
36+
def ok4():
37+
untrusted = request.args.get('target', '')
38+
safe = f"https://safe.com/{untrusted}"
39+
return redirect(safe, code=302) # FP
40+
41+
42+
@app.route('/ok5')
43+
def ok5():
44+
untrusted = request.args.get('target', '')
45+
safe = "https://safe.com/%s" % untrusted
46+
return redirect(safe, code=302)
47+
48+
49+
# Check that our sanitizer is not too broad
50+
51+
@app.route('/not_ok1')
52+
def not_ok1():
53+
untrusted = request.args.get('target', '')
54+
unsafe = untrusted + "?login=success"
55+
return redirect(unsafe, code=302)
56+
57+
58+
@app.route('/not_ok2')
59+
def not_ok2():
60+
untrusted = request.args.get('target', '')
61+
unsafe = "{}?login=success".format(untrusted)
62+
return redirect(unsafe, code=302)
63+
64+
65+
@app.route('/not_ok3')
66+
def not_ok3():
67+
untrusted = request.args.get('target', '')
68+
unsafe = f"{untrusted}?login=success"
69+
return redirect(unsafe, code=302)
70+
71+
72+
@app.route('/not_ok4')
73+
def not_ok4():
74+
untrusted = request.args.get('target', '')
75+
unsafe = "%s?login=success" % untrusted
76+
return redirect(unsafe, code=302) # Missing result

0 commit comments

Comments
 (0)