Skip to content

Commit 417b215

Browse files
authored
Merge pull request #10319 from geoffw0/cleartextbarrier
2 parents 144a045 + d0cda04 commit 417b215

File tree

8 files changed

+76
-27
lines changed

8 files changed

+76
-27
lines changed

swift/ql/lib/codeql/swift/security/SensitiveExprs.qll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,23 @@ class SensitiveExpr extends Expr {
154154
*/
155155
predicate isProbablySafe() { label.toLowerCase().regexpMatch(regexpProbablySafe()) }
156156
}
157+
158+
/**
159+
* A function that is likely used to encrypt or hash data.
160+
*/
161+
private class EncryptionFunction extends AbstractFunctionDecl {
162+
EncryptionFunction() { this.getName().regexpMatch(".*(crypt|hash|encode|protect).*") }
163+
}
164+
165+
/**
166+
* An expression that may be protected with encryption, for example an
167+
* argument to a function called "encrypt".
168+
*/
169+
class EncryptedExpr extends Expr {
170+
EncryptedExpr() {
171+
exists(CallExpr call |
172+
call.getStaticTarget() instanceof EncryptionFunction and
173+
call.getAnArgument().getExpr() = this
174+
)
175+
}
176+
}

swift/ql/src/queries/Security/CWE-311/CleartextStorageDatabase.ql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ class CleartextStorageConfig extends TaintTracking::Configuration {
8484
isSource(node)
8585
}
8686

87+
override predicate isSanitizer(DataFlow::Node node) {
88+
// encryption barrier
89+
node.asExpr() instanceof EncryptedExpr
90+
}
91+
8792
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
8893
// flow out from fields of a `RealmSwiftObject` at the sink, for example in `obj.var = tainted; sink(obj)`.
8994
isSink(node) and

swift/ql/src/queries/Security/CWE-311/CleartextTransmission.ql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ class CleartextTransmissionConfig extends TaintTracking::Configuration {
7676
// make sources barriers so that we only report the closest instance
7777
isSource(node)
7878
}
79+
80+
override predicate isSanitizer(DataFlow::Node node) {
81+
// encryption barrier
82+
node.asExpr() instanceof EncryptedExpr
83+
}
7984
}
8085

8186
from CleartextTransmissionConfig config, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode

swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,13 @@ edges
22
| file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [data] : |
33
| testCoreData.swift:18:19:18:26 | value : | testCoreData.swift:19:12:19:12 | value |
44
| testCoreData.swift:31:3:31:3 | newValue : | testCoreData.swift:32:13:32:13 | newValue |
5-
| testCoreData.swift:37:14:37:22 | data : | testCoreData.swift:37:49:37:49 | data : |
6-
| testCoreData.swift:38:11:38:23 | data : | testCoreData.swift:38:1:38:33 | data[return] : |
75
| testCoreData.swift:61:25:61:25 | password : | testCoreData.swift:18:19:18:26 | value : |
86
| testCoreData.swift:64:16:64:16 | password : | testCoreData.swift:31:3:31:3 | newValue : |
97
| testCoreData.swift:77:24:77:24 | x : | testCoreData.swift:78:15:78:15 | x |
108
| testCoreData.swift:80:10:80:22 | call to getPassword() : | testCoreData.swift:81:15:81:15 | y |
119
| testCoreData.swift:91:10:91:10 | passwd : | testCoreData.swift:95:15:95:15 | x |
12-
| testCoreData.swift:91:10:91:10 | passwd : | testCoreData.swift:99:14:99:14 | x : |
1310
| testCoreData.swift:92:10:92:10 | passwd : | testCoreData.swift:96:15:96:15 | y |
14-
| testCoreData.swift:92:10:92:10 | passwd : | testCoreData.swift:100:13:100:14 | &... : |
15-
| testCoreData.swift:92:10:92:10 | passwd : | testCoreData.swift:104:15:104:15 | y |
1611
| testCoreData.swift:93:10:93:10 | passwd : | testCoreData.swift:97:15:97:15 | z |
17-
| testCoreData.swift:99:6:99:15 | call to encrypt(_:) : | testCoreData.swift:103:15:103:15 | x |
18-
| testCoreData.swift:99:14:99:14 | x : | testCoreData.swift:37:14:37:22 | data : |
19-
| testCoreData.swift:99:14:99:14 | x : | testCoreData.swift:99:6:99:15 | call to encrypt(_:) : |
20-
| testCoreData.swift:100:13:100:14 | &... : | testCoreData.swift:38:11:38:23 | data : |
21-
| testCoreData.swift:100:13:100:14 | &... : | testCoreData.swift:100:13:100:14 | [post] &... : |
22-
| testCoreData.swift:100:13:100:14 | [post] &... : | testCoreData.swift:104:15:104:15 | y |
2312
| testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | value : |
2413
| testRealm.swift:34:2:34:2 | [post] a [data] : | testRealm.swift:35:12:35:12 | a |
2514
| testRealm.swift:34:11:34:11 | myPassword : | testRealm.swift:16:6:16:6 | value : |
@@ -34,10 +23,6 @@ nodes
3423
| testCoreData.swift:19:12:19:12 | value | semmle.label | value |
3524
| testCoreData.swift:31:3:31:3 | newValue : | semmle.label | newValue : |
3625
| testCoreData.swift:32:13:32:13 | newValue | semmle.label | newValue |
37-
| testCoreData.swift:37:14:37:22 | data : | semmle.label | data : |
38-
| testCoreData.swift:37:49:37:49 | data : | semmle.label | data : |
39-
| testCoreData.swift:38:1:38:33 | data[return] : | semmle.label | data[return] : |
40-
| testCoreData.swift:38:11:38:23 | data : | semmle.label | data : |
4126
| testCoreData.swift:48:15:48:15 | password | semmle.label | password |
4227
| testCoreData.swift:51:24:51:24 | password | semmle.label | password |
4328
| testCoreData.swift:58:15:58:15 | password | semmle.label | password |
@@ -54,12 +39,6 @@ nodes
5439
| testCoreData.swift:95:15:95:15 | x | semmle.label | x |
5540
| testCoreData.swift:96:15:96:15 | y | semmle.label | y |
5641
| testCoreData.swift:97:15:97:15 | z | semmle.label | z |
57-
| testCoreData.swift:99:6:99:15 | call to encrypt(_:) : | semmle.label | call to encrypt(_:) : |
58-
| testCoreData.swift:99:14:99:14 | x : | semmle.label | x : |
59-
| testCoreData.swift:100:13:100:14 | &... : | semmle.label | &... : |
60-
| testCoreData.swift:100:13:100:14 | [post] &... : | semmle.label | [post] &... : |
61-
| testCoreData.swift:103:15:103:15 | x | semmle.label | x |
62-
| testCoreData.swift:104:15:104:15 | y | semmle.label | y |
6342
| testRealm.swift:16:6:16:6 | value : | semmle.label | value : |
6443
| testRealm.swift:34:2:34:2 | [post] a [data] : | semmle.label | [post] a [data] : |
6544
| testRealm.swift:34:11:34:11 | myPassword : | semmle.label | myPassword : |
@@ -68,8 +47,6 @@ nodes
6847
| testRealm.swift:42:11:42:11 | myPassword : | semmle.label | myPassword : |
6948
| testRealm.swift:43:47:43:47 | c | semmle.label | c |
7049
subpaths
71-
| testCoreData.swift:99:14:99:14 | x : | testCoreData.swift:37:14:37:22 | data : | testCoreData.swift:37:49:37:49 | data : | testCoreData.swift:99:6:99:15 | call to encrypt(_:) : |
72-
| testCoreData.swift:100:13:100:14 | &... : | testCoreData.swift:38:11:38:23 | data : | testCoreData.swift:38:1:38:33 | data[return] : | testCoreData.swift:100:13:100:14 | [post] &... : |
7350
| testRealm.swift:34:11:34:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:34:2:34:2 | [post] a [data] : |
7451
| testRealm.swift:42:11:42:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:42:2:42:2 | [post] c [data] : |
7552
#select
@@ -84,7 +61,5 @@ subpaths
8461
| testCoreData.swift:95:15:95:15 | x | testCoreData.swift:91:10:91:10 | passwd : | testCoreData.swift:95:15:95:15 | x | This operation stores 'x' in a database. It may contain unencrypted sensitive data from $@ | testCoreData.swift:91:10:91:10 | passwd : | passwd |
8562
| testCoreData.swift:96:15:96:15 | y | testCoreData.swift:92:10:92:10 | passwd : | testCoreData.swift:96:15:96:15 | y | This operation stores 'y' in a database. It may contain unencrypted sensitive data from $@ | testCoreData.swift:92:10:92:10 | passwd : | passwd |
8663
| testCoreData.swift:97:15:97:15 | z | testCoreData.swift:93:10:93:10 | passwd : | testCoreData.swift:97:15:97:15 | z | This operation stores 'z' in a database. It may contain unencrypted sensitive data from $@ | testCoreData.swift:93:10:93:10 | passwd : | passwd |
87-
| testCoreData.swift:103:15:103:15 | x | testCoreData.swift:91:10:91:10 | passwd : | testCoreData.swift:103:15:103:15 | x | This operation stores 'x' in a database. It may contain unencrypted sensitive data from $@ | testCoreData.swift:91:10:91:10 | passwd : | passwd |
88-
| testCoreData.swift:104:15:104:15 | y | testCoreData.swift:92:10:92:10 | passwd : | testCoreData.swift:104:15:104:15 | y | This operation stores 'y' in a database. It may contain unencrypted sensitive data from $@ | testCoreData.swift:92:10:92:10 | passwd : | passwd |
8964
| testRealm.swift:35:12:35:12 | a | testRealm.swift:34:11:34:11 | myPassword : | testRealm.swift:35:12:35:12 | a | This operation stores 'a' in a database. It may contain unencrypted sensitive data from $@ | testRealm.swift:34:11:34:11 | myPassword : | myPassword |
9065
| testRealm.swift:43:47:43:47 | c | testRealm.swift:42:11:42:11 | myPassword : | testRealm.swift:43:47:43:47 | c | This operation stores 'c' in a database. It may contain unencrypted sensitive data from $@ | testRealm.swift:42:11:42:11 | myPassword : | myPassword |
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,35 @@
11
edges
2+
| testSend.swift:41:10:41:18 | data : | testSend.swift:41:45:41:45 | data : |
3+
| testSend.swift:45:13:45:13 | password : | testSend.swift:52:27:52:27 | str1 |
4+
| testSend.swift:46:13:46:13 | password : | testSend.swift:53:27:53:27 | str2 |
5+
| testSend.swift:47:13:47:25 | call to pad(_:) : | testSend.swift:54:27:54:27 | str3 |
6+
| testSend.swift:47:17:47:17 | password : | testSend.swift:41:10:41:18 | data : |
7+
| testSend.swift:47:17:47:17 | password : | testSend.swift:47:13:47:25 | call to pad(_:) : |
28
| testURL.swift:13:54:13:54 | passwd : | testURL.swift:13:22:13:54 | ... .+(_:_:) ... |
39
| testURL.swift:16:55:16:55 | credit_card_no : | testURL.swift:16:22:16:55 | ... .+(_:_:) ... |
410
nodes
511
| testSend.swift:29:19:29:19 | passwordPlain | semmle.label | passwordPlain |
12+
| testSend.swift:41:10:41:18 | data : | semmle.label | data : |
13+
| testSend.swift:41:45:41:45 | data : | semmle.label | data : |
14+
| testSend.swift:45:13:45:13 | password : | semmle.label | password : |
15+
| testSend.swift:46:13:46:13 | password : | semmle.label | password : |
16+
| testSend.swift:47:13:47:25 | call to pad(_:) : | semmle.label | call to pad(_:) : |
17+
| testSend.swift:47:17:47:17 | password : | semmle.label | password : |
18+
| testSend.swift:52:27:52:27 | str1 | semmle.label | str1 |
19+
| testSend.swift:53:27:53:27 | str2 | semmle.label | str2 |
20+
| testSend.swift:54:27:54:27 | str3 | semmle.label | str3 |
621
| testURL.swift:13:22:13:54 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
722
| testURL.swift:13:54:13:54 | passwd : | semmle.label | passwd : |
823
| testURL.swift:16:22:16:55 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
924
| testURL.swift:16:55:16:55 | credit_card_no : | semmle.label | credit_card_no : |
1025
| testURL.swift:20:22:20:22 | passwd | semmle.label | passwd |
1126
subpaths
27+
| testSend.swift:47:17:47:17 | password : | testSend.swift:41:10:41:18 | data : | testSend.swift:41:45:41:45 | data : | testSend.swift:47:13:47:25 | call to pad(_:) : |
1228
#select
1329
| testSend.swift:29:19:29:19 | passwordPlain | testSend.swift:29:19:29:19 | passwordPlain | testSend.swift:29:19:29:19 | passwordPlain | This operation transmits 'passwordPlain', which may contain unencrypted sensitive data from $@ | testSend.swift:29:19:29:19 | passwordPlain | passwordPlain |
30+
| testSend.swift:52:27:52:27 | str1 | testSend.swift:45:13:45:13 | password : | testSend.swift:52:27:52:27 | str1 | This operation transmits 'str1', which may contain unencrypted sensitive data from $@ | testSend.swift:45:13:45:13 | password : | password |
31+
| testSend.swift:53:27:53:27 | str2 | testSend.swift:46:13:46:13 | password : | testSend.swift:53:27:53:27 | str2 | This operation transmits 'str2', which may contain unencrypted sensitive data from $@ | testSend.swift:46:13:46:13 | password : | password |
32+
| testSend.swift:54:27:54:27 | str3 | testSend.swift:47:17:47:17 | password : | testSend.swift:54:27:54:27 | str3 | This operation transmits 'str3', which may contain unencrypted sensitive data from $@ | testSend.swift:47:17:47:17 | password : | password |
1433
| testURL.swift:13:22:13:54 | ... .+(_:_:) ... | testURL.swift:13:54:13:54 | passwd : | testURL.swift:13:22:13:54 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@ | testURL.swift:13:54:13:54 | passwd : | passwd |
1534
| testURL.swift:16:22:16:55 | ... .+(_:_:) ... | testURL.swift:16:55:16:55 | credit_card_no : | testURL.swift:16:22:16:55 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@ | testURL.swift:16:55:16:55 | credit_card_no : | credit_card_no |
1635
| testURL.swift:20:22:20:22 | passwd | testURL.swift:20:22:20:22 | passwd | testURL.swift:20:22:20:22 | passwd | This operation transmits 'passwd', which may contain unencrypted sensitive data from $@ | testURL.swift:20:22:20:22 | passwd | passwd |

swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
| testSend.swift:30:19:30:19 | passwordHash | isProbablySafe, label:passwordHash, type:credential |
2626
| testSend.swift:33:19:33:19 | passwordPlain | label:passwordPlain, type:credential |
2727
| testSend.swift:34:19:34:19 | passwordHash | isProbablySafe, label:passwordHash, type:credential |
28+
| testSend.swift:45:13:45:13 | password | label:password, type:credential |
29+
| testSend.swift:46:13:46:13 | password | label:password, type:credential |
30+
| testSend.swift:47:17:47:17 | password | label:password, type:credential |
31+
| testSend.swift:48:23:48:23 | password | label:password, type:credential |
32+
| testSend.swift:49:27:49:27 | password | label:password, type:credential |
33+
| testSend.swift:50:27:50:27 | password | label:password, type:credential |
2834
| testURL.swift:13:54:13:54 | passwd | label:passwd, type:credential |
2935
| testURL.swift:14:54:14:54 | encrypted_passwd | isProbablySafe, label:encrypted_passwd, type:credential |
3036
| testURL.swift:16:55:16:55 | credit_card_no | label:credit_card_no, type:private information |

swift/ql/test/query-tests/Security/CWE-311/testCoreData.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func test4(obj : NSManagedObject, passwd : String) {
100100
hash(data: &y);
101101
z = "";
102102

103-
obj.setValue(x, forKey: "myKey") // GOOD (not sensitive) [FALSE POSITIVE]
104-
obj.setValue(y, forKey: "myKey") // GOOD (not sensitive) [FALSE POSITIVE]
103+
obj.setValue(x, forKey: "myKey") // GOOD (not sensitive)
104+
obj.setValue(y, forKey: "myKey") // GOOD (not sensitive)
105105
obj.setValue(z, forKey: "myKey") // GOOD (not sensitive)
106106
}

swift/ql/test/query-tests/Security/CWE-311/testSend.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,22 @@ func test1(passwordPlain : String, passwordHash : String) {
3737
nw.send(content: data2, completion: .idempotent) // BAD [NOT DETECTED]
3838
nw.send(content: data3, completion: .idempotent) // GOOD (not sensitive)
3939
}
40+
41+
func pad(_ data: String) -> String { return data }
42+
func aes_crypt(_ data: String) -> String { return data }
43+
44+
func test2(password : String, connection : NWConnection) {
45+
let str1 = password
46+
let str2 = password + " "
47+
let str3 = pad(password)
48+
let str4 = aes_crypt(password)
49+
let str5 = pad(aes_crypt(password))
50+
let str6 = aes_crypt(pad(password))
51+
52+
connection.send(content: str1, completion: .idempotent) // BAD
53+
connection.send(content: str2, completion: .idempotent) // BAD
54+
connection.send(content: str3, completion: .idempotent) // BAD
55+
connection.send(content: str4, completion: .idempotent) // GOOD (encrypted)
56+
connection.send(content: str5, completion: .idempotent) // GOOD (encrypted)
57+
connection.send(content: str6, completion: .idempotent) // GOOD (encrypted)
58+
}

0 commit comments

Comments
 (0)