Jump to content
Larry Ullman's Book Forums

Chapter: 8 | Section: Prepared Statements


Recommended Posts

Guest Deleted

On page 266 under "To use prepared statements" I notice that Larry had his script look to see if $_SERVER['REQUEST_METHOD'] == 'POST' in order to tell form had been submitted. I don't ever do this in my scripts and I wonder if it's ok.

 

To let PHP know that a form is ready to be processed,  I use a hidden input in my forms and I have my PHP check for that hidden value.

 

I'm not always consistent in how I implement this, but here is one way:

 

<form action="" method="post">

<input type="hidden" name="process" value="true">

<strong>Your Name:</strong> <input type="text" name="name">

<br /><strong>Your Favorite Color:</strong> <input type="text" name="fav_color">

<br /><input type="submit">

</form>

 

The code would typecast $_POST['process'] into a boolean and then check if it's true. I realize that it will be evaluated to true regardless of what the value is, so long as there is a value, but I don't care since the only time it has a value is when the form is submitted.

 

I also think Larry only did this for the sake of example, but when he checks $_SERVER['REQUEST_METHOD'] he also makes sure that none of the required fields are empty. I do this as part of my form validation. That's ok, right?

 

So, in summary, is it ok to use my little process variable and is it ok to check for empty fields as part of my validation, not as part of determining form submission?

Link to comment
Share on other sites

There are any number of ways to check for form submission, and generally isset($_POST['submit_btn_name']) is fine.

Also, I agree that checking that all fields (minus radio and checkbox inputs) are properly submitted is a good idea, as it helps prevent hacking and the like.

Link to comment
Share on other sites

Guest Deleted

As for checking for empty fields, my validation will catch them and show the user an error. It won't take any further action until all of the validation's criteria is satisfied.

Link to comment
Share on other sites

Guest Deleted

Yeah, I try to think of everything. Like if I expect an integer I'll check to see that:

 

-it's there

-it came from $_POST
-it's an integer
-it's in the appropriate range

-it's of the appropriate length

 

I try to make a hackers job very hard xD

Link to comment
Share on other sites

Yeah, that seems like a good checklist. Here's what I generally do every time:

 

- Check that the submit button was posted and of the expected value. If it's not, display a blank form.

- Check that all the fields that should have been submitted were. Note that unselected radio buttons and checkboxes will not pass the isset test. If this test fails, I report a vague "system error" message, and display a blank form.

- In the case of integers, I type cast them as integers. This will make all non-number strings and whatnot change to 0. In other words, regardless of what they submitted, type casting will give you an integer every time. You then check the resulting integer on a range and report an error as necessary.

- I always set values for radio buttons, checkboxes and select inputs as numbers as well, so those can be validated as integers.

- Strings are the trickiest, but in general, if you run them through htmlentities and used prepared statements properly, there's nothing they can do. I also use filter_var for things like email addresses, and run passwords through an appropriate regex.

Link to comment
Share on other sites

Guest Deleted

Oooh you gave me lots of fodder to reply to. Yay!  ;) I'll start at the top and work my way down.

 

- - - - -

 

"Check that the submit button was posted and of the expected value. If it's not, display a blank form."

 

Hmm, never heard of this before, but I'm interested in hearing why you do it. I'd also like to hear what you mean by "submit button was posted."

 

 

"Check that all the fields that should have been submitted were. Note that unselected radio buttons and checkboxes will not pass the isset test. If this test fails, I report a vague "system error" message, and display a blank form."

 

I use empty() and as far as I can tell, I never have a problem. Try out this code:

<?php

/*  Note that in a real script, I would be checking for more than just empty fields.

Also note that this is a procedural example and I never do procedural coding anymore. It just seemed easier for the sake of example.
*/

$submit = TRUE;
$error_messages = array();

