I’m excited to announce that I will be presenting at this year’s Black Hat Asia
about my research into detecting and exploiting CBC padding oracles!
Zombie POODLE and GOLDENDOODLE are the names I’ve given to the vulnerabilities I’ll be discussing. Similar to ROBOT
, DROWN and many other vulnerabilities affecting HTTPS, these issues stem from continued use of cryptographic modes which should have been long ago deprecated and yet are inexplicably still supported in TLSv1.2. In this case, the troublesome feature is that TLSv1.2 supports CBC mode ciphersuites.
To understand these flaws, it’s important to have a little background on block ciphers and cipher-block chaining (CBC) mode.
A block cipher operates on discrete blocks of data as opposed to a stream cipher that would encrypt individual bits. AES is an example of a block cipher, while RC4 is a stream cipher. AES can only encrypt or decrypt 128-bit blocks of data. It is not possible to directly encrypt or decrypt more or less bits with AES without defining a mode of operation. CBC is a mode of operation for block ciphers in which ciphertexts are chained together via XOR. By doing this, repeated plaintext will not lead to repeated ciphertext, and modification of a ciphertext block will also change the plaintext in the following block.
A high-level overview of AES-CBC mode encryption in TLS is as follows:
- Plaintext message is split into discrete 16-byte blocks of data
- An initialization vector (IV) is randomly generated
- First block is encrypted using the selected block cipher and key
- Block cipher output is XORed with the initialization vector
- Result from #4 is stored as the first block of ciphertext
- The next block of plaintext is passed to the block cipher
- Output from the block cipher is XORed with the previous ciphertext block
- Result from #7 is stored as the next block of ciphertext
- Steps 6-8 are repeated until all plaintext is consumed
CBC mode decryption reverses this process by decrypting each block and XORing it with the previous ciphertext block (or IV) to recover the plaintext from that block.
Wikipedia has a nice illustration of how this works:
Credit: CBC decryption illustration by WhiteTimberwolf, https://commons.wikimedia.org/w/index.php?curid=26434095
Since AES-CBC only works with multiples of 128-bits, inputs may require extra bits to be evenly divided into blocks. These extra bits are called padding, and TLS prescribes a specific format for this padding. If a server reveals whether the padding conforms to a specific format, it is leaking information about the decryption to an attacker and may create the opportunity for a chosen ciphertext attack.
The POODLE attack leverages the fact that SSLv3 did not prescribe a deterministic format for padding and therefore could not fully validate these bytes. The implication is that an attacker with the ability to relocate an interesting ciphertext block to replace a block of padding can decrypt the last byte of the targeted block if the server confirms a proper padding. This is what is known as a padding oracle, and it’s really not as hard as it sounds to exploit.
What was POODLE?
In the wake of POODLE being revealed, it was quickly discovered that POODLE also affected many systems without SSLv3 because these systems incorrectly used the SSLv3 padding function in their TLS implementations.
For an excellent illustration of how the POODLE attack works, I recommend reading the older write-ups from Adam Langley
or Matthew Green
. At a high-level though, for this attack to work, the attacker must be able to trigger requests from a victim to an authenticated resource while actively intercepting and modifying the resulting SSL records. In other words, the victim’s web browser must have authenticated session cookies for a service using a vulnerable TLS stack.
Although this sounds challenging, it is more or less just an arithmetic problem based on things like hostname length and whatever default headers the victim’s browser sends.
As an example, let's consider a request to https://Example.com. In order to encrypt this request, the client must calculate a message authentication code (MAC), append this value to the request and then add padding to fill the final block. The result (for TLS) is as follows with MAC bytes replaced with XX:
Each row on the right represents a block which will be fed into the block cipher and chained together with XOR to produce 8 corresponding ciphertext blocks which will be encapsulated by a TLS record layer and then sent to the server.
The POODLE attacker allows the HTTPS handshake to occur without interference, but when the encrypted application data payload is sent, they replace the last ciphertext block (e.g. full of padding) with the ciphertext block expected to have a session cookie. The altered TLS record now looks like this:
Upon receipt, the vulnerable server will first decrypt the ciphertext as per the CBC decryption process. In doing so, the plaintext output from the last block will be the result of a bitwise XOR the 'Block 7' ciphertext with the deciphered Block 5. This means that the last block of plaintext will effectively be random. The final byte of this plaintext will be interpreted as a padding length vector that I will refer to as n
For a proper TLS implementation, the server will verify that the last n+1
bytes all have the value n
. If this is not true, the server is expected to reject the message with a generic 'Bad Record MAC' TLS alert. POODLE TLS vulnerable implementations fail to perform this check and will instead simply remove the last n+1
bytes. The final 20 bytes of the remaining buffer are set aside and compared to the MAC calculated from the remaining bytes. The only way for the MAC to be valid in this case is if the plaintext had ended with 0x0F
. The attacker is able to observe this based on whether the server rejects or accepts the modified record.
If the record is accepted, the attacker now knows that the last byte of the block cipher output from Block 5 XOR'd with the last byte of the Block 7 ciphertext yields the value 0x0F
. The attacker can now compute the plaintext of the last byte from Block 5:
 denotes the last byte of the Block 5 plaintext and Cn
 denotes the last byte of ciphertext block n. The attacker would then adjust the URL and headers in the controlled HTTPS request so that another byte of plaintext will align with the end of a block. For example, the requested path could be trimmed by a byte to shift the position of the cookie value while simultaneously adding a 15 byte header to maintain the 16 byte padding length. (A 15 byte header will add 17 bytes due to the CRLF line ending.) This process repeats until all desired bytes have been decrypted. On average, each byte will take 256 requests to decrypt since the encrypted bytes are effectively random.
