Imagine that you’re a hacker who has taken over a Wi-Fi access point at a coffee shop.
You don’t need to be there in person; you just need to be able to login to the access point as root (UNIX’s name for the system administrator).
If you can do that, you can almost certainly spy on, and sneakily modify, everyone’s network traffic.
However, you’re out of luck for coffee shop customers who are using HTTPS, because that traffic is encrypted.
At least, that’s the theory.
But by modifying traffic as it passes through your rogue access point, you can interfere with the way HTTPS connections are established.
That means you may be able to trick both ends of the connection – typically a browser and a server – into downgrading their security, falling back to using an old and less secure HTTPS version known as SSL 3.0.
If you can do that, you may then be able to extract confidential data, thanks to a bug known as CVE-2014-3566.
That’s not much of a name, so the Google researchers who worked out this attack have dubbed it POODLE, short for Padding Oracle On Downgraded Legacy Encryption.
How SSL 3.0 works
Very simply put, POODLE works because the encrypted data in an SSL 3.0 packet is arranged like this:
The MAC is a Message Authentication Code (MAC), or cryptographic checksum, used to ensure that the encrypted data hasn’t been tampered with along the way.
The padding is just that: extra bytes tacked on the end of the data to pad it out so that the encryption algorithm can process it properly.
→ Padding is not needed if the connection is using what’s known as a stream cipher, such as RC4, because stream ciphers can encrypt any number of bytes at a time, from one to millions. But if the HTTPS session is configured to use SSL 3.0 with a cipher such as AES-CBC or 3DES-CBC, it has to consume its data in fixed-size chunks, because AES and 3DES are block ciphers that can only encrypt one full chunk at a time: 8 bytes for 3DES, or 16 bytes for AES.
SSL 3.0 padding is done by adding zero or more bytes until the data size is one byte shorter than a multiple of the cipher block size.
Then, a final byte is added denoting how many padding bytes were added before.
Using the last byte to signal the size of the padding is convenient, because it makes it easy for the other end of the connection to get rid of the padding later, by doing this:
- Decrypt all the data (user data, MAC and padding).
- Chop off the last byte to get a count of how many padding bytes there are.
- Chop off the padding bytes.
- Chop off the MAC to leave just the confidential data.
- Verify that the MAC matches the checksum of the confidential data.
Note that if the data and MAC are already a multiple of the cipher block size, you can’t just leave it at that, because you always need to add at least one count byte, even if only to say that you’ve added zero padding bytes.
So, if we have 16 bytes of data plus a 16 byte MAC, and we are encrypting with AES (i.e. in 16-byte blocks), we’ll need 15 bytes of padding, plus a final byte (set to the value 15) to round out the overall content to 48 bytes, an exact multiple of the AES block size:
Cryptographic flaws in SSL 3.0
You probably have an inkling of the flaws in SSL 3.0 from the diagram above.
Firstly, the padding bytes and the padding count aren’t included in the MAC, and secondly, the 15 padding bytes can be anything at all and therefore cannot be validated or verified.
So, if you tamper with the last 16 bytes of the encrypted data, replacing them with absolutely anything you like as they pass through your rogue Wi-Fi router, there’s still a 1-in-256 chance that the entire 48 byte data packet will be accepted by the server.
If the last byte in the modified last block just happens to decrypt to the value 15, then the server will chop off that final byte, and then blindly but correctly chop off the other 15 bytes of padding, blissfully ignorant that the padding bytes are completely different from when they left the user’s browser.
That will leave the MAC, which will match the checksum of the confidential data, and the packet will be accepted even though it was altered.
This may not sound like much of a cryptographic hole, since only data that is going to be discarded anyway has been tampered with.
But it should be ringing a warning bell: modifications should always be spotted and if there are any inconsistencies in the received data, it should be rejected.
Deliberately devious tweaks
Now imagine that instead of randomly altering those last 16 bytes, you try some deliberately devious tweaks instead.
What if you copy the first 16 encrypted bytes and write them over the encrypted padding bytes, and then pass the data along?
If the server accepts your modified data stream, you now know that that the last byte of the block you copied decrypted to the value 15, otherwise the server would have extracted the wrong MAC and the data verification would have failed.
You just tricked the server into telling you something about the encrypted data you copied across!
Likewise, if the server reports an error, you know that the last byte of the first 16-byte block is not 15.
That doesn’t sound like much of an information leak, but in this case, size doesn’t matter: strong encryption isn’t supposed to leak anything at all.
You shouldn’t be able to extract anything about the plaintext in an SSL 3.0 data packet merely by fiddling with the encrypted data stream.
Clearly, we have a problem.
Cipher Block Chaining
Actually, the description above isn’t quite correct, because we omitted one aspect of the way that SSL 3.0 does its block ciphering, namely that is uses Cipher Block Chaining, or CBC.
That’s actually a security enhancement that XORs the previous block of ciphertext with the current block of plaintext before encrypting each block.
The first plaintext block, of course, doesn’t have any previous ciphertext to draw on, so it is XORed with a random starting block known as the Initialisation Vector, or IV.
CBC ensures that even a run of identical blocks, such as a sector’s worth of zeros, won’t encrypt into a recognisably repeating pattern of ciphertext blocks.
That’s because of the the random IV mixed in at the start, and the randomness that then percolates through the encryption of each subsequent block.
So, when the server unscrambles your sneaky copy of those first 16 encrypted bytes that you wrote over the padding block at the end, it decrypts it and then XORs it with the previous 16 bytes of ciphertext (which just happen to be the encrypted MAC – the middle 16 bytes in our diagram above).
Ironically, this actually improves your chances of learning something about that last byte in the copied block.
As described above, with straight decryption only, you could only tell if the last byte was 15 or not.
But with CBC, that last byte is decrypted and then XORed with what is an essentially a random number.
In other words, it’s not always going to be a plaintext byte of 15 that decrypts to 15 to trigger the POODLE trick and give the byte away.
In fact, if you can somehow persuade the user’s browser to generate the same HTTPS request many times, for example by tricking it into thinking it needs to re-send the data due to an error, you’ll have a fresh 1-in-256 chance every time of working out what that last byte is.
That’s because the random IV means that you’ll get a different stream of encrypted data every time.
Sooner or later, you’ll recover the 16th byte of the original plaintext.
Recovering plaintext one byte at a time
Then you can recover the new 16th byte in the block, which was the previous 15th byte, and so on.
One obvious way to control the positioning of both known and unknown content in SSL 3.0 packets is by generating a series of download requests in which you ask for a file that is one character longer each time.
You can then predict where the filename will appear in each HTTP request, and thus almost certainly work out where the HTTP headers, including the data you want to decrypt and steal, such as a session cookie, will be located:
The green data is controlled by you, because it is determined by the URL in the web request; the red data is the confidential content inserted by the user’s browser that you want to attack using POODLE.
What to do?
The problem is SSL 3.0 and its unauthenticated, unverifiable padding process.
SSL 3.0 is an old version of the secure socket layer protocol: about as old as XP, in fact.
It was long ago superseded by safer alternatives such as TLS 1.0, TLS 1.1 and TLS 1.2.
So consider turning it off altogether.
You can tell your browser not to support SSL 3.0 connections, so that no rogue cybercrook in a coffee shop can downgrade your HTTPS sessions to his own advantage.
And you can tell your servers not to offer or to accept SSL 3.0 connections, so that you can never be tricked into accepting a malicious sequence of POODLE downgrade requests.
Please be aware: if you run a web server that refuses SSL 3.0 even when users specifically ask for it, those users, who might be your customers, will no longer be able to access your HTTPS pages.
But when WordPress.com VIP, the service on which Naked Security is hosted, wrote to tell us that it turned off SSL 3.0 on all its sites, including ours, it pointed out that only about 1 in 1000 users make SSL 3.0 connections at all.
Those 1 in 1000 users have much bigger problems than POODLE: most of them are using SSL 3.0 because they’re still running IE 6 on Windows XP.
And that’s a story for another day…