8

I'm evaluating a credit card processor[1], and I noticed they are using MD5 as part of a salted hash algorithm to protect a secret key. Since I know MD5 is generally considered broken, this feels like a poor solution. Is that enough of a criteria to reject them as our processor? Is it possible to demonstrate an attack?

(If this ought to be on a different StackExchange site, please let me know.)

Here's the specific scenario, simplified to the salient points.

Credentials

First, I have a "secret key" of 30+ upperalphanumeric characters and symbols. (Say, TUQ1ICGIIIK/PSBKNDFK=GNKOTHMMDBI.) I also have an "merchant id" of 12 digits. (Say, 123456789012.)

Publicly Accessible Payment Form

Second, the simplified payment form looks something like this. (The real form would include other parameters like name and address.)

<form action="https://examplepaymentprocessor.com" method="POST">
    <input name="MERCHANT" value="123456789012" />
    <input name="TAMPER_PROOF_SEAL" value="d550a25dfb97697f5be928953ee7cfc4" />
    <input name="TPS_DEF" value="MERCHANT AMOUNT TRANSACTION_TYPE" />
    <input name="AMOUNT" value="10.00" />
    <input name="TRANSACTION_TYPE" value="SALE" />
    <!-- other input fields for credit card number, contact information, etc. -->
    <input type="submit" value="Make Purchase" />
</form>

The "tamper-proof seal" is the "digest" of an MD5 hash of, in this case, a "message" composed of a string concatenation of:

  1. my secret key,
  2. my merchant id,
  3. the amount of the transaction, and
  4. the transaction type

Thus, in this case, MD5("TUQ1ICGIIIK/PSBKNDFK=GNKOTHMMDBI12345678901210.00SALE") = d550a25dfb97697f5be928953ee7cfc4.

TPS_DEF allows the user to specify the specific content of the message—or, if you prefer, the secret key plus a salt. The message includes, at minimum, the secret key, but could include up to all other parameters on the form. My example includes the merchant id, the amount, and the transaction type.

Data Retrieval

The process to retrieve example transactions is similar. Through either a (not publicly accessible) HTML form or some other method to HTTP POST, I can get information about a given transaction. (Assume that I have a transaction ID given to me from the above procedure.)

<form action="https://examplepaymentprocessor.com/transaction_status" method="POST">
    <input name="MERCHANT" value="123456789012" />
    <input name="TAMPER_PROOF_SEAL" value="d550a25dfb97697f5be928953ee7cfc4" />
    <input name="TPS_DEF" value="MERCHANT" />
    <input name="TRANSACTION_ID" value="1234567890" />
    <input type="submit" value="Get Info" />
</form>

This will return information including all the contact details of the customer and the last four digits of their credit card number. Note that, again, you (or an attacker) can specify the TPS_DEF as desired.

Imagined Attack

Given that MD5 is vulnerable to a chosen-prefix attack, I've played with using HashClash from Mark Stevens, but that seems to create two new messages with certain prefixes, rather than creating a second message whose MD5 matches the first. It seems, though, that someone with their own secret key could potentially create transaction status request that, would hash in such a way that it would retrieve my data rather than theirs.

Questions

  • How likely is it that an attacker could falsify the "tamper proof seal" to imitate me? (Either for forged transactions or for getting customer & transaction information—the latter is what I think is most likely.)
  • Are there other attacks that you can imagine or demonstrate?
  • Would you reject this processor? (Note that they are a perfect match for us in every other respect.)

EDIT 1: Reading this other question makes me think that, since MD5 is still resistant to pre-image attacks, this particular situation is safe.

EDIT 2: I clarified my question about an attack to be about both forged transactions and stolen customer information.

[1] Not named here. Email me for specifics.

  • 2
    Their choice of MD5 isn't the issue. But that they think hash(k||m) is a good MAC is problematic. See [Why is H(k||x) not a secure MAC construction?](http://crypto.stackexchange.com/questions/1070/why-is-hkx-not-a-secure-mac-construction) on crypto.SE. – CodesInChaos Apr 17 '13 at 16:46

