IBM WebSphere Commerce or WebSphere Commerce Suite (WCS), developed by IBM, is a software platform framework for e-commerce and is actively being used by giant retailers.
While working on an engagement last year, I stumbled upon a crypto vulnerability in the IBM Websphere Commerce framework, originally found by VSR Security (CVE-2013-05230). Essentially the krypto parameter found in some URLs could be decrypted using a padding oracle attack. Since no public exploit has been published as time of this writing, I figured it might be an interesting exercise to write one.
if (decrypting) {
if (outputCapacity < paddedLen) {
cipher.save();
}
// create temporary output buffer so that only "real"
// data bytes are passed to user's output buffer.
byte[] outWithPadding = new byte[totalLen];
totalLen = finalNoPadding(finalBuf, finalOffset, outWithPadding,
0, totalLen);
if (padding != null) {
int padStart = padding.unpad(outWithPadding, 0, totalLen);
if (padStart < 0) {
throw new BadPaddingException("Given final block not "
+ "properly padded");
}
This crypto library will throw a BadPaddingException when invalid padding is encountered. It is then up to the code that is using this library to handle this exception. In this case, IBM WebSphere Commerce framework seems to leak the information about the padding byte by returning a different response when invalid padding occurs.
Detection
Once you have found a page with krypto URL parameter, differentiate between the following conditions:
Valid ciphertext decrypted
Valid padding – You will need this one to de-krypto 🙂
Invalid padding error
In real world scenario, I found condition (1) and (2) are the same for most of the time. Here is how to test it:
You can use Burp’s Comparer tool to compare those responses. If (3) is different from (2) and (1) then it may be possible to decrypt this parameter.
Exploitation
Padding oracle attack is not specific to any cipher, rather it is a generic attack against CBC ciphers. Therefore any padding oracle implementations will work in this scenario. I have looked at several padding oracle algorithms, and Ron Bowes’ algorithm by far is the fastest one. The reason is, most padding oracle algorithms iterate over the ciphertext bytes of [Block (n-1)] randomly (bytes ranging from 0-255) to find the plaintext of [Block n]. Ron’s algorithm also iterates over the ciphertext bytes of [Block (n-1)]; but instead of doing so randomly, it loops over a defined character set first (which is composed of ASCII characters, bytes ranging from 32-126), then the rest of the possible byte values (0-31 and 127-255). This greatly reduces number of requests sent, since most meaningful string is composed of ASCII characters.
In addition, I made the following adaptations to Ron’s poracle framework in order for the exploit to work with this particular case:
Encoding/decoding
Ron’s Bowes’ script assumes the payload is in hexadecimal format. So extra encoding/decoding of the krypto parameter is required. The decoding process is as follow:
URL decode key characters (including newline)
Base64 decode
ASCII encode
Encoding steps:
ASCII decode
Insert newline character at every 77th character (RFC 2045 or 4880)
Base64 encode
URL encode key characters
Format of payload
Ron’s original script is made on the assumption that the server will decrypt any two-block payload provided by the attacker. Let us assume that our valid ciphertext blocks is:
[Block 0] [Block 1] [Block 2] [Block 3]
To decrypt [Block 2], we need to send
[Block 1] [Block 2*]
and wait until the server returns padding error.
However, with IBM Web Commerce, the server does not decrypt any arbitrary two-block payload. It seems to require a valid header or expect certain values at the beginning of the block. Therefore, in order to decrypt [Block 3], we need to send:
[Block 0] [Block 1] [Block 2*] [Block 3]
This is an easy fix, I only needed to append the early blocks to the payload.
Parallelization
I added support for multi-threading. The script uses Meh’s Ruby thread pool library to reduce the overhead of creating and destroying threads.
I also added the ability to skip already-decrypted blocks and save temporary results to a session file. In situations where the connection ends abruptly, the script only needs to work off the remaining blocks.
Usage
Usage: Usage: Dekrypto.rb [options]
Specific options:
-s, --sort Sort temporary results
-v, --verbose Show debug messages
-t, --threads SIZE Set threadpool size
-f, --file FILE Save temporary results to file
-h, --help Show this message
Example
Running test server:
ruby KryptoTestServer.rb
Running Dekrypto script with verbose output, ten threads, saving temporary results to a text file (decrypted.txt)
When testing against real applications, I notice that some blocks may not be decrypted properly. My guess is that the server may catch earlier exception in the decoding phase (at either the URL decoding step or the UTF-8 decoding step) and return valid response. Currently, I do not know how to overcome this limitation so any suggestions will be much appreciated.
Necessary cookies help make a website usable by enabling basic functions like page navigation and access to secure areas of the website. The website cannot function properly without these cookies.
Name
Domain
Purpose
Expiry
Type
YSC
youtube.com
YouTube session cookie.
52 years
HTTP
Marketing cookies are used to track visitors across websites. The intention is to display ads that are relevant and engaging for the individual user and thereby more valuable for publishers and third party advertisers.
Name
Domain
Purpose
Expiry
Type
VISITOR_INFO1_LIVE
youtube.com
YouTube cookie.
6 months
HTTP
Analytics cookies help website owners to understand how visitors interact with websites by collecting and reporting information anonymously.
We do not use cookies of this type.
Preference cookies enable a website to remember information that changes the way the website behaves or looks, like your preferred language or the region that you are in.
We do not use cookies of this type.
Unclassified cookies are cookies that we are in the process of classifying, together with the providers of individual cookies.
We do not use cookies of this type.
Cookies are small text files that can be used by websites to make a user's experience more efficient. The law states that we can store cookies on your device if they are strictly necessary for the operation of this site. For all other types of cookies we need your permission. This site uses different types of cookies. Some cookies are placed by third party services that appear on our pages.
Cookie Settings
Discover why security operations teams choose NetSPI.