It seemed back in 2014 or early 2015 that all the popular stacks with POODLE TLS had been discovered and patches had been issued. That’s why I was quite surprised when I developed a generic CBC padding oracle detection tool and found that POODLE is actually still readily exploitable on at least one prominent middlebox/load balancer product by only making a very slight tweak to the underlying oracle.
Because I had thought POODLE died years before (and because ROPOODLE doesn’t roll off the tongue), I affectionately called this finding Zombie POODLE. Citrix has now released a patch for Zombie POODLE under the ID CVE-2019-6485.
I strongly encourage all Citrix users to upgrade immediately.
The other finding, GOLDENDOODLE was named with tongue firmly planted in cheek as a cousin to POODLE. It is quite similar to POODLE in that they both allow a man-in-the-middle to decrypt certain data like session cookies. The similarity ends, however, when considering attack performance.
Whereas POODLE requires an average of 256 tampered requests per byte being decrypted, each request in the GOLDENDOODLE attack allows the attacker to guess the value of a plaintext byte. In practical terms, this means that an uppercase hexadecimal session ID will require at most only 16 requests per byte.
Do we really need another named crypto vulnerability?
NO. I absolutely didn’t need to name these, but naming vulnerabilities is fun, and you know what’s said about all work and no play. Plus, names have made it easier when communicating with vendors.
Exactly how much sleep should I lose over this?
For most people, the answer is none or at least no more than was warranted by POODLE. Although these conditions can be exploited in a practical manner and could expose access to thousands of systems, the attacks have certain preconditions which limit the likelihood of widespread exploitation. Exploitation requires a man-in-the-middle position, and the exploitation must be tuned somewhat for different environments to determine block offsets of authentication tokens being targeted.
How can I detect these flaws on my network?
Currently, Tripwire IP360’s
generic CBC padding oracle detection is the only tool known to detect these conditions. Public testing tools will be made available at the time of my talk.
I’m a vendor making products with a proprietary TLS stack or hardware TLS acceleration. Can I test my product already?
I have made a Go-based scanning tool which is available (under embargo) to vendors looking to test their systems.