Reputation: 3540
I seek a way to verify that a sender of a set of post variables is one I approve of.
I have a simple HTML form hosted on server A. The action of this form points to server B where I do stuff with the data. What I want is a way to be sure that the data is in fact sent from server A and not some random server C. Is there a convenient way to do this?
I have looked at some different approaches, none which I feel is good:
HTTP_REFERER
in $_SERVER
. This cannot really be trusted according to
php.net.
Preserving session variables (Having session ids transfer over from A to B and append them to the query string). This does not feel right.
adding a <input type="hidden" name="secretkey" />
to the form and checking for that key in the recieving end. This will only require a view at the html source to get the "secretkey".
Upvotes: 4
Views: 2752
Reputation: 6275
Short answer: Your form, lets call it X, needs to post back to A. A can then sign the request and then forward all of this onto B.
If you do NOT post back to A, then how does B know that the request came from A? A has no clue what the client, who we will call Zed, sends? A only sent form X to Zed and is no longer involved in the conversation otherwise.
Zed, can post anything in X they want to back to A. Zed may be malicious, or Zed may be the victim of a CSRF. However, your question is only that B knows that the request is coming from A. A can validate the input and take appropriate action. If A chooses to accept input form X and sign the request and send to B, B will then know that the request came from A.
This idea is similar to what OAuth 1.0a does.
Take all form variables in X and create a URL encoded string with the keys sorted by alpha-numeric sorting.
$str = "keyA=<val1>&keyB=<val2>&keyB123=<val3>";
Then hash and sign this. HMAC-SHA1 is once such algorithm to do this. For the key, you need to generate some random string of characters and numbers. Both A and B should know this value and you should keep it VERY PRIVATE. You can then generate the signature to add to your request to B.
$signature = hash_hmac("sha1", $str, $key);
B can verify the signature for form X by performing the same steps that you did to create the original $str
.
Upvotes: 5