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…