Skip to content

Commit 2b4ea18

Browse files
committed
Swift: Add a similar sink for password hashing as well.
1 parent 98b7659 commit 2b4ea18

3 files changed

Lines changed: 37 additions & 5 deletions

File tree

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,24 @@ private class DefaultWeakPasswordHashingSink extends WeakPasswordHashingSink {
111111
override string getAlgorithm() { result = algorithm }
112112
}
113113

114+
/**
115+
* A sink for weak password hashing through a call with a metatype qualifier.
116+
*/
117+
private class WeakPasswordHashingMetatypeSink extends WeakPasswordHashingSink {
118+
string algorithm;
119+
120+
WeakPasswordHashingMetatypeSink() {
121+
exists(CallExpr c |
122+
c.getAnArgument().getExpr() = this.asExpr() and
123+
algorithm = ["SHA256", "SHA384", "SHA512"] and
124+
c.getQualifier().getType().getFullName() = algorithm + ".Type" and
125+
c.getStaticTarget().getName() = ["hash(data:)", "update(data:)", "update(bufferPointer:)"]
126+
)
127+
}
128+
129+
override string getAlgorithm() { result = algorithm }
130+
}
131+
114132
/**
115133
* A barrier for weak password hashing, when it occurs inside of
116134
* certain cryptographic algorithms as part of their design.

swift/ql/test/query-tests/Security/CWE-328/WeakPasswordHashing.expected

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
edges
2+
| testCryptoKit.swift:218:38:218:38 | passwordString | testCryptoKit.swift:218:38:218:53 | .utf8 | provenance | |
3+
| testCryptoKit.swift:218:38:218:53 | .utf8 | testCryptoKit.swift:218:33:218:57 | call to Data.init(_:) | provenance | |
24
nodes
35
| testCryptoKit.swift:84:47:84:47 | passwd | semmle.label | passwd |
46
| testCryptoKit.swift:90:36:90:36 | passwd | semmle.label | passwd |
57
| testCryptoKit.swift:96:44:96:44 | passwd | semmle.label | passwd |
8+
| testCryptoKit.swift:102:37:102:37 | passwd | semmle.label | passwd |
9+
| testCryptoKit.swift:108:37:108:37 | passwd | semmle.label | passwd |
10+
| testCryptoKit.swift:114:37:114:37 | passwd | semmle.label | passwd |
611
| testCryptoKit.swift:168:32:168:32 | passwd | semmle.label | passwd |
712
| testCryptoKit.swift:177:32:177:32 | passwd | semmle.label | passwd |
813
| testCryptoKit.swift:186:32:186:32 | passwd | semmle.label | passwd |
914
| testCryptoKit.swift:195:32:195:32 | passwd | semmle.label | passwd |
1015
| testCryptoKit.swift:204:32:204:32 | passwd | semmle.label | passwd |
16+
| testCryptoKit.swift:214:49:214:49 | passwordData | semmle.label | passwordData |
17+
| testCryptoKit.swift:218:33:218:57 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
18+
| testCryptoKit.swift:218:38:218:38 | passwordString | semmle.label | passwordString |
19+
| testCryptoKit.swift:218:38:218:53 | .utf8 | semmle.label | .utf8 |
1120
| testCryptoSwift.swift:154:30:154:30 | passwdArray | semmle.label | passwdArray |
1221
| testCryptoSwift.swift:157:31:157:31 | passwdArray | semmle.label | passwdArray |
1322
| testCryptoSwift.swift:160:47:160:47 | passwdArray | semmle.label | passwdArray |
@@ -37,11 +46,16 @@ subpaths
3746
| testCryptoKit.swift:84:47:84:47 | passwd | testCryptoKit.swift:84:47:84:47 | passwd | testCryptoKit.swift:84:47:84:47 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:84:47:84:47 | passwd | password (passwd) |
3847
| testCryptoKit.swift:90:36:90:36 | passwd | testCryptoKit.swift:90:36:90:36 | passwd | testCryptoKit.swift:90:36:90:36 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:90:36:90:36 | passwd | password (passwd) |
3948
| testCryptoKit.swift:96:44:96:44 | passwd | testCryptoKit.swift:96:44:96:44 | passwd | testCryptoKit.swift:96:44:96:44 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:96:44:96:44 | passwd | password (passwd) |
49+
| testCryptoKit.swift:102:37:102:37 | passwd | testCryptoKit.swift:102:37:102:37 | passwd | testCryptoKit.swift:102:37:102:37 | passwd | Insecure hashing algorithm (SHA256) depends on $@. | testCryptoKit.swift:102:37:102:37 | passwd | password (passwd) |
50+
| testCryptoKit.swift:108:37:108:37 | passwd | testCryptoKit.swift:108:37:108:37 | passwd | testCryptoKit.swift:108:37:108:37 | passwd | Insecure hashing algorithm (SHA384) depends on $@. | testCryptoKit.swift:108:37:108:37 | passwd | password (passwd) |
51+
| testCryptoKit.swift:114:37:114:37 | passwd | testCryptoKit.swift:114:37:114:37 | passwd | testCryptoKit.swift:114:37:114:37 | passwd | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:114:37:114:37 | passwd | password (passwd) |
4052
| testCryptoKit.swift:168:32:168:32 | passwd | testCryptoKit.swift:168:32:168:32 | passwd | testCryptoKit.swift:168:32:168:32 | passwd | Insecure hashing algorithm (MD5) depends on $@. | testCryptoKit.swift:168:32:168:32 | passwd | password (passwd) |
4153
| testCryptoKit.swift:177:32:177:32 | passwd | testCryptoKit.swift:177:32:177:32 | passwd | testCryptoKit.swift:177:32:177:32 | passwd | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoKit.swift:177:32:177:32 | passwd | password (passwd) |
4254
| testCryptoKit.swift:186:32:186:32 | passwd | testCryptoKit.swift:186:32:186:32 | passwd | testCryptoKit.swift:186:32:186:32 | passwd | Insecure hashing algorithm (SHA256) depends on $@. | testCryptoKit.swift:186:32:186:32 | passwd | password (passwd) |
4355
| testCryptoKit.swift:195:32:195:32 | passwd | testCryptoKit.swift:195:32:195:32 | passwd | testCryptoKit.swift:195:32:195:32 | passwd | Insecure hashing algorithm (SHA384) depends on $@. | testCryptoKit.swift:195:32:195:32 | passwd | password (passwd) |
4456
| testCryptoKit.swift:204:32:204:32 | passwd | testCryptoKit.swift:204:32:204:32 | passwd | testCryptoKit.swift:204:32:204:32 | passwd | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:204:32:204:32 | passwd | password (passwd) |
57+
| testCryptoKit.swift:214:49:214:49 | passwordData | testCryptoKit.swift:214:49:214:49 | passwordData | testCryptoKit.swift:214:49:214:49 | passwordData | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:214:49:214:49 | passwordData | password (passwordData) |
58+
| testCryptoKit.swift:218:33:218:57 | call to Data.init(_:) | testCryptoKit.swift:218:38:218:38 | passwordString | testCryptoKit.swift:218:33:218:57 | call to Data.init(_:) | Insecure hashing algorithm (SHA512) depends on $@. | testCryptoKit.swift:218:38:218:38 | passwordString | password (passwordString) |
4559
| testCryptoSwift.swift:154:30:154:30 | passwdArray | testCryptoSwift.swift:154:30:154:30 | passwdArray | testCryptoSwift.swift:154:30:154:30 | passwdArray | Insecure hashing algorithm (MD5) depends on $@. | testCryptoSwift.swift:154:30:154:30 | passwdArray | password (passwdArray) |
4660
| testCryptoSwift.swift:157:31:157:31 | passwdArray | testCryptoSwift.swift:157:31:157:31 | passwdArray | testCryptoSwift.swift:157:31:157:31 | passwdArray | Insecure hashing algorithm (SHA1) depends on $@. | testCryptoSwift.swift:157:31:157:31 | passwdArray | password (passwdArray) |
4761
| testCryptoSwift.swift:160:47:160:47 | passwdArray | testCryptoSwift.swift:160:47:160:47 | passwdArray | testCryptoSwift.swift:160:47:160:47 | passwdArray | Insecure hashing algorithm (SHA2) depends on $@. | testCryptoSwift.swift:160:47:160:47 | passwdArray | password (passwdArray) |

swift/ql/test/query-tests/Security/CWE-328/testCryptoKit.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,19 +99,19 @@ func testHashMethods(passwd : UnsafeRawBufferPointer, cert: String, encrypted_pa
9999
hash = Crypto.Insecure.SHA1.hash(data: account_no) // BAD
100100
hash = Crypto.Insecure.SHA1.hash(data: credit_card_no) // BAD
101101

102-
hash = Crypto.SHA256.hash(data: passwd) // BAD, not a computationally expensive hash [NOT DETECTED]
102+
hash = Crypto.SHA256.hash(data: passwd) // BAD, not a computationally expensive hash
103103
hash = Crypto.SHA256.hash(data: cert) // GOOD, computationally expensive hash not required
104104
hash = Crypto.SHA256.hash(data: encrypted_passwd) // GOOD, not sensitive
105105
hash = Crypto.SHA256.hash(data: account_no) // GOOD, computationally expensive hash not required
106106
hash = Crypto.SHA256.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
107107

108-
hash = Crypto.SHA384.hash(data: passwd) // BAD, not a computationally expensive hash [NOT DETECTED]
108+
hash = Crypto.SHA384.hash(data: passwd) // BAD, not a computationally expensive hash
109109
hash = Crypto.SHA384.hash(data: cert) // GOOD, computationally expensive hash not required
110110
hash = Crypto.SHA384.hash(data: encrypted_passwd) // GOOD, not sensitive
111111
hash = Crypto.SHA384.hash(data: account_no) // GOOD, computationally expensive hash not required
112112
hash = Crypto.SHA384.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
113113

114-
hash = Crypto.SHA512.hash(data: passwd) // BAD, not a computationally expensive hash [NOT DETECTED]
114+
hash = Crypto.SHA512.hash(data: passwd) // BAD, not a computationally expensive hash
115115
hash = Crypto.SHA512.hash(data: cert) // GOOD, computationally expensive hash not required
116116
hash = Crypto.SHA512.hash(data: encrypted_passwd) // GOOD, not sensitive
117117
hash = Crypto.SHA512.hash(data: account_no) // GOOD, computationally expensive hash not required
@@ -211,11 +211,11 @@ func testSHA512UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer,
211211
func testBadExample(passwordString: String) {
212212
// this is the "bad" example from the .qhelp
213213
let passwordData = Data(passwordString.utf8)
214-
let passwordHash = Crypto.SHA512.hash(data: passwordData) // BAD, not a computationally expensive hash [NOT DETECTED]
214+
let passwordHash = Crypto.SHA512.hash(data: passwordData) // BAD, not a computationally expensive hash
215215

216216
// ...
217217

218-
if Crypto.SHA512.hash(data: Data(passwordString.utf8)) == passwordHash { // BAD, not a computationally expensive hash [NOT DETECTED]
218+
if Crypto.SHA512.hash(data: Data(passwordString.utf8)) == passwordHash { // BAD, not a computationally expensive hash
219219
// ...
220220
}
221221
}

0 commit comments

Comments
 (0)