if (isset($_POST['process']))
{
	if (empty($_POST['name']))
	{
		$error_messages[] = 'You must enter your name.';			
		$submit = FALSE;
	}	
	
	if (empty($_POST['fav_color']))
	{
		$error_messages[] = 'You must enter at least one favorite color.';			
		$submit = FALSE;
	}
	
	if (empty($_POST['gender']))
	{
		$error_messages[] = 'You must specify your gender.';			
		$submit = FALSE;
	}			

	if (!$submit)
	{
		echo '<span style="color:red">';
		
		foreach ($error_messages as $message)
		{
			echo '<p>'.$message.'</p>';	
		}
		
		echo '</span>';
	}
	else
	{
		//were this real, this part would put the information in the database via a prepared statement
	}

}

?>


<form action="" method="post">
<strong>Your Name:</strong> 
<input type="hidden" name="process" value="true">
<br /><input type="text" name="name">
<br />
<br /><strong>Your Favorite Colors:</strong> 
<br /><input type="checkbox" name="fav_color[]" value="red"> Red 
<br /><input type="checkbox" name="fav_color[]" value="blue"> Blue 
<br /><input type="checkbox" name="fav_color[]" value="green"> Green 
<br /><input type="checkbox" name="fav_color[]" value="yellow"> Yellow
<br /><input type="checkbox" name="fav_color[]" value="pink"> Pink
<br /><input type="checkbox" name="fav_color[]" value="brown"> Brown
<br />
<br /><strong>Your Gender</strong>
<br /><input type="radio" name="gender" value="male"> Male
<br /><input type="radio" name="gender" value="female"> Female
<br />
<br /><input type="submit" value="Send Form">
</form>

*scratches head* As far as I know, what I did up there was acceptable. It always works, so, unless I have a security flaw then I guess it's ok.

 

 

" In the case of integers, I type cast them as integers. This will make all non-number strings and whatnot change to 0. In other words, regardless of what they submitted, type casting will give you an integer every time. You then check the resulting integer on a range and report an error as necessary."

 

I first heard about this recently, and it does indeed sound like a good idea. I'm gonna start doing it.

 

 

" I always set values for radio buttons, checkboxes and select inputs as numbers as well, so those can be validated as integers."

 

What do you mean by "set values"? You mean put value="somethinghere" in the tags? Did I do this in my code above? Or would I have had to put an integer? I'm confused, =)

 

 

"Strings are the trickiest, but in general, if you run them through htmlentities and used prepared statements properly, there's nothing they can do. I also use filter_var for things like email addresses, and run passwords through an appropriate regex."

 

I'd say one reason they're tricky is because there is so many different kinds of strings and you have to learn how to deal with each kind. You have passwords, emails, usernames, entire posts, etc. as well as strings that will have very little variation. For instance, when I validate a gender field for a form, my script checks to see if the value is "male" or "female". Nothing else (to my knowledge) gets through. 

 

