Weak Hash Algorithm
ID |
swift.weak_hash_algorithm |
Severity |
critical |
Resource |
Cryptography |
Language |
Swift |
Tags |
CWE:328, MASWE:0021, NIST.SP.800-53, OWASP:2021:A2, PCI-DSS:3.6.1, crypto |
Description
Weak hash algorithm vulnerabilities arise when outdated or insufficiently secure hashing algorithms are used, making systems susceptible to threats such as hash collisions or preimage attacks.
This often involves the use of algorithms like MD5 or SHA-1.
Rationale
Hashing algorithms are essential for ensuring data integrity and verifying authenticity. However, algorithms like MD5 and SHA-1 are no longer considered secure due to vulnerabilities that allow attackers to find hash collisions or preimage matches efficiently. A collision occurs when two different inputs produce the same hash, which can lead to data tampering or fraudulent authentication.
For example, MD5 is susceptible to collision attacks, allowing attackers to substitute a malicious file for a legitimate one by ensuring both files generate the same hash. SHA-1, while more secure than MD5, is also vulnerable to collision attacks with current computational capabilities.
For example, using MD5 to hash sensitive data in a Swift application using CommonCrypto:
import Foundation
import CommonCrypto
func hashPassword(_ password: String) -> String {
let data = password.data(using: .utf8)!
var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
data.withUnsafeBytes { bytes in
CC_MD5(bytes.baseAddress, CC_LONG(data.count), &digest) // FLAW
}
return digest.map { String(format: "%02hhx", $0) }.joined()
}
Using CryptoKit’s Insecure namespace:
import CryptoKit
func hashSensitiveData(_ data: Data) -> String {
let digest = CryptoKit.Insecure.MD5.hash(data: data) // FLAW
return digest.map { String(format: "%02hhx", $0) }.joined()
}
func sha1Hash(_ data: Data) -> String {
let digest = CryptoKit.Insecure.SHA1.hash(data: data) // FLAW
return digest.map { String(format: "%02hhx", $0) }.joined()
}
In these examples, MD5 and SHA-1’s vulnerability to collision attacks allows attackers to craft inputs that match an existing hash, potentially masquerading as legitimate users or accessing sensitive data undetected.
Remediation
To remediate weak hash algorithm vulnerabilities in software, adopt the following practices:
-
Use Stronger Hash Algorithms: Replace weak algorithms like MD5 and SHA-1 with more secure options such as SHA-256 or SHA-3, which offer enhanced collision resistance and security.
-
Cryptographic Libraries and Standards: Utilize well-supported libraries and standards that provide robust cryptographic hash functions. Ensure proper configuration and usage.
In highly regulated environments, consider using cryptographic modules (which can encompass hardware devices, software libraries, firmware…) compliant with standards like FIPS 140-3.
-
Hashing in Secure Contexts: When hashing passwords, use additional strengthening techniques such as salting and key derivation functions like PBKDF2 or Bcrypt to enhance security.
-
Periodic Reviews: Regularly evaluate your cryptographic implementations against the latest security research and recommendations, updating algorithms as needed.
For Swift applications, use secure hash functions from CryptoKit or CommonCrypto:
Using CryptoKit (recommended for iOS 13+, macOS 10.15+):
import CryptoKit
func hashPassword(_ password: String) -> String {
let data = password.data(using: .utf8)!
// FIXED: Use SHA-256 instead of MD5
let digest = SHA256.hash(data: data)
return digest.map { String(format: "%02hhx", $0) }.joined()
}
func hashSensitiveData(_ data: Data) -> String {
// FIXED: Use SHA-512 for sensitive data
let digest = SHA512.hash(data: data)
return digest.map { String(format: "%02hhx", $0) }.joined()
}
Using CommonCrypto (for older platforms):
import Foundation
import CommonCrypto
func hashPassword(_ password: String) -> String {
let data = password.data(using: .utf8)!
var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
data.withUnsafeBytes { bytes in
CC_SHA256(bytes.baseAddress, CC_LONG(data.count), &digest) // FIXED
}
return digest.map { String(format: "%02hhx", $0) }.joined()
}
func hashSensitiveData(_ data: Data) -> String {
var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
data.withUnsafeBytes { bytes in
CC_SHA512(bytes.baseAddress, CC_LONG(data.count), &digest) // FIXED
}
return digest.map { String(format: "%02hhx", $0) }.joined()
}
Important Notes:
-
For Password Hashing: Use specialized password hashing functions like
bcrypt,scrypt, orPBKDF2with a salt, not general-purpose hash functions. -
CryptoKit Advantages:
-
Modern Swift API
-
Hardware acceleration support
-
Memory-safe by design
-
Clearly marked insecure algorithms in
Insecurenamespace
-
-
Algorithm Selection:
-
SHA-256: Good balance of security and performance
-
SHA-384/SHA-512: Extra security margin for highly sensitive data
-
SHA3: Alternative to SHA-2 family
-
Configuration
The detector has the following configurable parameters:
-
allowedAlgorithms, that indicates the algorithms that are allowed to be used. -
forbiddenAlgorithms, that indicates the algorithms that are considered weak and that should not be used.
For Swift, you can customize the allowed and forbidden algorithms:
swift.weak_hash_algorithm:
properties:
allowedAlgorithms:
- sha256
- sha384
- sha512
- sha3
- sha3-256
- sha3-384
- sha3-512
- keccak
- whirlpool
forbiddenAlgorithms:
- md2
- md4
- md5
- sha1
- ripemd128
References
-
CWE-328 : Use of Weak Hash.
-
OWASP - Top 10 2021 Category A02 : Cryptographic Failures.
-
MASWE-0021: Improper Hashing.
-
CryptoKit - Apple’s cryptography framework
-
CryptoKit.Insecure - Namespace for weak algorithms
-
CommonCrypto - Legacy cryptographic functions