Why rand() every time I refresh the page? - php

I want to run mini program for confirmation security question :
$questions = array('dog legs','car legs','the best country in the world');
$answers = array(4,4,'USA');
$questionId = rand(0, (count($questions)-1));
and then
$ans = $_POST['answer'];
if($ans == $answers[$questionId]){echo 'Confirmed !';}
So the prob is that not every time that I answer the answer is correct, because after sending form the rand function runs and changes the question ! Any solutions ?

You can pass in the form an hidden input with as value the question ID, that way the id will be resent.
<input type="hidden" name="questionId" value="<?php echo $questionId; ?>"></input>
Then check if the form is submitted.
<?php
if ($_POST['questionID'])
$questionID = $_POST['questionID'];
else
$questionID = rand(0, (count($questions)-1));
You can also secure all this by using base64 encoding

Best way:
Basicly you need to save the question id into the users session.
Workaround:
If thats to complicated, do the following.
Create a secret string.
Create md5 from secret string + correct answer.
Write the md5 into a form hidden field.
On form submission, check if the secret string + given answer returns the md5 from the form.
Unless someone knows your secret string, you are safe even without sessions.
Attention
My workaround has the same problem than storing the question ID into the form like sugegsten in another answer: One could simply manipulate the question ID to always show a once-solved question. Session is the only more or less safe way
Best regards
Zsolt

You'll need to know what the original question was as well. Easiest way to do that would be just to post the question in the form as a hidden input :
<form>
<?php echo $questionID; ?>
<input type="text" name="answer" />
<input type="hidden" name="question" value="<?php echo $questionID; ?>" />
</form>
and do
$questions = array('dog legs','car legs','the best country in the world');
$answers = array(4,4,'USA');
$questionID = rand(0, (count($questions)-1));
if (isset($_POST['answer'])) {
$answer = $_POST['answer'];
$question = $_POST['question'];
if ( $questions[ $question ] == $answer ) // you're golden
}

Related

Simple Captcha in PHP with rand()

