37

I know that a POST can be spoofed in terms of originating domain, but what about being able to change the variables of the hidden POST variables in my HTML? I am concerned that someone could alter the "amount" value in my PayPal form from this:

<input type="hidden" name="amount" value="1.00">

to this:

<input type="hidden" name="amount" value="0.01">

or something similar. Thanks.

Andrew Kozak
  • 1,631
  • 2
  • 22
  • 35
Vlad
  • 475
  • 5
  • 9

6 Answers6

76

Yes, it is trivially easy for anyone to modify your form variables. Whether they are GET or POST doesn't matter at all.

Web security rule #1: Never trust any user input. Also stated as "All users are malicious hackers" or some variant thereof.

answer to comment: The solution is to know all of the correct values on the server side, without having to pass them through the client side (Javascript). So regardless of what the form says, you already know the price. Just use the same value you used to populate the form in the first place.

Tesserex
  • 17,166
  • 5
  • 66
  • 106
  • 32
    Emphasis on the word *trivially* – Bob Kaufman Nov 29 '11 at 15:33
  • 1
    then what are my alternatives? only use php to create and submit the form? also, isn't this a security risk for all paypal merchants who don't use an encrypted button? (the reason I don't use an encrypted button is I need to change these variables on the fly) – Vlad Nov 29 '11 at 15:34
  • @Vlad see edit. Having the values in Javascript is mainly used for user convenience - for example, to do totals calculations before the form is submitted. – Tesserex Nov 29 '11 at 15:36
  • 7
    @Vlad Why do you need the user to pass back something that he/she is not allowed to use? Can you not just store that info server side, or if you have to send it to the user, sign the data so you can check if it has been tampered with? – Roger Lindsjö Nov 29 '11 at 15:38
  • If you're relying on data in the hidden form elements, then you're doing it wrong. "change the variables on the fly" is far easier to justify to your clients than than "selling your products for free" – Cylindric Nov 29 '11 at 15:40
  • I am creating an auction-like site where the price depends on time and other variables. Warnings heeded: I will submit the form server-side. Thanks – Vlad Nov 29 '11 at 15:42
  • 11
    Ideally, you wouldn't be taking amount as any kind of input. You would take a list of items, and you would calculate the amount in your php script. At the store, you would very rarely see clients fill their shopping carts, and then tell the cashier how much they have to pay. – Frank Nov 29 '11 at 15:42
  • 6
    +1 for that web security rule. Never (completely) trust any input that came from the client, ever. This potentially includes _encrypted cookies_. All input must be completely checked and validated, _every_ time it is recieved. Never store anything other than some sort of id/session token client side (which must still be validated). Note that some 'malicious' users may not be doing it deliberately, if their computer is part of a botnet. – Clockwork-Muse Nov 29 '11 at 17:05
  • I don't know why nodoby talks about **`_SESSION`** variables: you just put the **ids** of the products on the web page. Once the objects have been selected and sent to the server, save the ids and the # of objects. Then you internally fetch the prices and set them into **`_SESSION`** variables. Doing so you would never ever have such problems. – Olivier Pons Dec 05 '11 at 07:36
13

Update 2020:

OWASP covers this topic in "Injection Theory", where applications accept data from untrusted, uncontrolled, or potentially compromised sources.

Injection is an attacker’s attempt to send data to an application in a way that will change the meaning of commands being sent to an interpreter.

Review this OWASP "cheatsheet" for an overview of mitigations that can be implemented to better secure REST based endpoints.


Yes, it is very simple to do with browser inspector tools, JavaScript, cURL and other tools.


You shouldn't rely on the amount field being what you'd initially transmitted in the response to the client. A more secure approach would be to rely on an identifier for an item, which you can map to a price on the server (a more controlled environment).

Alex
  • 34,899
  • 5
  • 77
  • 90
7

Yes, it is possible to change that value using javascript. If you haven't practice in using javascript, you can also do the test using Google Chrome's Developer Tools.

Infact this is one of the main reason to don't rely on user input.

Aurelio De Rosa
  • 21,856
  • 8
  • 48
  • 71
7

Forget javascript and browser tools. Please realize that I can send ANY cookie, POST and GET argument (key and value pairs) I want, regardless of whether this is a form for them. (See cURL)

Frank said "At the store, you would very rarely see clients fill their shopping carts, and then tell the cashier how much they have to pay."

Try to think of it like that. The browser (not user) is the client and the server is the cashier. Any information that flows from the browser to the server can be anything I want.

user606723
  • 4,918
  • 2
  • 27
  • 34
5

Yes. It gets worse because they don't even have to alter your page to do it. A user could use any text editor to construct an html page with a form full of text boxes, load it from local disk, fill them with whatever they want and hit submit. OTOH, that will show up in some header values.

Or if they are really determined, that can connect to port 80 on your server via telnet and forge the entire HTTP request including headers.

There is not a single byte of the incoming request that you can trust.

That said, there are known solutions to these problems that are generally implemented in terms of hashes, signatures and cryptography, but I don't know enough to suggest where to look for them.

BCS
  • 75,627
  • 68
  • 187
  • 294
-3

In this case let them change the value if they want to, and let them pay you the $0.01. But then, when you get the Paypal IPN (Instant Payment Notification) it will include the price they paid; check that against your item database to make sure that it's the correct price.

If it's not the correct price, do not send/give the item. You earned $0.01!

Andreas Bonini
  • 44,018
  • 30
  • 122
  • 156
  • haha. Would that be legal? Taking the law into your own hands? – Ian Warburton Nov 29 '11 at 20:55
  • @Ian: What do you mean would that be legal? If I say that I sell pens for $10, and you mail me $1, do you really think I'm legally obliged to mail you a pen even if you paid less? – Andreas Bonini Nov 29 '11 at 21:30
  • Hmmm... don't move the goal posts! I mean if I give you $0.01 for an item and you don't send it and keep the $0.01. – Ian Warburton Nov 29 '11 at 21:34
  • @Ian: no, it's different. You know the item costs $1 (it's clearly specified) but you went ahead and *artificially modified the price* (a client-only thing) and then forced your computer to send the wrong amount of money. Do you really expect the item in this case? – Andreas Bonini Nov 29 '11 at 22:19
  • How do you convince paypal that the price was not $1, if the attacker complains? – Bobbi Bennett Nov 29 '11 at 22:41
  • @Bobbi: if the attacker complains you can always offer a refund. BTW keep in mind that the way I described (letting the user change the price, but then not sending the item) is as far as I know the most common way this is done with a paypal IPN setup. Try on a few websites if you want – Andreas Bonini Nov 29 '11 at 22:43
  • @Bobbi: There really isn't any other way to do it - except sending the item even if you weren't paid enough :D - because paypal needs to know the price, which is sent to paypal through a hidden form field. The code he pasted comes from paypal itself, it's just the standard way to do it. – Andreas Bonini Nov 29 '11 at 22:45
  • @AndreasBonini No I I don't expect the item. But aren't you taking the law into your own hands by keeping money that you've received via an act of fraud? – Ian Warburton Nov 29 '11 at 22:49
  • @Ian: what you do with the money is up to you -- I'm just resolving his specific programming problem. You can give it back, you can try to contact him, you can try to keep it; I don't know what's the best thing to do in this situation. – Andreas Bonini Nov 29 '11 at 22:55
  • 2
    Dude; that would be theft. But if the OP is selling a download he should just send the % of the bytes for which the user has paid for :) – iHaveacomputer Nov 29 '11 at 23:35
  • @iHaveacomputer: the definition of theft is "the illegal taking of another person's property without that person's permission or consent" – Andreas Bonini Nov 29 '11 at 23:48
  • 6
    Best case: You earn $0.01 and pay out a few $k in lawyers fees. – BCS Nov 30 '11 at 02:15
  • 3
    This post seems to have some merit http://en.wikipedia.org/wiki/Instant_payment_notification. There is a verification step in there, if the numbers don't add up then you would need to reject the transaction or something ... not keep the money. – row1 Nov 30 '11 at 10:35
  • 1
    Strangely, this *is* the what PayPal expects you to do. At least for the moment, PayPal doesn't let you reprogram its servers, and they do look for the amount value coming from the customer's POST action. – Edward Newell May 19 '14 at 21:36