3 Answers3

12

This "tamper proof seal" is a homemade MAC, and not a good one.

That MD5 is "broken" has no bearing here. MD5 is broken for collisions and collisions do not have any impact on your situation. What could be a worry is length extension attacks. This is because MD5 is a Merkle-Damgård function. This means that when MD5 processes a message m, it does the following:

  • The message m is padded with a bit sequence p, which has length between 65 and 576 bits (inclusive), so that the total length of m||p is a multiple of 512. p depends on the length of m, but not on the contents of m.
  • The padded string m||p is split into 512-bit blocks.
  • MD5 processes each block in due sequence, using a 128-bit state which is the result of the processing of the previous block. The hash output is the output of the processing of the last block.

Now imagine that the attacker could see one of your "tamper proof seals". The seal is a hash of some m which the attacker does not know (it begins with your secret key). However, the attacker might make a good guess at the length of m. Thus, the attacker can compute p. Now, the attacker chooses a string m', arbitrarily. The "length extension attack" is that he can compute MD5(m||p||m') even without knowing m, because he knows the state of MD5 when it has processed m||p: that's exactly your "tamper proof seal" value. He can then use that as starting point for processing the blocks that m' consists in.

What may save you in your case are the two following points:

  1. Even if the attacker can choose m' arbitrarily, he can only append, with the padding p in between. His goal is to compute a hash for a syntactically valid transaction. Depending on the actual encoding of the "amount" and "transaction type", the attacker may or may not design some m' such that m||p||m' still makes some sense on the server side.

  2. The attacker must observer one "seal" value to begin with. Since they are transmitted with HTTPS, this might prove difficult for him.

Important note: the length extension attack would work exactly the same (modulo some endianness details in p) with SHA-256. This does not exploit a specific weakness of MD5.

The correct way to compute a MAC is HMAC. HMAC uses an underlying hash function like MD5 or SHA-256, but it does so "smartly", with two nested invocations, precisely to avoid problems such as the length extension attack.


As for your exact question: no, I don't think this is ground for refusing to do business with these people. After all, the MAC is not a "proof", despite its name. This is symmetric cryptography: to verify the seal, the server must know your secret value as well. Correspondingly, the server has the technical power to make "fake" seal values. In case of dispute between you and the credit card processor themselves, you could point that out: the seal cannot be used as a proof against you, during litigation.

This seal is what they require to authenticate you, so it is, basically, their responsibility. I suggest you leave their own problems to their hands. You may want to raise the issue as a courteous warning, though. Something along the lines of: "ya know, for a good seal, you'd better use a standard, NIST approve solution like HMAC/SHA-256, rather than a non-standard homegrown mechanism with MD5 (of dubious repute)". The known weaknesses of MD5 (as compared to SHA_256) don't have a practical impact on security in this specific case, but the name "MD5" and its bad press can still be effective as diplomatic leverage.

Tom Leek
  • 170,038
  • 29
  • 342
  • 480
  • Thank you for the insight on length extension attacks. I was not aware of those and have learned something new today. – Sébastien Renauld Apr 17 '13 at 15:42
  • Still digesting your answer, but one point of clarification: in the case of a purchase form, the "seal" is actually publicly visible to the purchaser in the HTML form, as well as the merchant id and the `TPS_DEF`. The "secret key" is (obviously) not visible. – David Alan Hjelle Apr 17 '13 at 15:47
  • Thank you so much for your excellent answer! I've learned a lot. Plus, after your pointer to length extension attacks and trying out the [HashPump](https://github.com/bwall/HashPump) program, I see that, while they are *oh-so-close* to an exploit, the first mitigating factor you mentioned (valid syntax of the padding data) seems to cover all the possible bases I can see. – David Alan Hjelle Apr 17 '13 at 17:42
1

If they're using it as a concat signature (effectively, that's what it is - it guarantees that the parameters were not tampered with), and seeing the order of parameters, I dare say that MD5, whilst not the best choice on Earth, is not as bad as it may sound.

