How do I keep users from spoofing data through a form?

Go To StackoverFlow.com

0

I have a site which has been running for some time now that uses a great deal of user input to build the site. Naturally there are dozens of forms on the site. When building the site, I often used hidden form fields to pass data back to the server so that I know which record to update.

an example might be: <input type="hidden" name="id" value="132" /> <input type="text" name="total_price" value="15.02" />

When the form is submitted, these values get passed to the server and I update the records based on the data passed (i.e. the price of record 132 would get changed to 15.02).

I recently found out that you can change the attributes and values via something as simple as firebug. So...I open firebug and change the id value to "155" and the price value to "0.00" and then submit the form. Viola! I view product number 155 on the site and it now says that it's $0.00. This concerns me.

How can I know which record to update without either a query string (easily modified) or a hidden input element passing the id to the server?

And if there's no better way (I've seen literally thousands of websites that pass the data this way), then how would I make it so that if a user changes these values, the data on the server side is not executed (or something similar to solve the issue)?

I've thought about encrypting the id and then decrypting it on the other side, but that still doesn't protect me from someone changing it and just happening to get something that matches another id in the database.

I've also thought about cookies, but I've heard that those can be manipulated as well.

Any ideas? This seems like a HUGE security risk to me.

2012-04-05 23:17
by codescribblr
Sounds like you need to implement some server-side validation - sarnold 2012-04-05 23:19
Look up the price based on the ID, not a hidden field - Ry- 2012-04-05 23:19
There's a fundamental problem in your architecture: your server should NOT take prices from the client. Make the prices something that can't be changed by the client and you're set - machineghost 2012-04-05 23:20
Never trust the dark side...I mean the client side : - Songo 2012-04-05 23:22
I'm not actually allowing them to change prices...it was just an example to prove the point - codescribblr 2012-04-05 23:23
The point is valid though: everything coming from a client is unsafe and you have to expect people to meddle with it and even intentionally try to find your security gaps just for the fun of it - Armatus 2012-04-05 23:27


4

Don't try to control what data is submitted (because you can't).

Check that the user who is making the submission has the right to make whatever change it will trigger.

e.g. if they change the id to 155 and the price to 0.00 then make sure that they have permission to update record 155 and to set the price to 0.00.

2012-04-05 23:19
by Quentin
In other words, you need to store the data on the server side, then when you receive the data from the client you need to validate it against the stored data - Moses 2012-04-05 23:20
Adding on what Quentin said (and Moses), you can do a more secure alternative that cookies, with storing session data server-side. Also serializing identifiers works wonders as well - TNC 2012-04-05 23:22
so...if I did a check to make sure the user has permission to update and then encrypted the id field to make it harder to tell how to change it, that would pretty much solve my issue - codescribblr 2012-04-05 23:34


4

It's always good to check the $_SERVER['HTTP_REFERER'] on sensitive pages by doing something like:

if ($_SERVER['HTTP_REFERER'] !== "previous_page.php") {
 header("Location: error_page.php");
 session_destroy();
 exit;
}

But that isn't full proof, because if an attacker is on previous_page.php he can simply browse to the page we're trying to protect, so further protection is needed.

You could (and should) implement a token system. On your form page, you'd add this PHP code:

$_SESSION['token'] = md5(uniqid(rand(), TRUE));
$token = $_SESSION['token'];

And somewhere within the form, add:

<input type="hidden" name="token" value="<?php echo $token; ?>"/>

This will generate a nice long string that is unique to the person browsing that page. The point of doing this is to pass this session variable into the next page as a $_POST variable, then on the receiving page you compare the $_POST to the $_SESSION to make sure they equal each other. This is done like so on the receiving page:

$token = $_SESSION['token']; //re declaring your session variable

if ($_POST['token'] !== $_SESSION['token']) {
 header("Location: error_page.php");
 session_destroy();
 exit;
}

I'd suggest doing more research on "CSRF Forgery." Hope this gets you off in the right direction.

2012-04-05 23:52
by Norse
+1 for token system explainatio - shivgre 2013-09-11 06:49
Ads