Common Web Application Vulnerabilities - Part 9
In this series of posts, my colleagues and I will dig into some specific, common web application vulnerabilities we observe regularly while performing network and application pentests. The intention of this series is to further expand upon a lot of the great information that already exists on the topic while preemptively addressing common questions we receive from our customers.
Part 9: Padding Oracle Attacks
Padding oracle attacks are becoming more frequent and recently made headlines with the Padding On Oracle Downgraded Legacy Encryption (POODLE) vulnerability within the 18-year-old SSL 3.0. Today, I will be diving into padding oracle attacks and what you can do to defend against them.
First, there a few items we need to look at in order to understand the nature of padding oracle attacks. First, we’ll look at how Cipher-Block Chaining, padding and the oracle work so we have a fundamental understanding. Then, we’ll look at how an attacker would conduct a padding oracle attack.
Cipher-Block Chaining (CBC) is a block cipher mode for encryption and is used for block ciphers to encrypt network traffic in SSL implementations. CBC mode works by encrypting a sequence of bits as a single unit with a single cipher key applied to the entire block. CBC mode makes each sent message unique by implementing an initialization vector within the first block. Additionally, the block ciphers typically encrypt data in specific sizes that are commonly 8 and 16-bytes in size.
In CBC mode, each unit is XOR’d with the previous before the encryption occurs, which means that any encrypted unit requires the decrypted portion up until that point. Wikipedia - CBC Mode contains a nice illustration of this process:
The next piece of information we need to understand is the role padding plays in the process. Block ciphers need padding in order to make the plain-text to be encrypted a multiple of the desired block size (i.e. make a 3-byte plain-text a multiple of 8-bytes). One of the more commonly used methods for padding a block cipher text is PKCS7. The most common byte sizes are 8-bytes (DES) and 16-bytes (AES). This method of byte padding states that the value of each byte added is the number of the bytes to be appended to the end as padding for a given cipher-text (see Wikipedia - PKCS7).
Essentially, this looks like the below:
- 1 Byte is added
- \x01 is added
- 2 Bytes are added
- \x02\x02 is added
- 3 Bytes are added
- \x03\x03\x03 is added
This is done until the multiple of the desired block size is met. Looking at this another way, let’s say we have a plain-text size of 10-bytes with our desired size to be 16 bytes. In order to meet the 16-byte requirement, we would use the padding scheme of ‘\x06\x06\x06\x06\x06\x06’ in order to pad the plain-text to the appropriate size.
The above is an example that contains valid padding and should successfully be decrypted. The curious question now is what happens when a block is sent without valid padding? For instance, lets assume that instead of 6-bytes with a character value of ‘\x06’ we instead use the character values of ‘\x02\x09\x15\x21\x22\x23’. This would not be considered valid padding and as a result would not be decrypted. Furthermore, this is also a scenario where the application that conducts the decryption attempt may generate an error. This error that is generated can be useful as it grants an attacker the ability to differentiate between successful and unsuccessful decryptions for a given cipher-text.
In our analysis of how padding works above, I mentioned a scenario where a cipher-text with valid padding is accepted (fully decrypted without error) and unaccepted (decrypts with an exception). The oracle is the “all-seeing” counterpart to the remote application that analyzes whether or not the cipher-text is accepted. This also means that the oracle is the one to spill the beans to an attacker as to whether or not their attempt at using an arbitrary cipher-text is valid or not.
Lastly, I previously mentioned a way to determine a cipher-text with invalid padding is based on an exception being thrown be the application. Another example could be based on HTTP Status codes. There could be a configuration setup to respond to an HTTP Status 500 (i.e. internal server error) code for all cipher-texts with invalid padding that given.
Padding Oracle Attack
Now that we’ve established a fundamental understanding the CBC mode of operation, the purpose of padding and the “all-seeing” oracle, we begin to see how a padding oracle attack plays out.
An attacker that is appropriately placed on a network makes attempts to decrypt traffic using specific variations of cipher-texts to trigger an exception, or some kind of indicator, from the application’s oracle that can be used to differentiate between a successful and unsuccessful decrypt to plain-text. The attacker would then continuously try cipher-texts in a brute-force like manner, slowly decrypting the entire cipher-text to gain access to the plain-text data within.
There are multiple toolsets that can be used to automate the process for padding oracle attacks.
Poracle, written by Ryan Bowes, provides us with nice example of a vulnerable application where we can conduct a padding oracle attack. The setup contains an HTTP web server using Sinatra that has two separate directories: /encrypt and /decrypt. The /encrypt directory sends data encrypted with the current key, and /decrypt attempts to decrypt the data but only reveals whether or not it was successful to the client. The test application currently utilizes AES-256-CBC for encrypting the super secret message.
First, we start up the “RemoteTestServer.rb” test server file and then the “Demo.rb” file provided with Poracle. Once started, we then fire up the client that makes the initial request to the /encrypt directory.
Server is started and the client's initial request is sent.
Data received from the request to /encrypt.
As you can see, this request displays for us the cipher-text’s block size and encrypted data. Next, we see a series of requests made in an attempt to decrypt the cipher-text with a brute force like approach.
Decryption attemps made from client.
We begin to see the plain-text since the correct cipher-text's are used.
We can see above the plain-text data is slowly displayed as the attempts at the cipher-text begin to succeed. This eventually leads us to the end where the entire message has successfully been decrypted to reveal the super secret message. This demo took no more than five seconds to fully decrypt this data, although it was of relatively small size. The above is a nice idea of what the currently available exploit tool sets will do for us as well as grant us a visual to the brute forcing process.
I wanted to give a quick shout out to POODLE which is a recent well-known padding oracle attack against implementations of SSL 3.0, specifically with CBC mode block ciphers. SSL 3.0 has been found to contain CBC mode ciphers that are not covered by the Message Authentication Code (MAC) and therefore lacks integrity. This attack requires an attacker to be appropriately placed on the network and the ability to intercept traffic to send on modified requests. In the event that the modified request is accepted, when the correct cipher-text is successfully brute forced by an attacker, the plain-text data can be decrypted.
Remediation and Conclusion
The question on everyone’s mind is likely how do we defend against this attack? There are a few things that be done to defend against these style of attacks. First, all application error messages should be configured in such a way that an attacker would not be able to determine if an arbitrarily chosen cipher-text was successful or not in decrypting the cipher-text, i.e. custom errors codes.
In order to defend against the POODLE vulnerability, upgrading all services with vulnerable CBC mode Ciphers to more secure versions is recommended (i.e. all SSL 3.0 implementations should be changed to TLS 1.0, 1. or 1.2 with SSL 3.0 being disabled). For legacy applications that support but are not using SSL 3.0, TLS_FALLBACK_SCSV should be enabled to prevent downgrade attacks.
In conclusion, padding oracle attacks require flaws within CBC mode block ciphers that are currently used within SSL 3.0 and many other applications. In the case of POODLE, the attacker would need to be appropriately placed on the network containing the vulnerable service or application in order to intercept network traffic and send the modified requests.
It is important that an application’s oracle does not reveal exceptions in the event invalid padding is used within the cipher-text. This information, if discovered, would aid an attacker in brute forcing legitimate cipher-texts to thereby gain access to the plain-text data.
- Part 1.1 - XSS Overview and Reflected XSS
- Part 1.2 - Stored XSS
- Part 1.3 - DOM-Based XSS
- Part 4 - Command Injection Overview
- Part 5 - SQLi Overview and Examples
- Part 6 - Directory Traversal
- Part 7 - Cross-Site Request Forgery
- Part 8 - Session Fixation
- Part 10 - Abusing Same-Origin Policy