Chosen-prefix collisions are trivial (order of 2^{50} ) to generate in the following situation:

  • you know hash(p1 // m1) (True)
  • you know p1 (False. Your prefix is your private key, which is supposed to be private)
  • you pick a second prefix p2

Chosen-prefix attacks do not therefore necessarily apply. Not just this, but in order to effectively forge a transaction, you'd be looking to change one segment of the hash, keeping all others constant (you don't want a different public or private key, if you were to forge something, you'd only change the amount).

So, in reality, it's not the best (HMAC-SHA256 is usually used for this purpose), but it does the trick and is relatively secure (for a given value of relative). I personally would base the rejection/acceptance based on the amounts going through and the payment provider's insurance payout in the case of a forged transaction that was not your fault.

  • But the signature being sent over the same form as the parameters? I dunno.. sounds weird to me. –  Apr 17 '13 at 15:10
  • How is this different to how most APIs sign their requests? The only difference is that all the ones I know (PayPal, Amazon, Azure) use HMAC-SHA256 to generate the request signature. Format remains the same - worse, Amazon's is in GET rather than POST! – Sébastien Renauld Apr 17 '13 at 15:12
  • (Adding to this: to forge a MD5 hash that has 3 of the four concatenated strings the same, without knowing one of the three equal parameters would take significantly more than 2^50 hash evaluations) – Sébastien Renauld Apr 17 '13 at 15:14
  • I must admit I'm not all that familiar with the way APIs sign their request. It just seems weird to me that the thing being used to verify integrity is being sent over the same form. I guess some reading up is in order. –  Apr 17 '13 at 15:15
  • AWS signing helper: http://aws.amazon.com/code/JavaScript/2609 . Paypal: https://www.paypalobjects.com/WEBSCR-640-20130317-1/en_US/DE/pdf/PP_APIReference.pdf – Sébastien Renauld Apr 17 '13 at 15:22
  • (Those signatures are there to prevent MITM attacks, by the way. What makes them difficult to forge is that the private key is a factor in the signature - and the private key *isn't* in the form) – Sébastien Renauld Apr 17 '13 at 15:23
  • What seems odd about this situation is: (1) it isn't (necessarily) preventing MITM, since you specify the factors in the signature (except for the required secret key) and (2) because you can specify the factors in the digest, it you can effectively "pad" the message and manipulate the hash. You mentioned "_change one segment of the hash, keeping all others constant_": but, for data retrieval, an attacker doesn't have to keep *anything* constant, right? Nonetheless, chosen-prefix doesn't seem to apply since an attacker can't manipulate the factors for *both* hashes. Am I understanding right? – David Alan Hjelle Apr 17 '13 at 15:35
  • @DavidAlanHjelle: If trimming is done before signature validation on the receiving end, you have a point - one could in theory manipulate the hashes by padding. However, in most cases, people are not that stupid. As for data retrieval - the same process applies, the attacker still has to modify the signature to change the transaction ID, keeping the merchant ID, private key and TPS_DEF fields constant. Assuming the private key comes first again, chosen-prefix attacks cannot occur. To comment on anything else, one would have to see the provider's API code. – Sébastien Renauld Apr 17 '13 at 15:39
  • Thanks, I was previously confused only because I did not notice that the secret key wasn't being sent over the form as well. –  Apr 17 '13 at 15:43
0

It would be better if they used SHA-256. However, the design looks like a brute force forgery attack would be quite computationally expensive. I think an attacker is more likely to try to bypass it via malware, MITM or social engineering. Honestly, they rarely try to break straight through the crypto unless it's a poorly done password hash. The payment processor might still be worthwhile if other aspects of a business agreement look good.

Nick P
  • 677
  • 4
  • 4
  • 2
    Using SHA-256 wouldn't have had any practical effect. Using a proper MAC construction is far more important. HMAC-SHA-256 > HMAC-MD5 >> SHA-256(k||m) – CodesInChaos Apr 18 '13 at 11:45
  • 1
    I assumed an HMAC. It's good that you explicitly said it, though. – Nick P Apr 18 '13 at 18:59