Forum Moderators: coopster

Message Too Old, No Replies

PHP $ SERVER["HTTP REFERER"]

         

smagdy

2:41 pm on Jan 13, 2009 (gmt 0)

10+ Year Member



Hello,

I have PAGE A with a Form that gets submitted to PAGE B

I want to make sure 100% that PAGE B never gets the Form variables except from PAGE A

So, I use $_SERVER["HTTP_REFERER"] to do that check, but I am reading that it is not safe as it could contain NULL or something, so what other method(s) I can use to make that check?

Thanks in advance

smagdy

2:55 pm on Jan 13, 2009 (gmt 0)

10+ Year Member



The problem is that some users save the form and play in its variables then submit it, so any solution is appreciated!

vincevincevince

3:10 pm on Jan 13, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Use sessions...

Instead of (page A):

print '<input name="credits" value="10" type="hidden">';

Use this:

session_start();
$_SESSION['credits']=10;

Then when you process (Page B), instead of:

mysql_query("UPDATE `table` SET `credits` = ".intval($_POST['credits']).")

Use this:

session_start();
mysql_query("UPDATE `table` SET `credits` = ".intval($_SESSION['credits']).")

Basically (and this is the important point) - do not trust the user in any circumstances. There are browser plugins which allow users to edit any field of any form (including hidden) should they wish - live in situ - and then submit.

Instead, use sessions to store the data which should be 'unchangeable' and then read it from the session when the rest of the form (user editable parts) is submitted.

smagdy

3:30 pm on Jan 13, 2009 (gmt 0)

10+ Year Member



Thanks, but this won't solve it!

They can refresh the online page to activate the sessions then submit the offline/saved/edited page or ?

Also, you have used "a hidden field" in your example which can be filled with SESSION variable, but am talking about other fields specially "radio buttons"!

vincevincevince

12:14 am on Jan 14, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



smagdy - I am guessing they need to pick one of a number of radio options? And you are just eating the 'value' field and using it? That's a mistake... never ever trust the user's data.

Do it like this:

$allowed=Array("UK","France","Spain");
if (!in_array($_POST['field'],$allowed)) die("Sorry, you have meddled with the form - pick one of the options we provide");

To summarise: you cannot reliably or even semi-reliably stop users editing the form. You must check that the form they have POSTed is a valid set of data based upon the form they claim to have filled in. If the data is fixed (e.g. hidden field type) then store it in a session instead, and retrieve it from the session. If the data is a radio/dropdown type, then compare it against an array of valid answers using in_array().

smagdy

1:11 am on Jan 14, 2009 (gmt 0)

10+ Year Member



I also have this check in place..

Well, yes they are number of radio buttons and they pick one and there are several groups of these radio buttons, in short its like questionnaire.. and I save the start time of opening the page and the end time when they submit the form to calculate the number of seconds it took to answer the questions correctly..

So a user was able to do something that i don't know exactly what is it, but he was able to answer the questions under 2 seconds which is never possible cuz they are at least 7 questions..

So, i think he had the page saved offline with the correct answers in place then he opened the questions online and directly submitted the offline version.

So, I need to stop submitting the form from any other page except the original page and since we can't trust PHP $ SERVER["HTTP REFERER"] so what would be the solution?

Thanks for taking the time to help!

smagdy

10:47 pm on Jan 14, 2009 (gmt 0)

10+ Year Member



Any help please?

penders

10:50 pm on Jan 14, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



So, I need to stop submitting the form from any other page except the original page and since we can't trust PHP $ SERVER["HTTP REFERER"] so what would be the solution?

I think this is what vincevincevince is saying... use sessions. (?) Page A sets a session variable and Page B checks for its existence to make sure you have come from Page A. I would have thought you could also keep track of the elapsed time in the session - even if the user refreshes the page (or only store the start time if it is not already set)? Although if it is possible for the user to get back to Page A later (or from another browser etc.) then I would have thought you would need to present the user with a random set of questions each time - as they could always write the Qs down?

smagdy

11:21 pm on Jan 14, 2009 (gmt 0)

10+ Year Member



The start time is saved in DB, so they can never change it, also the questions and the answers and displayed randomly everytime they refresh the page.

But the thing is that they can open Page A so the sessions be active, then do something else which I don't know what is it.

It is getting me crazy because there is a user still doing it.

I check the form coming from correct IP address and I check the POST var, and also the HTTP REFERER, and I redirect if HTTP REFFERER is not SET.

So i dont get how he still can hack it.

Receptional Andy

11:30 pm on Jan 14, 2009 (gmt 0)



You can't trust HTTP_REFERER since it is supplied by the user. Even a non-technical firefox user could install an extension like refspoof (or if more advanced, tamper data) and always send the correct value to your script.

That said, AFAIK, the measures outlined in the thread should be sufficient to prevent the problem you're having. Is there any chance some of the code might not be running as intended?

smagdy

11:37 pm on Jan 14, 2009 (gmt 0)

10+ Year Member



so it is possible to save the page offline and mark the correct answers then RUN PAGE A to activate the sessions and submit the saved page after correcting the HTTP_REFERER using refspoof!

So, what I made is not sufficient to prevent the problem..

Hmm, I dono what else could be done!

vincevincevince

4:46 am on Jan 15, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Randomise the field names and store them in the session (as well?)


$rand=substr(md5(rand()),0,5);
$_SESSION['fieldname']=$rand;
print "<input name=\"$rand\">";
Gives (e.g.): <input name="c3b24">

When the form is submitted then just 'translate' the answers:


print $_POST[$_SESSION['fieldname']];

That way, the user who has got a saved form won't be able to submit it - all the field names won't match up. The only form he can submit is the one he just downloaded.

If he has time to read the new field names, replace them in his offline version, then submit.. well :p you can't beat them all!

The biggest problem with quiz type things is that two people (friends?) collaborate. One takes his time to get it right - then his friend is able to very quickly fill in the answers given by the first submission.

For that reason I suggest you consider absolute time basis - start the clock when questions are released - and time them until answers are in. Winner is the absolute first set of correct results received - not the one who did it in the shortest time from opening the page.

smagdy

11:04 am on Jan 15, 2009 (gmt 0)

10+ Year Member



Well, storing the inputs in SESSIONS is a brilliant idea, it could solves a lot, I will try that today... thank :)

Other thing, i didn't understand this part:
"Winner is the absolute first set of correct results received - not the one who did it in the shortest time from opening the page."

I mean the idea is that the winner who answers correct in the shortest time, but what you suggest could allow just the first person who participate would answer correct and wins, so no other would bother to participate.. or i miss something?

Thanks again!

vincevincevince

2:09 am on Jan 16, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



smagdy - good point about others losing interest. I guess it depends on the aims / purpose of the quiz.