Safeguard
Application Security•

CWE-1204 Weak Initialization Vector (IV): Causes and Fixes

A static or predictable IV can break otherwise sound encryption. Learn what MITRE says about IV generation and how to fix it in code.

Safeguard Security Team
4 min read

CWE-1204 covers products that use a cryptographic primitive requiring an Initialization Vector (IV), but do not generate IVs that are sufficiently unpredictable or unique for that primitive. It affects anyone who calls a block cipher directly, which includes application developers who thought they were only using a library.

How it happens

Some primitives, block ciphers in particular, need IVs with specific properties, such as uniqueness, unpredictability or both. How much each property matters depends on the primitive. If a bug breaks those properties, the cryptography may be weakened or broken by attacking the IVs themselves.

MITRE's demonstrative examples show the most common mistake, an IV that is always a block of zeros. This makes the ciphertext much more predictable and open to dictionary attack.

// Vulnerable pattern: a fixed all zero IV for CBC mode
byte[] iv = { 0,0,0,0,0,0,0,0 };
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));

The C example in the record does the same with memset(iv, 0, EVP_MAX_IV_LENGTH) before EVP_EncryptInit.

The record also lists real world cases:

  • CVE-2020-1472, known as ZeroLogon, used a static IV of all zeroes in AES-CFB8 mode.
  • CVE-2011-3389, the BEAST attack, hit SSL 3.0 and TLS 1.0. In CBC mode the chained IVs were not random, allowing decryption of HTTPS traffic with a chosen plaintext attack.
  • CVE-2001-0161 describes a wireless router that did not use 6 of the 24 bits for WEP encryption, which made decrypting traffic easier.
  • CVE-2001-0160 describes a WEP card that generated predictable IV values.

MITRE also describes the WEP design itself. Its IVs were only 24 bits, so the chance of reusing one across messages was high. The IV travelled in plaintext in each packet. According to the cited analysis, only 5000 messages are needed before a collision occurs because of the birthday paradox. Some implementations reused the same IV for every packet, which made it much easier to recover plaintext from two packets with the same IV.

What an attacker gains

The record lists a loss of confidentiality. If the IV is not properly initialized, encrypted data can be compromised and information about the data can leak.

How to find it

MITRE lists automated static analysis (SAST) with high effectiveness. It builds a model of data flow and control flow and looks for patterns connecting sources to sinks. A constant array or a zero filled buffer that reaches a cipher initialization call is exactly that kind of pattern.

A quick manual search helps too:

  • Grep for byte arrays or buffers of constants passed to IvParameterSpec, EVP_EncryptInit or similar calls.
  • Look for IVs derived from a counter, a timestamp or the previous ciphertext when the mode does not allow it.
  • Check that each encryption call produces a fresh IV and that it is stored or sent alongside the ciphertext.

How to fix it

MITRE's guidance is to understand the requirements of the mode you choose, since different modes have different IV requirements. Generally, it is safest to generate a random IV, because it will be unpredictable and have a very low chance of being non-unique.

IVs do not have to be secret. If duplicates are a concern, you can keep a list of already used IVs and check against it. NIST publishes recommendations for IV generation for the modes it approves, including options for when random IVs are not practical. The record points to NIST guidance for CBC, CFB and OFB, and separate guidance for GCM.

// Fixed: a fresh random IV for every encryption
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
// prepend iv to the ciphertext so the receiver can decrypt

Prefer a high level, well reviewed authenticated encryption API where you can, so the library owns IV handling.

Try it yourself

Run a code scan against a sample project and look at how a hard coded value reaching a cipher call is reported.

Click through it at your own pace, or open it full screen.

Quick check

Does an IV need to be kept secret?

No. MITRE says IVs do not have to be kept secret. They need to meet the uniqueness or unpredictability requirements of the mode.

What is the safest general way to produce an IV?

Generate a random one, since it is unpredictable and has a very low chance of repeating.

Why was an all zero IV a problem in ZeroLogon?

A static IV of all zeroes in AES-CFB8 mode removes the unpredictability the primitive depends on.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.