CWE-354: Improper Validation of Integrity Check Value
Overview
Improper integrity check validation occurs when applications fail to verify checksums, HMAC values, or hash digests, or use weak integrity checks (CRC32, simple checksums) for security purposes, enabling data tampering, corrupted downloads, and MITM attacks.
Risk
High: Missing or weak integrity checks enable undetected data tampering, corrupted file downloads, modified API responses, cookie manipulation, database corruption, and acceptance of malicious data as legitimate.
Remediation Steps
Core principle: Integrity checks must be verified correctly and enforced before use; reject any data that fails validation.
Locate the improper integrity check validation in your code
- Review the flaw details to identify the specific file, line number, and code pattern with missing or weak integrity checks
- Identify the integrity check issue: no verification, weak algorithm (CRC32, MD5), client-controlled checksum, missing HMAC
- Determine what data lacks integrity protection: file downloads, API responses, cookies, database records, configuration
- Trace the validation flow: where checksums/HMACs should be verified but aren't
Use strong integrity mechanisms (Primary Defense)
- For Security:
- HMAC-SHA256 (message authentication): Use for API messages, cookies, tokens that must resist tampering
- Digital signatures (RSA, ECDSA): Use for software updates, documents, critical data requiring non-repudiation
- Authenticated encryption (AES-GCM): Use when data needs both confidentiality and integrity
- NOT CRC32, Adler32, or simple checksums (easily forged; not cryptographically secure)
- For Corruption Detection (non-security):
- SHA-256, SHA-512: Acceptable for detecting accidental corruption (not malicious tampering)
- CRC32 (acceptable for error detection only): Use only for detecting transmission errors, not for security
Verify integrity before use
- Calculate expected checksum/HMAC: Compute the expected integrity value using the same algorithm and key
- Compare with provided value: Compare computed value with received checksum/HMAC
- Use constant-time comparison: Prevents timing attacks; use
crypto.timingSafeEqual(),hmac.compare_digest() - Reject data if verification fails: Don't log and continue; immediately reject data if integrity check fails
Protect integrity check value
- Don't send HMAC key to client: Keep HMAC key secret on server; never send to client or embed in client-side code
- Sign checksum with private key: For public distribution (software updates), sign checksums with private key
- Use authenticated encryption: AES-GCM, ChaCha20-Poly1305 protect both data and integrity tag
- Store checksums securely: Don't store integrity check values in same location as data (separate database, signed manifest)
Implement end-to-end integrity
- Verify at final destination (not intermediate nodes): Only the final recipient should verify integrity; intermediate proxies can't be trusted
- Check integrity after decryption: Decrypt first, then verify HMAC/signature (encrypt-then-MAC pattern)
- Validate entire message (not just parts): Verify integrity of complete message including headers, metadata, payload
- Use message authentication codes: HMAC provides both integrity and authenticity
Test the integrity validation fix
- Verify data without integrity check is rejected (send message without HMAC/checksum, should fail)
- Test with tampered data: Modify data and verify it's rejected due to integrity check failure
- Test with valid integrity checks: Ensure legitimate data with correct checksum/HMAC is accepted
- Test with weak algorithms replaced: Verify CRC32/MD5 replaced with HMAC-SHA256 or stronger
- Re-scan with security scanner to confirm the issue is resolved
Common Vulnerable Patterns
- Not verifying checksums at all
- Using CRC32 for security
- Weak hash for integrity (MD5)
- Client-controlled checksum values
- Missing HMAC verification