I'm trying to make a simple captcha in PHP, but it does not work. The query is not currently executing. This is my current code:
<?php
$Random = rand(1, 100);
$Random2 = rand(1,100);
echo "Result: ".$Random." + ".$Random2." ?";
?>
<input type="text" name="r_input"/><br />
$Cap = mysql_real_escape_string($_POST['r_input']);
$Result = $Random+$Random2;
if(isset($_POST['myButton']) and trim($Var) and trim($Var2) and trim($Var3) and $Cap==$Result){
//My Query
}
When you use rand() to generate 2 values, and show those 2 values, and give the form for the user to enter the answer, ...
... the user enters the answer and submits back to the server ...
... the server gets the answer, and then GENERATES 2 NEW VALUES, that don't correspond to the answer given by the user.
Try using session variables to store the generated values in, and match against when the user submits the form!
<?php
session_start();
$captcha_id = 'captcha_' . rand();
$_SESSION['$captcha_id']['val1'] = rand(1,1000);
$_SESSION['$captcha_id']['val2'] = rand(1,1000);
echo "
<form action='' method='post'>
<p>Result: {$_SESSION['$captcha_id']['val1']} + {$_SESSION['$captcha_id']['val2']} = </p>
<input type='hidden' name='captcha_id' value='{$captcha_id}' />
<input type='text' name='captcha_answer' />
<p>?</p>
</form>
";
if (
isset($_POST['captcha_id'])
&& isset($_SESSION[$_POST['captcha_id']])
&& isset($_POST['captcha_answer'])
&& $_SESSION[$_POST['captcha_id']]['val1'] + $_SESSION[$_POST['captcha_id']]['val2'] == intval($_POST['captcha_answer'])
) {
unset($_SESSION[$_POST['captcha_id']]); // don't let this answer be reused anymore.
// do allowed stuff
}
?>
Because $Random and $Random2 have a different value each time.
When you show the form for the first time, they may have the values $Random = 12 and $Random2 = 26. The User sees those, adds them up correctly and types in 38 (which is the correct answer for those two values). The answer is sent to the script again, the values of $Random and $Random2 are generated again (this time as $Random = 23 and $Random2 = 30 which equals 53) and the answer the user has sent is not correct any more.
So you would need to store those values in hidden fields and add these up, instead of the generated ones, like so:
<input type="hidden" name="rand_1" value="<?php echo $Random; ?>">
<input type="hidden" name="rand_2" value="<?php echo $Random2; ?>">
<?php
if ($_POST['rand_1'] + $_POST['rand_2'] == $_POST['r_input']) {
// Query etc.
EDIT: As suggested by #nl-x you should use the Session variables instead of hidden fields to prevent abuse of the captcha:
<?php
$Random = $_SESSION['rand_1'] = rand(1, 100);
$Random2 = $_SESSION['rand_2'] = rand(1,100);
echo "Result: ".$Random." + ".$Random2." ?";
?>
And check those values against the given result afterwards:
<?php
$Cap = mysql_real_escape_string($_POST['r_input']);
$Result = $_SESSION['rand_1'] + $_SESSION['rand_2'];
if ($Result == $Cap) {
// ...
You never re-enter PHP mode after you output your form field:
<input type="text" name="r_input"/><br />
<?php // <----this is missing
$Cap = mysql_real_escape_string($_POST['r_input']);
Pardon me, but you are not making a real captcha. The purpose of the captcha is to distinguish the human from the bots. I would highly suggest you to pick a image database, and randomize a function to call a image. Internally, i would check if the text/description of the image matches with what the user typed.
The only thing you will rand() is what image to load from your image database.
That's a not-healthy way to do it, and there are plenty of better ways to do this. But it's more closer to a captcha than just your current code.
There is also a lot of libraries and engines that can do the job for you.
I'm not a pro at PHP, or even programming at all, but i think you're going to the wrong side - your code won't block any... malicious actions at all, or whatever kind of action that you will try to prevent with the captcha.
Search google for the libraries. PhpCaptcha is one of them. And here is a very simple quickstart guide for phpcaptcha.
Here's a code example, extracted from PHPCaptch that I linked above.
At the desired position in your form, add the following code to display the CAPTCHA image:
<img id="captcha" src="/securimage/securimage_show.php" alt="CAPTCHA Image" />
Next, add the following HTML code to create a text input box:
<input type="text" name="captcha_code" size="10" maxlength="6" />
[ Different Image ]
On the very first line of the form processor, add the following code:
<?php session_start(); ?>
The following php code should be integrated into the script that processes your form and should be placed where error checking is done. It is recommended to place it after any error checking and only attempt to validate the captha code if no other form errors occured. It should also be within tags.
include_once $_SERVER['DOCUMENT_ROOT'] . '/securimage/securimage.php';
$securimage = new Securimage();
This includes the file that contains the Securimage source code and creates a new Securimage object that is responsible for creating, managing and validating captcha codes.
Next we will check to see if the code typed by the user was entered correctly.
if ($securimage->check($_POST['captcha_code']) == false) {
// the code was incorrect
// you should handle the error so that the form processor doesn't continue
// or you can use the following code if there is no validation or you do not know how
echo "The security code entered was incorrect.<br /><br />";
echo "Please go <a href='javascript:history.go(-1)'>back</a> and try again.";
exit;
}
Following the directions above should get Securimage working with minimal effort.
This code is included here as well.
Good luck!

Updating hidden input depending on what user has checked

I've created a test system that has multiple steps (using jquery) allowing users to check checkboxes to select their answers, with a summary page and a final submission button... all within a form. I now want to create the scoring system.
1) Firstly this is the code (within a loop) that grabs the answers from Wordpress for each question:
<input type="checkbox" name="answer<?php echo $counter; ?>[]" value="<?php echo $row['answer']; ?>" />
2) In Wordpress next to each answer is a dropdown with a yes or no option to mark whether the answer is right or wrong. This is output in the following way:
<?php $row['correct']; ?>
3) Each correct answer the user checks should be worth 1 point. The passmark is determined by the field:
<?php the_field('pass_mark'); ?>
4) I want it to update a hidden field with the score as the user checks the correct answer:
<input type="hidden" value="<?php echo $score; ?>" name="test-score" />
How can I update the hidden field with the user score as the user is checking the correct answer? I'm not sure what to try with this to even give it a go first!
Ok, everyones spotted a big hole in this. I'm completely open to doing it a hidden way so people can't check out the source. The type of user this is targeted at wouldn't have a clue how to look at the source but might as well do it the right way to start with!
The whole test is within a form so could it only update the hidden field on submit?
I still need some examples of how to do it.
In my opinion you should use sessions for that purpose, because any browser output may be saved and viewed in ANY text editor. This is not right purpose oh hidden input elements. You use hidden inputs when you need to submit something automatically, but never use it when processing some important data.
Mapping your questions and answers via id will allow you not to reveal real answers and scores in HTML.
Just a very simple example how to do that:
<?php
$questions = array(
125 => array("text"=>"2x2?", "answer"=>"4", 'points'=>3),
145 => array("text"=>"5x6?", "answer"=>"30", 'points'=>2),
);
?>
<form method="post">
<?php foreach ($questions as $id => $question): ?>
<div><?php echo $question['text'] ; ?></div>
<input type="text" name="question<?php echo $id ; ?>"/>
<?php endforeach ; ?>
<input type="submit" value="Submit"/>
</form>
/* In submission script */
<?php
if (isset($_POST['submit'])){
foreach($questions as $id => $question){
if (isset($_POST["question{$id}"])){
$answer = $_POST["question{$id}"] ;
if ($answer === $question['answer']){
$_SESSION['score'] += $question['points'] ;
}
}
}
}
Spokey is right - the user would be able to cheat if your score it on the client side like using the method you suggested.
Instead, either user a JQuery $.post call to post each answer and then store the score in a PHP Session. Or just wait until the entire form is submitted and evaluate the score of the form as a whole on the server side.
* Update *
You have to submit the form to a script that can evaluate the form. So say it gets submitted to myForm.php
In myForm.php, get the post vars:
$correct_answers = $however_you_get_your_correct_answers();
//Assuming $correct_answers is a associative array with the same keys being used in post -
$results = array();
if($_POST){
foreach ($_POST as $key=>$value) {
if ($_POST[$key] == $correct_answers[$key]){
$results[$key] = 'correct';
}
else $results[$key] = 'incorrect';
}
}
This is untested, but it should work.

