Skip to content

Commit 606a114

Browse files
authored
Merge pull request github#3331 from RasmusWL/python-improve-file-taint
Approved by tausbn
2 parents b03e87f + e0b4518 commit 606a114

File tree

5 files changed

+43
-3
lines changed

5 files changed

+43
-3
lines changed

python/ql/src/semmle/python/security/strings/External.qll

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,14 +183,20 @@ private predicate urlparse(ControlFlowNode fromnode, CallNode tonode) {
183183

184184
/** A kind of "taint", representing an open file-like object from an external source. */
185185
class ExternalFileObject extends TaintKind {
186-
ExternalFileObject() { this = "file[" + any(ExternalStringKind key) + "]" }
186+
ExternalStringKind valueKind;
187+
188+
ExternalFileObject() { this = "file[" + valueKind + "]" }
187189

188190
/** Gets the taint kind for the contents of this file */
189-
TaintKind getValue() { this = "file[" + result + "]" }
191+
TaintKind getValue() { result = valueKind }
190192

191193
override TaintKind getTaintOfMethodResult(string name) {
192-
name = "read" and result = this.getValue()
194+
name in ["read", "readline"] and result = this.getValue()
195+
or
196+
name = "readlines" and result.(SequenceKind).getItem() = this.getValue()
193197
}
198+
199+
override TaintKind getTaintForIteration() { result = this.getValue() }
194200
}
195201

196202
/**

python/ql/test/library-tests/taint/strings/Taint.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,11 @@ class ExceptionInfoSource extends TaintSource {
3434

3535
override string toString() { result = "Exception info source" }
3636
}
37+
38+
class ExternalFileObjectSource extends TaintSource {
39+
ExternalFileObjectSource() { this.(NameNode).getId() = "TAINTED_FILE" }
40+
41+
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalFileObject }
42+
43+
override string toString() { result = "Tainted file source" }
44+
}

python/ql/test/library-tests/taint/strings/TestStep.expected

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@
132132
| Taint externally controlled string | test.py:112 | test.py:112:9:112:22 | tainted_string | | --> | Taint externally controlled string | test.py:112 | test.py:112:9:112:30 | Attribute() | |
133133
| Taint externally controlled string | test.py:115 | test.py:115:9:115:22 | tainted_string | | --> | Taint externally controlled string | test.py:115 | test.py:115:9:115:30 | Attribute() | |
134134
| Taint externally controlled string | test.py:116 | test.py:116:9:116:22 | tainted_string | | --> | Taint externally controlled string | test.py:116 | test.py:116:9:116:33 | Attribute() | |
135+
| Taint externally controlled string | test.py:127 | test.py:127:5:127:29 | For | | --> | Taint externally controlled string | test.py:128 | test.py:128:14:128:17 | line | |
136+
| Taint file[externally controlled string] | test.py:120 | test.py:120:20:120:31 | TAINTED_FILE | | --> | Taint file[externally controlled string] | test.py:122 | test.py:122:9:122:20 | tainted_file | |
137+
| Taint file[externally controlled string] | test.py:120 | test.py:120:20:120:31 | TAINTED_FILE | | --> | Taint file[externally controlled string] | test.py:123 | test.py:123:9:123:20 | tainted_file | |
138+
| Taint file[externally controlled string] | test.py:120 | test.py:120:20:120:31 | TAINTED_FILE | | --> | Taint file[externally controlled string] | test.py:124 | test.py:124:9:124:20 | tainted_file | |
139+
| Taint file[externally controlled string] | test.py:120 | test.py:120:20:120:31 | TAINTED_FILE | | --> | Taint file[externally controlled string] | test.py:125 | test.py:125:9:125:20 | tainted_file | |
140+
| Taint file[externally controlled string] | test.py:120 | test.py:120:20:120:31 | TAINTED_FILE | | --> | Taint file[externally controlled string] | test.py:127 | test.py:127:17:127:28 | tainted_file | |
141+
| Taint file[externally controlled string] | test.py:123 | test.py:123:9:123:20 | tainted_file | | --> | Taint externally controlled string | test.py:123 | test.py:123:9:123:27 | Attribute() | |
142+
| Taint file[externally controlled string] | test.py:124 | test.py:124:9:124:20 | tainted_file | | --> | Taint externally controlled string | test.py:124 | test.py:124:9:124:31 | Attribute() | |
143+
| Taint file[externally controlled string] | test.py:125 | test.py:125:9:125:20 | tainted_file | | --> | Taint [externally controlled string] | test.py:125 | test.py:125:9:125:32 | Attribute() | |
144+
| Taint file[externally controlled string] | test.py:127 | test.py:127:17:127:28 | tainted_file | | --> | Taint externally controlled string | test.py:127 | test.py:127:5:127:29 | For | |
135145
| Taint json[externally controlled string] | test.py:6 | test.py:6:20:6:45 | Attribute() | | --> | Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:20 | tainted_json | |
136146
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:20 | tainted_json | | --> | Taint externally controlled string | test.py:7 | test.py:7:9:7:25 | Subscript | |
137147
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:20 | tainted_json | | --> | Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:25 | Subscript | |

python/ql/test/library-tests/taint/strings/TestTaint.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,8 @@
5454
| test.py:112 | test_str_methods | Attribute() | externally controlled string |
5555
| test.py:115 | test_str_methods | Attribute() | externally controlled string |
5656
| test.py:116 | test_str_methods | Attribute() | externally controlled string |
57+
| test.py:122 | test_tainted_file | tainted_file | file[externally controlled string] |
58+
| test.py:123 | test_tainted_file | Attribute() | externally controlled string |
59+
| test.py:124 | test_tainted_file | Attribute() | externally controlled string |
60+
| test.py:125 | test_tainted_file | Attribute() | [externally controlled string] |
61+
| test.py:128 | test_tainted_file | line | externally controlled string |

python/ql/test/library-tests/taint/strings/test.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,14 @@ def test_str_methods():
115115
tainted_string.upper(),
116116
tainted_string.zfill(100),
117117
)
118+
119+
def test_tainted_file():
120+
tainted_file = TAINTED_FILE
121+
test(
122+
tainted_file,
123+
tainted_file.read(),
124+
tainted_file.readline(),
125+
tainted_file.readlines(),
126+
)
127+
for line in tainted_file:
128+
test(line)

0 commit comments

Comments
 (0)