The Dangers of CBC Mode

Sep 19, 2023 1:13:54 PM / by Flake Redmond and Ali Esparza

Today, data is everything. For our complicated digital infrastructure to properly function, it is necessary that data is communicated between many different devices and networks. Something as simple as authenticating into your company email requires that your sensitive data is sent to many different places. This includes your credentials being sent to a service that validates them, which may then assign you a sensitive token to prove that you’ve been authenticated. Afterwards, this sensitive token will be sent to the service that actually retrieves the content of your mailbox.

Malicious actors have extensive knowledge about workflows that transmit data 24/7 over the Internet. They constantly evolve their techniques to disrupt these workflows, aiming to identify security flaws that could grant them access to sensitive information. Without proper security controls, company proprietary information and user data would be fair game to anyone that can intercept communications over the Internet. This is why encrypting communications is crucial for protecting the confidentiality of data. It provides assurance to users and companies that even if their communications are intercepted, the data will be rendered useless to malicious actors.

Encryption is a computing process that alters data to appear like random data that can only be deciphered if the party accessing it has the correct cryptographic key. This process can be very simple to extremely complex, and the goal of using encryption is to keep sensitive data out of the hands of unauthorized users.

The main idea behind encryption in transit is to ensure that data is encrypted (ideally with a strong encryption algorithm — I’ll talk about this in a bit) before it is transmitted from one location to another. By implementing encryption, data remains protected even if it happens to be intercepted during transfer. Encryption in transit is achieved by using an industry-standard cryptographic protocol called Transport Layer Security (TLS). It determines how data should be encrypted when transferred to another system or through a network. While fully explaining TLS could be a blog of its own, interested users can learn more here . The most important thing to understand about TLS for this article is that TLS relies on something that is called a “cipher suite”. This can be thought of as a set of instructions that tell TLS what cryptographic parameters should be used to encrypt data in an HTTPS connection.

The decision of what TLS cipher suite should be used when making a connection during the TLS Handshake depends on how a web server is configured.

A cipher suite can look something like this:

DHE_RSA_WITH_AES_256_CBC_SHA256

To quickly explain what each portion of this cipher suite means:

  • DHE represents the key exchange algorithm
  • RSA being the digital signature algorithm
  • AES being the cipher algorithm with the strength of 256
  • CBC which is the block cipher mode, which is our focus
  • SHA256 which is the hash algorithm

What is CBC Mode?

A very common type of block cipher mode of cipher suites that is used in the industry is the cipher block chaining (CBC) mode. This block cipher mode consists of two processes: encryption and decryption.

Encryption

In this mode of operation for a block cipher, a sequence of bits is encrypted as a single unit (or a block) with a cipher key that is applied to the entire block. An initialization vector (IV) is first Exclusively-ORed (XORed) with the plaintext block before the encryption key is used on the block. In simple terms, XORing data involves comparing two pieces of binary data (either 0s or 1s). During the comparison, if both pieces are identical such as both being 1’s or both being 0’s, the result would be a 0. If the data pieces differ from one another, the result is a 1. This is a way to change the data into a different binary form to begin the encryption process. The truth table below illustrates these operations:

These below are some basic rules that apply to XOR operations. There is actually a long list, however, for the purpose of understanding attacks against AES in CBC mode, these two rules are all that are needed:

The idea with CBC mode is to use an initialization vector (IV) of a certain length for each block. Each block starts off as unencrypted data, also known as plaintext, and after it is encrypted, it is then known as ciphertext. In most implementations, the first IV that is used to encrypt the first plaintext block is randomly generated. Ideally, this randomly generated IV will also be a cryptographically secure generated number created by a cryptographically secure random number generator. Every IV that is used on subsequent blocks will just be the ciphertext of the previous and adjacent encrypted block. For example, the second ciphertext that is derived by encrypting the second plaintext block will have used the first ciphertext block as the IV for this round of encrypting with CBC mode. The same encryption key is also used to encrypt each plaintext block in the chain and this process repeats itself until there are no more plaintext blocks left to encrypt.

If we summarize this encryption process into a formula, it will look like this:

where EK denotes the block encryption algorithm using key K, and Ci-1 is the cipher corresponding to Bi-1.

Decryption

The decryption formula can be summarized as:

where DK donates the block decryption algorithm using key K.

To decrypt a series of cipher blocks, you essentially do the reverse of the encryption process. To do that, you must first input the first ciphertext block through the decryption process. This means that you must use the same encryption key the blocks were encrypted with, but on the ciphertext blocks that were produced from the original encryption procedure. After combining the encryption key on the ciphertext block, you then XOR each block with IVs that were used to encrypt the blocks in the previous encryption procedure.

While this process appears to be similar to encryption, the main difference of decrypting the first ciphertext block compared to any of the other ciphertext block is that the first ciphertext block uses the original IV to decrypt itself, while the subsequent ciphertext block must use the previous ciphertext block as its IV.

For example, if you want to decrypt the second ciphertext block in the chain, you must first combine it with the encryption key. This is then XORed with the first ciphertext block because the first ciphertext block was the IV that was used in the original CBC encryption process to encrypt the second plaintext box, producing the second ciphertext block. This pattern repeats through the entire decryption process until all ciphertext blocks have been successfully decrypted back into plaintext.

CBC Mode Advantages and Disadvantages