PHP Trivia Game using sessions

I am creating a trivia game, how it works:
A person goes to the index page.
The system generates him a random question out of the array.
The user answers the questions
If question is right, system will echo 'Correct answer' and will generate a new question.
If question is not equal to answer in the array, system will echo 'Wrong answer' and will generate a new question.
I have done the part of question generations, but I am having problems with the matching answers - Considering if you answer a question, after you click submit, the question automatically changes so your answer will be incorrect unless the randomQuestion stays the same.
My friend told me I need to use sessions for the random questions part, but nothing else.
I am not really sure how would I do this, I am really lost.
This is my code:
Question generation
<?php
session_start();
$questions = array(array('What is Google?', 'god'),
array('What is God?', 'gode'),
array('Why is god?', 'godee'));
$randomQuestion = array_rand($questions);
$question1 = $questions[0][0];
$question2 = $questions[1][0];
$question3 = $questions[2][0];
if ($randomQuestion == 0 && !isset($_SESSION['question1'])) {
echo $question1;
} else if ($randomQuestion == 1 && !isset($_SESSION['question2'])) {
echo $question2;
} else if ($randomQuestion == 2 && !isset($_SESSION['question3'])) {
echo $question3;
}
?>
Form + matching answers
This script is currently only checking for question 1 as a test.
<form action="index.php" method="post">
<input type="text" name="answer">
<input type="submit" value="Answer it!">
</form>
<?php
$answer = $_POST['answer'];
if (!empty($answer)) {
if ($randomQuestion == 0) {
if ($answer == $questions[0][1]) {
echo 'Correct Answer!';
unset($_SESSION['question1']);
unset($_SESSION['question2']);
unset($_SESSION['question3']);
}
} else {
echo 'Answer is incorrect.';
return;
}
} else {
echo 'Field is empty';
return;
}
session_destroy();
?>
What I have thought of:
After reading much articles about sessions, I thought about checking if randomQuestion is isset, if it's isset, then it won't generate new questions.
After you answer the question, it will unset the random question so the system can generate a new question.
But it didn't really work as I didn't do it right.
What did I do wrong?
And what is the easiest way to do this?
Thanks!
I wouldn't start by using sessions. Of course I may end up using them but for a proof of concept it's best to do it the simple way first.
All you really need to do is insert a hidden value into your form that will tell you the question number.
For example (not tested):
<?php
$questions = array(
array('What is Google?', 'god'),
array('What is God?', 'gode'),
array('Why is god?', 'godee')
);
$rnd=mt_rand(0,count($questions)-1);
$question=$questions[$rnd];
echo($question[0]);
?>
<form action="index.php" method="post">
<input type="hidden" name="q" value="<?=$rnd?>">
<input type="text" name="answer">
<input type="submit" value="Answer it!">
</form>
The rest of the server code to verify the question and answer I'll leave as an exercise.
If you want this trivia game to be played by more that one person (and I suppose you do) , you need to come up with something more that a simple < form > ... You must store the answers one user gives so that the other user can see them.

comparing $_get result to db stored value

