Swift: Add a similar sink for password hashing as well.

This commit is contained in:
Geoffrey White
2026-05-26 17:33:50 +01:00
parent 98b7659cc1
commit 2b4ea18dfe
3 changed files with 37 additions and 5 deletions

View File

@@ -111,6 +111,24 @@ private class DefaultWeakPasswordHashingSink extends WeakPasswordHashingSink {
override string getAlgorithm() { result = algorithm }
}
/**
* A sink for weak password hashing through a call with a metatype qualifier.
*/
private class WeakPasswordHashingMetatypeSink extends WeakPasswordHashingSink {
string algorithm;
WeakPasswordHashingMetatypeSink() {
exists(CallExpr c |
c.getAnArgument().getExpr() = this.asExpr() and
algorithm = ["SHA256", "SHA384", "SHA512"] and
c.getQualifier().getType().getFullName() = algorithm + ".Type" and
c.getStaticTarget().getName() = ["hash(data:)", "update(data:)", "update(bufferPointer:)"]
)
}
override string getAlgorithm() { result = algorithm }
}
/**
* A barrier for weak password hashing, when it occurs inside of
* certain cryptographic algorithms as part of their design.

View File

@@ -1,13 +1,22 @@
edges
| testCryptoKit.swift:218:38:218:38 | passwordString | testCryptoKit.swift:218:38:218:53 | .utf8 | provenance | |
| testCryptoKit.swift:218:38:218:53 | .utf8 | testCryptoKit.swift:218:33:218:57 | call to Data.init(_:) | provenance | |
nodes
| testCryptoKit.swift:84:47:84:47 | passwd | semmle.label | passwd |
| testCryptoKit.swift:90:36:90:36 | passwd | semmle.label | passwd |
| testCryptoKit.swift:96:44:96:44 | passwd | semmle.label | passwd |
| testCryptoKit.swift:102:37:102:37 | passwd | semmle.label | passwd |
| testCryptoKit.swift:108:37:108:37 | passwd | semmle.label | passwd |
| testCryptoKit.swift:114:37:114:37 | passwd | semmle.label | passwd |
| testCryptoKit.swift:168:32:168:32 | passwd | semmle.label | passwd |
| testCryptoKit.swift:177:32:177:32 | passwd | semmle.label | passwd |
| testCryptoKit.swift:186:32:186:32 | passwd | semmle.label | passwd |
| testCryptoKit.swift:195:32:195:32 | passwd | semmle.label | passwd |
| testCryptoKit.swift:204:32:204:32 | passwd | semmle.label | passwd |
| testCryptoKit.swift:214:49:214:49 | passwordData | semmle.label | passwordData |
| testCryptoKit.swift:218:33:218:57 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
| testCryptoKit.swift:218:38:218:38 | passwordString | semmle.label | passwordString |
| testCryptoKit.swift:218:38:218:53 | .utf8 | semmle.label | .utf8 |
| testCryptoSwift.swift:154:30:154:30 | passwdArray | semmle.label | passwdArray |
| testCryptoSwift.swift:157:31:157:31 | passwdArray | semmle.label | passwdArray |
| testCryptoSwift.swift:160:47:160:47 | passwdArray | semmle.label | passwdArray |
@@ -37,11 +46,16 @@ subpaths
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |
| 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) |

View File

@@ -99,19 +99,19 @@ func testHashMethods(passwd : UnsafeRawBufferPointer, cert: String, encrypted_pa
hash = Crypto.Insecure.SHA1.hash(data: account_no) // BAD
hash = Crypto.Insecure.SHA1.hash(data: credit_card_no) // BAD
hash = Crypto.SHA256.hash(data: passwd) // BAD, not a computationally expensive hash [NOT DETECTED]
hash = Crypto.SHA256.hash(data: passwd) // BAD, not a computationally expensive hash
hash = Crypto.SHA256.hash(data: cert) // GOOD, computationally expensive hash not required
hash = Crypto.SHA256.hash(data: encrypted_passwd) // GOOD, not sensitive
hash = Crypto.SHA256.hash(data: account_no) // GOOD, computationally expensive hash not required
hash = Crypto.SHA256.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
hash = Crypto.SHA384.hash(data: passwd) // BAD, not a computationally expensive hash [NOT DETECTED]
hash = Crypto.SHA384.hash(data: passwd) // BAD, not a computationally expensive hash
hash = Crypto.SHA384.hash(data: cert) // GOOD, computationally expensive hash not required
hash = Crypto.SHA384.hash(data: encrypted_passwd) // GOOD, not sensitive
hash = Crypto.SHA384.hash(data: account_no) // GOOD, computationally expensive hash not required
hash = Crypto.SHA384.hash(data: credit_card_no) // GOOD, computationally expensive hash not required
hash = Crypto.SHA512.hash(data: passwd) // BAD, not a computationally expensive hash [NOT DETECTED]
hash = Crypto.SHA512.hash(data: passwd) // BAD, not a computationally expensive hash
hash = Crypto.SHA512.hash(data: cert) // GOOD, computationally expensive hash not required
hash = Crypto.SHA512.hash(data: encrypted_passwd) // GOOD, not sensitive
hash = Crypto.SHA512.hash(data: account_no) // GOOD, computationally expensive hash not required
@@ -211,11 +211,11 @@ func testSHA512UpdateWithUnsafeRawBufferPointer(passwd : UnsafeRawBufferPointer,
func testBadExample(passwordString: String) {
// this is the "bad" example from the .qhelp
let passwordData = Data(passwordString.utf8)
let passwordHash = Crypto.SHA512.hash(data: passwordData) // BAD, not a computationally expensive hash [NOT DETECTED]
let passwordHash = Crypto.SHA512.hash(data: passwordData) // BAD, not a computationally expensive hash
// ...
if Crypto.SHA512.hash(data: Data(passwordString.utf8)) == passwordHash { // BAD, not a computationally expensive hash [NOT DETECTED]
if Crypto.SHA512.hash(data: Data(passwordString.utf8)) == passwordHash { // BAD, not a computationally expensive hash
// ...
}
}