As it is with any block cipher mode of operation, CBC mode has its advantages and disadvantages. One of the main advantages to CBC mode is that each plaintext block is encrypted using a “unique” IV. This theoretically means that even if two identical plaintext blocks are being encrypted with the same encryption key, the fact that they are both being XORed with different IVs means that their respective ciphertext blocks will be completely different. This reduces the odds of any collisions or having two ciphertext blocks with the same value. Also, encryption in CBC mode is done sequentially, meaning blocks are encrypted one at a time. This means that the decryption process can be parallelized if all ciphertexts are available and can tolerate any loss of data, another advantage of CBC mode.

While CBC mode being sequential is one of its advantages while decrypting, it is also one of its main disadvantages while encrypting using CBC mode. Since CBC encrypts sequentially, it means that to properly encrypt all plaintext blocks, you must calculate each block to calculate any adjacent ones, making the process slow. Another disadvantage is that if any of the ciphertext blocks are lost, damaged, or corrupted, a user will not be able to completely decrypt all the ciphertext blocks. This is because ciphertext blocks are used in the encryption and decryption process as IVs for subsequent plaintext and ciphertext blocks.

How CBC Mode Can Break

One issue that arises when using AES in CBC mode is an attack known as the Padding Oracle Attack. For a server (also referred to as the “oracle”) to be vulnerable to this attack, the following conditions must be met:

  • The server possesses the secret key used for encryption and decryption.
  • The server uses AES in CBC mode to encrypt and decrypt messages.
  • The attacker possesses at least one cipher text that was encrypted by the server.
  • This is the most crucial one: when the server is sent a cipher text, the server must leak information about the validity of the padding used on the plaintext.

If all the above requirements are met, the application is vulnerable to the Padding Oracle Attack. So, what is the impact of a successful attack? It is a total compromise of the encrypted data. A successful attack will reveal the entire plaintext of a piece of ciphertext. The significance of this is that the attacker does not need to know the secret cryptographic key.

In order to understand the exact details of how this attack works, I made a video below working out the attack to decrypt a single block of cipher text. Before going into the video, make sure you understand the material in the “What is CBC Mode?” section above.

Now that you have reviewed the video and understand how the attack works, you can try to implement the padding Oracle attack in this Python coding challenge. The code comes with instructions and a script that simulates the oracle.

https://gitlab.com/aesparza1/cbc-padding-oracle-challenge

You think it can’t leak? Think again.

Many of you reading this might think, well we can use CBC as long as we do not leak information about the validity of the padding. However, preventing information leakage is a very tricky thing to accomplish. An information leak can be as obvious as returning a message like “the padding is invalid” or it can be as innocuous as a timing difference, which is a type of side channel leak. Also, many libraries are programmed to automatically throw an error if the padding is invalid. For instance, the following block of code in the Python Crypto module will return an error if the padding is invalid:

from Crypto.Util.Padding import unpad

from Crypto.Cipher import AES

       try:

            aes = AES.new(key, AES.MODE_CBC, iv)

            plaintext = unpad( aes.decrypt(cipher) , AES.block_size).decode('utf-8')

process_message(plaintext)

       except:

            return “error”

         return “success”

This may not be obvious because many operations are placed with the try statement. The source of the error appears to be ambiguous and un-padding a plaintext message is just a regular and necessary operation. However, an attacker looking for CBC padding vulnerabilities will quickly figure out that when the server returns the message “error”, the padding might be invalid.

Prevention

The only way to prevent this attack is to simply not use CBC mode. However, if it is necessary to use CBC mode, the next best alternative is to use the “Encrypt-then-MAC” construction. In this scheme, a Message Authentication Code (MAC) is computed for the cipher text. A MAC is basically a numeric representation of a signature. It can be generated by using an algorithm such as HMAC. The algorithm takes a message, in this case the cipher text, and a secret key known only to the server. In future requests, when the server is sent a cipher text, it should also expect a corresponding MAC. The MAC can then be validated to ensure that the cipher text has not been tampered with. If tampering is detected, the request must be rejected. Applying the “Encrypt-then-MAC” validation, to the previous code block would change it to the following (note this is just code for demonstration purposes).

from Crypto.Util.Padding import unpad 

from Crypto.Cipher import AES

import hmac

import hashlib

     mac_recieved = request.mac

     cipher = request.cipher

     if (not is_valid_mac(mac_recieved, cipher, mac_key)):

            return “invalid mac”

     try:

 

            aes = AES.new(key, AES.MODE_CBC, iv)

            plaintext = unpad( aes.decrypt(cipher) , AES.block_size).decode('utf-8')

process_message(plaintext)

       except:

            return “error”

         return “success”

def is_valid_mac(mac, message, key):

   h = hmac.new(key, message, digestmod=hashlib.sha256)

   m = hmac.digest()

     return hmac.compare_digest(mac, m)

Conclusion

Securely implementing cryptography can be a complex and daunting task to get right. One needs to understand its mathematical principles as well as the ability to detect security vulnerabilities which are often missed by automated scanners. When working with a third-party firm that specializes in application security, they can provide you with the expertise and guidance to ensure proper development of your software. If your team is developing software that relies on cryptographic techniques, talk to one of our experts today.

Subscribe to Our Blog

Stay up-to-date on the latest ISE and cybersecurity news.

We're committed to your privacy. ISE uses the information you provide to us to contact you about our relevant content, products, and services. You may unsubscribe from these communications at any time. For more information, check out our privacy policy.