0

I am working on a plugin that has the following within a <form> tag:

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

The problem with this is that users can easily inspect element, change the value, and thus affect the form processing.

The form processing happens via an ajax function and is outside of the loop (obviously).

How do you normally solve this type of scenario?

  • User sending some random values is not a problem unless your model is that user can not do that, in which case you are thinking the wrong way. you just can't have full control on the input to the server in a client server applications and this is why you have to validate all input. – Mark Kaplun Jan 25 '15 at 16:11
  • anyway it is not really a wordpress specific question, can you edit it to get it into a wordpress context? why is it so important that the value will be the one sent from the server? – Mark Kaplun Jan 25 '15 at 16:13
  • @MarkKaplun The problem is that if a user alters this specific value, then the entire form will process a completely different post and will add information to that post. There must be a way how developers have solved this. For example, how do people code Thumb up/voting type of features. The form must pass post_id value, right? – Christine Cooper Jan 25 '15 at 16:15
  • maybe you could create another hidden input field and validate it with your hidden post_id. – birgire Jan 25 '15 at 16:18
  • @birgire Can you please elaborate what you mean with this approach? Maybe in an answer to this question. – Christine Cooper Jan 25 '15 at 16:21
1

To be honest I think this question is off topic, because its topic is so a general concept that can apply to any language capable to handle web development. So is even broader than a general PHP question.

By the way, what I want to suggest is too much for a comment.

When you need to check data coming from trusted users (assuming you already have a way to check if an user is trusted) is to put in place a system for data integrity check.

A simple example. Assuming you have a form like:

<?php $data = get_my_form_data(); ?>
<form method="post">
    <input type="hidden" name="postid" value="<?= $data['postid'] ?>">
    <input type="text" name="vote" value="<?= $data['vote'] ?>">
    <input type="text" name="username" value="<?= $data['username'] ?>">
<form>

The function that retrieves data is just as a placeholder to make clear data comes from server and then is used to fill form values.

Now let's see how data integrity can be put in place. It is usually done with an a two-way (reversible) encryption.

<?php
function obfuscate_postid($id) {
  return wp_create_nonce('pre-md5').md5($id.AUTH_SALT).wp_create_nonce('post-md5');
}

$data = get_my_form_data();    
$check = obfuscate_postid($data['postid']);
?>
<form method="post">
    <input type="hidden" name="postid" value="<?= $data['postid'] ?>">
    <input type="text" name="vote" value="<?= $data['vote'] ?>">
    <input type="text" name="username" value="<?= $data['username'] ?>">
    <input type="hidden" name="__ch" value="<?= $check ?>">
<form>

This way in the server-side processing you can check that

$valid = obfuscate_postid($_POST['postid']) === $_POST['__ch'];

If an user change the post id in the form without changing the check string, $valid above is false and you can stop processing the data.

I've used a pretty simple 2 way obfuscation, and thanks to fact that nonces are not fixed in time, this is a pretty strong way to secure your data.

I also used nonces to make the answer a bit more WordPress related ;)

It would be a very strong system if nonces would be usable only once, but it is a post voting system, not an online-banking application. And if you want you can also change nonces TTL.

Finally, note how I used a salt to make md5 more secure, because even if md5 is not reversible, result of md5 for sole integers can be easily found (e.g. try this using the string b706835de79a2b4e80506f582af3676a).

  • since the user has no idea what is the importance of post_id it will not try to understand it, but will simply copy the value from the form at another post, and he will copy the check as well and therefor the check do not solve the initial problem. You can try do be smarter and insert the check with javascript and therefor be less obvious for anyone that just looks at the html, but my experiance from people that cheat in online games is that there are enough people that know how to operate the developer tools of the browser and analyz the trafic itself. – Mark Kaplun Jan 25 '15 at 19:43
  • Problem in OP is to be sure a vote should go to a certain post is actually assigned to that post. Let's assume there's a post A and a post B. A logged user is allowed to vote on A but not on B. So she goes on page for post B and see "Sorry, you can't vote this post". She things: "I go to post A, change post id in the form to B using dev tools so I'll vote for B". Using my code you prevent that. Even if she goes in another page and edits both id and hash for post A, then the vote will be assigned to post A and that's fine because she was allowed to vote that post. @MarkKaplun – gmazzap Jan 25 '15 at 20:32
  • Point is you can't be sure from which page the vote comes from, but you can be sure that the user is allowed to vote the post if post id and hash match. @MarkKaplun – gmazzap Jan 25 '15 at 20:33
  • this is a typical competition situation in which a author gets a prize if he gets the most votes, therefor you want to have some kind of prof that you actually read the post that you are voting for to avoid automatic votes. Your best defense is to make the users register and then you don't have to carry the username field, but this will reduce the number of people that will be willing to vote therefor you don't want to go that way. This problem is very similiar to fighting spam and you can't fight spam when you provide all the authentication info in the HTML. – Mark Kaplun Jan 25 '15 at 21:25
  • @MarkKaplun you can't be sure an user read a post. Unless you can monitor user brain activity. You can only be sure an user visited the page in which the post is. And if the hash is generated server side only in the page where the post is, than it means that if an user has a valid pair id/hash the user visisted the page. And if so she's allowed to vote. No matter from where she sends valid data, but only that data is valid. It doesn't prevent spam, because a spam bot can visit the page too. If you read my answer I said that you need to be sure the user is trusted before use my code – gmazzap Jan 25 '15 at 22:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.