i have a multiple choice quiz which sends a possible answer via URL like this
<form method="post" action="test2score.php?q=<?php echo $quiz_id; ?>">
on the test2score.php page it reads and tries to compare the value like this
$ans = mysql_result(mysql_query('select c_answer from quiz where quiz_id = "'.$_GET['q'].'"'),0);
if ($_POST['answer'] == $ans){
echo "You got it right!";
}else if ($_POST['answer'] <> $ans){
echo "You got it wrong!";
}
where c_answer is the correct answer stored in db, but even when i select the right answer and post it it still echoes "you got it wrong"
any help would be appreciated.
Your form method="post" is post and your receiving values in $_GET['q'] Kindly correct either of the one
Or use
$_REQUEST['q']`
Use a hidden field q and post that value to your action page and receive that value using
$_POST['q'] and use that in your query.
Thanks.
Why are you using a $_GET request in the action of a form that is $_POST? Since you aren't worried about your users seeing the value of q then why not just put a hidden input in the form with the results of q:
<input type="hidden" value=<?php echo $quiz_id ?> name="q" />
Then in your query, check for $_POST['q']
Seems the saner, more logical way to achieve this
instead of passing quiz id from form action pass it from hidden form field
like below
set form action to
action="test2score.php"
and take hidden form field as
<input type="hidden" name="q" value=<?php echo $quiz_id; ?> />
and get that value like below
$_POST['q'];

How to pass data from form without a form field? (PHP)

I have a form for editing a users name and email.
So when it updates the name and email, it needs the username to identify which row it should update.
So i wanted to know if there is any element which is passed with the form but without showing the value or being editable in the input tag.
So i get the username from one script.
The edit user script gets the name and email from the database with the specified username.
Then it passes that new name and email with the username to another script which updates it.
I believe you are looking for
<input type='hidden' name='username' value='theusername' />
hidden - can only be seen in the source of your HTML document
name - where it will be in the $_REQUEST/$_POST/$_GET ($_POST or $_GET depending on how you are submitting your form) variable on submit
value - the username you want this form to relate to
PRO TIP: Have a way to tell who is trying to update users so you don't have unauthorized people updating your user information. It would be very easy for someone to change the username in the form and try to update someone else.
You can use input type hidden
<input type="hidden" name = "username" value="<?php echo $username ?>">
use an:
<input type="hidden" />
HIDDEN is a TYPE attribute value to the INPUT element for FORMs. It indicates a form field that does not appear visibly in the document and that the user does not interact with. It can be used to transmit state information about the client or server. Hidden fields often store a default value (e.g.via php), or have their value changed by a JavaScript.
more here
Use a hidden input tag:
<input type='hidden' name='username' value='theusername' />
As all the others stated you need a hidden input. It WILL be editable though, never trust it as you never trust any other data coming from outside.
But I'd like to add that it would be nicer not to use the username for identifying a row, add an ID column as a primary key instead to your database (possibly auto incremented), and use that in your form.
Something like
<input type="hidden" name="userid" value="<?=$userid?>" />
Arun, you can use GET to pass variables from one page to another page. Simply construct URLs as edituser.php?username=arun and so on. This is the only possible way to pass on variables or data, of course apart from cookies, to other pages w/out using form tags.
Second method is to use JavaScript to create a hidden form field and update it with username.
Third one is to simply add hidden input tags. But this and latter will require form tags.
A word of caution, filter user inputs, be JS, GET or hidden fields.
You can use a hidden form field:
<input type="hidden" name="originalUsername" value="something" />
This won't render on the form in the browser and will likely be ignored and unnoticed by the user.
However, be aware that this is editable. Do not rely on this as a security measure. When the form is submitted, make sure that the user submitting the form (using whatever authentication and authorization mechanisms you have in place) is authorized to make this change before persisting it to the database. Any form field being submitted can be edited.
Use this if you want to use it safely:
<input type='hidden' name='username' value='<?php echo encode("Please Encode Me!","This is a key"); ?>' />
wich will result into:
<input type='hidden' name='username' value='p3e4e4241674d2r4m4i5o464a4f2p3k5c2' />
and in the modification script you will have to use:
<?php $username = decode("p3e4e4241674d2r4m4i5o464a4f2p3k5c2","This is a key"); ?>
Below you have the PHP functions for the ENCODE/DECODE:
<?php
function encode($string,$key) {
$key = sha1($key);
$strLen = strlen($string);
$keyLen = strlen($key);
for ($i = 0; $i < $strLen; $i++) {
$ordStr = ord(substr($string,$i,1));
if ($j == $keyLen) { $j = 0; }
$ordKey = ord(substr($key,$j,1));
$j++;
$hash .= strrev(base_convert(dechex($ordStr + $ordKey),16,36));
}
return $hash;
}
function decode($string,$key) {
$key = sha1($key);
$strLen = strlen($string);
$keyLen = strlen($key);
for ($i = 0; $i < $strLen; $i+=2) {
$ordStr = hexdec(base_convert(strrev(substr($string,$i,2)),36,16));
if ($j == $keyLen) { $j = 0; }
$ordKey = ord(substr($key,$j,1));
$j++;
$hash .= chr($ordStr - $ordKey);
}
return $hash;
}
?>

Categories