If memory serves, I run htmlentities() on most strings. Off the top of my head, I don't I do it on strings like $_POST['gender'] because I define explicitly what values strings like that can have. I don't think I do it on passwords either. Passwords get hashed. I think with passwords all I check is they meet the minimum requirements (basically that's right length and at least one of each required character).

 

I recently discovered filter_var(). I like it. I'm unsure though as to how flexible that function is. I use it for a few things like URLs and emails but for most stuff, I find myself turning to other things. Like I use preg_match() a lot. 

 

 

Now you have lots of reply fodder xD Yay?

Link to comment
Share on other sites

My general strategy is to do everything I can to ensure that the form is submitted the way it's intended to be submitted. What this means is that if a users fills out the form and clicks the submit button like they're supposed to, then there should be no issues. However, if they try to use cURL, etc. to submit/hack the form, then I'm gonna deny them access to anything. I don't go so far as to check cross-domain requests and the user-agent string, but it really comes down to if they submit the form properly with valid data, then it's all good.

 

To that end, by checking that the submit button input was submitted and the value is what I expect, then they are less likely to be trying to hack my site. For example, if I have a submit input with the name submit_btn and a value of Submit, then I'll put the following in my PHP:

if (isset($_POST['submit_btn']) && $_POST['submit_btn'] === 'Submit')

I wouldn't use empty for a variety of reasons. Instead of explaining though, I think the following link will make those reasons more than obvious:

http://techtalk.virendrachandak.com/php-isset-vs-empty-vs-is_null/

 

For radio buttons, checkboxes and select inputs, I always set number values, which means that I don't do the following:

<input type="radio" name="gender" value="male"> Male
<input type="radio" name="gender" value="female"> Female

But instead do the following:

<input type="radio" name="gender" value="1"> Male
<input type="radio" name="gender" value="2"> Female

And then I have an array in a PHP file that looks like the following:

$gender = array(1 => 'male', 'female');

That way, I can always validate all those inputs as integers, which as I stated before, is infinity easier to validate and is more foolproof than strings.

 

As for strings, well, yes, there's a lot of variety, so I can't get into all the details here, but basically htmlentities and trim is run on every string. Also, I check that required strings are not empty strings. Beyond that, I run regexes on strings that require them, and then use prepared statements for all DB interactions.

 

I think that about covers it. And of course passwords are hashed with salts and the like.

Link to comment
Share on other sites

Guest Deleted

Oh! Your link made me remember. When I use empty() I have to do this to prevent notices:

if (!isset($_POST['name'])) $_POST['name'] = '';

And then just do it for each field.

 

Now that I think about this, this step might be more DRY if I used an array.

 

Example:

$fields = array('name', 'fav_color', 'gender');

foreach ($fields as $field)
{
if (!isset($_POST[$field])) $_POST[$field] = '';

}

- - -

 

I'm still a little confused on the checking for the submit button thing. Couldn't a hacker just put a variable in $_POST with the name "submit_btn" and the value "Submit"?

Link to comment
Share on other sites

I don't understand your last question, Buttercream.

Like Larry said, if someone really wanted to, they could submit the form from another site, but all the checks does make it harder to do, and really, at the end of the day, the key is to prevent the sending of bad data. So long as they submit all the valid data, I really don't care how they submit it.

Link to comment
Share on other sites

Guest Deleted

I dunno I'm just confused on how secure my validation methods are. I'm aware that people try to submit forms from remote locations but I always thought that so long as I validated everything thoroughly, it wouldn't matter. From what I've been able to gather, the submit button validation thing is just a little something extra to make it a littler harder to hack your site. From what I can tell, it doesn't make a big difference because the hacker can just look at the html and see <input type="submit" name="submit_btn" value="Submit"> and a savvy hacker might think "Hmm, the form submission is not going through. Maybe I need to add that to my faked variables." Or whatever it is that they do, I don't know. I never tried to hack a site.

 

So yeah that's the current status of my confusion. :)

Link to comment
Share on other sites

Yes, you're absolutely right, checking the submit button is just one little extra thing added to your validation to prevent non-normal submissions. Ultimately, if a hacker is savvy enough and interested enough, they can look at your HTML and probably figure that out, but again, it's one extra loop they have to jump through and one extra potential sticking point.

 

Like I said, I try to perform validation so that anyone submitting the form properly (i.e., normally) will get through fine, but others will not.

 

As an added note, I usually add a hidden field to most forms with a Unix timestamp in order to check for bots. If a standard form is submitted less than five seconds after the page is first loaded, then a bot is likely trying to submit your form, which I like to prevent.

Link to comment
Share on other sites

Guest Deleted

Hmm that's an interesting idea. And one that I never heard of. 

 

Curious: What's the error message that you give when it's submitted too quickly?

Link to comment
Share on other sites

I usually just tell them straight up; "You must wait at least 3 seconds to submit the form." Again though, I've never met anyone that can fill in a form quicker than that (even with a browser assisting them with all/most of the fields). I mean, keep in mind that that is three seconds from the time the page first loads. It usually takes that long for people to just orient themselves.

Link to comment
Share on other sites

Guest Deleted

Does the wording in the error message matter? Ever heard of a bot that would understand "oh! this site wants me to wait a little bit" or would you say bots like that are probably not common.

Link to comment
Share on other sites

I think the wording matters so much as an error message that has grammar or spelling errors reflects badly on the site. Beyond that, I'm not worried about bots, as they're not that smart yet. Bots have never gotten through that defensive mechanism that I mentioned. When bots start making it through, then I'll amend my forms accordingly.

Link to comment
Share on other sites

 Share

×
×
  • Create New...