Plimus vulnerability: "Plimus uses MD5hex encryption"
In my
last
blogpost about Plimus I talked about the lack of SSL based security. At some point in time
Plimus must have realized this and started looking for a solution. Of course, Plimus is a serious
business and can't afford to break backwards compatibility for their customers and so
devised their ingenious "MD5hex encryption" technology.
Let's think back about the lack of proper use of SSL and the problems that this brings:
- No identification
- Possible to alter data
- Possible to record data
Now let's see what Plimus claims to protect:
Parameters Protection is an advanced feature that helps prevent
unauthorized changes to sensitive BuyNow page parameters, such as last name, currency, and custom
fields. The protection involves the selection of the relevant parameter data and its encryption
using MD5hex technology. In order to use this feature you will need to set up a Data Protection
Key (link) if you have not already done so. This single key can be used to generate encryption in
a number of different situations in relation to your Seller account. Enter your key details into
the appropriate field.
So Plimus claims that this feature protects against data
modification and as a side effect also some identification.
When you study how this "MD5hex technology" works, you will see it's nothing more than a basic
HMAC (Hash-based Message Authentication Code).
Let's walk through an example with a simplified
IPN-like message to see how this works:
First you need to enable parameter protection in the Plimus admin. (No protection by default.
Backwards compatibility, remember?) Now you can choose which fields you want to protect.
Don't ask me why you wouldn't want to protect all fields, I have no idea. Our simplified
IPN has the following fields: transactionType, productId, price, firstName and
lastName.
Without parameter protection the following POST data will be send:
transactionType=CHARGE
productId=1337
price=100
firstName=Floor
lastName=Terra
Now let's say we only protected productId and price and we used the shared secret "topsecretkey".
Now Plimus will send the following
IPN:
transactionType=CHARGE
productId=1337
price=100
firstName=Floor
lastName=Terra
authKey=336e6416fe2181620adc57bcbec1b8f1
This is how the authKey is calculated (in Python):
>>> import md5
>>> md5.md5("1337"+"100"+"topsecretkey").hexdigest()
'336e6416fe2181620adc57bcbec1b8f1'
Just simple concatenation of the values plus the shared secret and the md5sum over that string.
This should protect against tampering by people who don't know the shared secret. But there are
still a few problems:
- People can still read the data
- No data is protected by default
- After enabling parameter protection, most data is still not protected unless you enable it
for all fields yourself.
How about the identification I talked about earlier? If all the data is still readable in
clear text, Plimus should make sure it doesn't send the customer data to the wrong party. Plimus
does that, kind of,
after sending the data.
After enabling parameter protection, the webshop that receives an
IPN should now
return a specific value to Plimus to prove it knows the secret key. How do you calculate the
return value?
>>> import md5
>>> md5.md5("OK"+"topsecretkey").hexdigest()
'9f7a77a9db565b595725ea3c0e39e8af'
Notice how this value is constant for all transactions. This has at least 2 consequences:
- An attacker can use a replay attack to fake authentication
- An attacker can build a rainbow table for md5 hashes of the strings "OK"+$sharedSecret in
advance and reverse the original shared secret.
And after the identification has failed, Plimus should stop all communication until an admin
has verified the server is ok and manually re-enables the communication. But what does Plimus do?
It keeps retrying the same
IPN and it keeps sending new
IPNs to the same,
possibly compromised, host.
To be continued...