Reputation: 2413
I'm implementing a simple store to take payments. I'm using a hosted store solution. The way it works is:
I want to make sure the transactions run as smoothly and securely as possible. The documentation for the store makes the process seem quite simple. All that really needs to be sent to the store provider is below, grabbed from their documentation.
<FORM METHOD="POST" ACTION="https://www.fakehostedstore.com/xxx/index.php">
<INPUT TYPE="HIDDEN" NAME="store_id" VALUE="abcdefg">
<INPUT TYPE="HIDDEN" NAME="store_key" VALUE="hijklmnop">
<INPUT TYPE="HIDDEN" NAME="charge_total" VALUE="100.00">
<!--MORE OPTIONAL VARIABLES CAN BE DEFINED HERE -->
<INPUT TYPE="SUBMIT" NAME="SUBMIT" VALUE="Click to proceed to Secure Page">
</FORM>
This has me somewhat concerned. If I, for example, opened up something like Firebug, I could change the "charge_total" to whatever I like before submitting the form. Very quickly, I could reduce the amount of the charge to be sent to the store from "100.00" to "10.00". The store, who will be making the charge, will be none the wiser, and proceed with the incorrect charge.
If the transaction completes at the store, the store sends back the amount that was successfully charged. I can then verify against my expected charge. For example, I expected a $100 charge, only $10 was charged, WTF!
Is there a way to secure this form in such a way that it is less susceptible to tampering?
Upvotes: 1
Views: 140
Reputation: 2413
I thought I'd mention how the store suggested handling this potential security issue. Perhaps this is applicable to others who are implementing secure hosted store pages.
The store offers two ways to take a payment. The first, "purchase", immediately takes the money from the credit card. This was the method I was using. It was easy to implement, but provided no assurance that the proper amount was charged to the card.
The second, "preauth", puts a hold on the money on the card, but does not take the money until an additional "capture" transaction is performed. By adding this step, it is possible to confirm the preauthorized charge before formally charging the card. If the charge is invalid, it is then also possible to remove the hold on the card.
In my case, I'm doing the "capture" transaction immediately, but it would be possible for an accountant to "capture" all of the day's "preauth"s together in a batch.
Upvotes: 0
Reputation: 41348
I think you can't do anything with that unless they change the method of handling the payments (like, for instance, you register a product in their service, with the fixed price, and they give you back product id, user inputs the number of items she wants to purchase, and then they calculate the total price on their side).
Do they send you back some data from the service (like the amount that was taken)? Do you have any possibility to see the amount the user paid (response value, some API call etc.) other than wait for the money to appear on the bank account? If not, their design is seriously flawed.
Regarding tampering, you can't really do anything to prevent power user from changing the value. It doesn't even necessarily have to be done at the browser level - she can use a proxy like Fiddler to tamper HTTP requests.
However, whether you should worry about it, depends on what and how you sell. If it's some immediate-selling platform (like you give access to some internet resources etc.) it's bad. If the shop is a hardware store which sends stuff by post, you can each time verify the amount received, comparing it to the one expected (I guess, there would be some automated tool to look up the incoming payments on the bank account, since usually you don't send stuff to the user until you see the money is on your account).
I immediately remembered myself similar thing I've read some day, somewhere (most likely on SO): in the early internet shops, you were sometimes able to input something like 0.01 in the "quantity" field, and on the server, the price was calculated by multiplying (so you paid 0.01 actual price!) while the quantity was rounded to integer!
Edit: do they have the documentation on the response they give? Have you tried doing a fake transaction?
Edit 2: Since the store gives you back the amount charged, that's good. However, this could still pose problems (non-technical) for the shop, because the money still will be charged. You can display the information on the next screen, saying that you've received 10x less that you want, but you still would have to return that money to the cheater (otherwise it'll be unlawful).
It's a pity the shop doesn't provide some kind of handling of message authentication code. In fact, there's a good way to prevent exactly these kind of cheats. However, both servers must cooperate in this.
Take a look at HMAC. It looks complicated, but the idea is simple. I'll explain it on the simplified algorithm.
You have an input, say price=100
. You hand it do the third-party. At this time, it's easy to tamper. But let's say we send additional field, price_verification
. We can calculate this using a pre-agreed hash function with pre-agreed salt (both you and the payment server must know it). Then you calculate, say price_verification=SHA1(price + someLengthySalt)
and send it to the payment server. They know the algorithm and the salt, so they calculate SHA1(received_price + someLengthySalt)
. If the two differ, user is a cheater and you abort the transaction. Of course, this is secure as long as the user don't know the algorithm and/or the salt, so he can't easily calculate price_verification
.
The salt should be really strong however, and the algorithm perhaps more convoluted, like SHA1(SHA1(price)+salt)
etc.). It needs to be taken into consideration that the input space for the price is very small (only numbers with 2 decimal places - can be easily brute-forced if there's no salt).
This could be easily extended to verify any number of parameters (you just need to make an agreement on how to serialize data).
Upvotes: 1