Skip to content

Resolve vulnerability: Use of a broken or risky cryptographic algorithm

MR created from vulnerability: Use of a broken or risky cryptographic algorithm

AI GENERATED FIX

The suggested code changes were generated by GitLab Duo Vulnerability Resolution, an AI feature. Use this feature with caution. Before you run a pipeline or apply the code changes, carefully review and test them, to ensure that they solve the vulnerability.

The large language model that generated the suggested code changes was provided with the entire file that contains the vulnerable lines of code. It is not aware of any functionality outside of this context.

Please see our documentation for more information about this feature and leave feedback in this issue.

Description:

The application was found using an insecure or risky digest or signature algorithm. MD2, MD4, MD5 and SHA1 hash algorithms have been found to be vulnerable to producing collisions.

This means that two different values, when hashed, can lead to the same hash value. If the application is trying to use these hash methods for storing passwords, then it is recommended to switch to a password hashing algorithm such as Argon2id or PBKDF2.

Note that the Crypto and Cryptodome Python packages are no longer recommended for new applications, instead consider using the cryptography package.

Example of creating a SHA-384 hash using the cryptography package:

from cryptography.hazmat.primitives import hashes
# Create a SHA384 digest
digest = hashes.Hash(hashes.SHA384())
# Update the digest with some initial data
digest.update(b"some data to hash")
# Add more data to the digest
digest.update(b"some more data")
# Finalize the digest as bytes
result = digest.finalize()

For more information on secure password storage see OWASP:

For more information on the cryptography module see:

Analysis:

The vulnerability report indicates a "Use of a broken or risky cryptographic algorithm" (CWE-327). The specific part of the code flagged as vulnerable is the use of the MD5 hash function:

md5 = hashlib.md5()

This is indeed a security concern. MD5 is a cryptographic hash function that has been considered cryptographically broken and unsuitable for further use since 2008. It's vulnerable to collision attacks and should not be used for any security-related purpose, especially not for password hashing or encryption.

The code uses MD5 in the encrypt_data function, which is then used for password comparison in the login route and for general data encryption. This is highly insecure for several reasons:

  1. MD5 is not an encryption algorithm, it's a hash function. It's not reversible, so the decrypt_data function doesn't actually decrypt anything.
  2. MD5 is vulnerable to collision attacks, making it unsuitable for password hashing or any security-critical applications.
  3. The code doesn't use any salt, making it vulnerable to rainbow table attacks.
  4. The base64 encoding doesn't add any security; it's just an encoding, not encryption.

This vulnerability is not a false positive and needs to be addressed.

Summary:

  1. The reported vulnerability is the use of a broken or risky cryptographic algorithm, specifically the use of MD5 for password hashing and data encryption.

  2. The fix provided addresses this security concern in several ways:

    • For password hashing, we've replaced MD5 with PBKDF2 (Password-Based Key Derivation Function 2) using SHA256. This is a much more secure method for password hashing as it:

      • Uses a strong hash function (SHA256)
      • Applies key stretching (100,000 iterations)
      • Uses a unique salt for each password to prevent rainbow table attacks
    • For data encryption and decryption, we've replaced the misuse of MD5 with Fernet, which provides authenticated symmetric encryption. Fernet uses AES in CBC mode with a 128-bit key for encryption and HMAC with SHA256 for authentication.

    • We've replaced the hardcoded secret key with a securely generated random key using secrets.token_bytes(32).

    • We've implemented proper password verification using a constant-time comparison function (secrets.compare_digest) to prevent timing attacks.

These changes significantly improve the security of the application by using modern, secure cryptographic practices for both password handling and data encryption/decryption. The overall functionality of the code remains the same, but the security has been greatly enhanced.

Identifiers:

  • CWE-327
  • A3:2017 - Sensitive Data Exposure
  • Bandit Test ID B303
  • A02:2021 - Cryptographic Failures
  • bandit.B303-1

Merge request reports

Loading