Validating and Sanitizing PHP DB INPUT HELP PLEASE

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
Jenny Dithe
Forum Newbie
Posts: 2
Joined: Wed Sep 08, 2010 7:13 am

Validating and Sanitizing PHP DB INPUT HELP PLEASE

Post by Jenny Dithe »

Hi,

I would be incredibly grateful for any help as I have taken this as far as I am able and am now in a position where I am just confused by all the different methods I have seen. I have my HTML form and I am sending my information to the insertinto form and am trying to validate, sanitize and prevent injections before the data is put into the database. At the moment it is a mess and not working, all I get is the first response, "Please enter a firstname" even if I have entered a firstname.

Please could someone help me with:
1. What am I doing wrong (I think my code is becoming worse each time I try to solve the problem)?
2. Am I doing everything to protect my code and database, I hear people mentioning MD5 but have no idea what it is. Should I being this or anything else in addition to what is involved?

Code: Select all

<html>
<head>

</head>
<body>
<?php
$filters=array
	(
	"fname"=>array
		(
		"filter"=>FILTER_SANITIZE_STRING
		),
	"lname"=>array
		(
		"filter"=>FILTER_SANITIZE_STRING
		),
	"email"=>FILTER_VALIDATE_EMAIL,
		
	"cemail"=>FILTER_VALIDATE_EMAIL,
			
	"pword"=>array
		(
		"filter"=>FILTER_SANITIZE_INT,
		"options"=>array
			(
			"min_range"=>1,
			"max_range"=>9,
			"strlen"=>12
			)
		),
	"cpword"=>array
		(
		"filter"=>FILTER_SANITIZE_INT,
		"options"=>array
			(
			"min_range"=>1,
			"max_range"=>9,
			"strlen"=>12
			)
		),
	"dobyear"=>array
		(
		"filter"=>FILTER_SANITIZE_INT,
		"options"=>array
			(
			"min_range"=>1992
			)
		),
	"natcountry"=>array
		(
		"filter"=>FILTER_SANITIZE_STRING
		),
	"rcountry"=>array
		(
		"filter"=>FILTER_SANITIZE_STRING
		),
	"postcode"=>array
		(
		"filter"=>FILTER_SANITIZE_STRING
		),
	"other"=>array
		(
		"filter"=>FILTER_SANITIZE_STRING
		),
	);


	$result = filter_input_array(INPUT_GET, $filters);


	if (!$result["fname"])
		{
		echo("Please enter your first name.<br />");return false;
		}
	elseif (!$result["lname"])
		{
		echo("Please enter your last name.<br />"); return false;
		}
	elseif (!$result["email"])
		{
		echo("Email address is not valid.<br />"); return false;
		}
	elseif (!$result["cemail"])
		{
		echo("Your email addresses do not match.<br />"); return false;
		}
	elseif (!$result["pword"])
		{
		echo("Please ensure your password includes a number between 0-9.<br />"); return false;
		}
	elseif (!$result["cpword"])
		{
		echo("Please ensure your password includes a number between 0-9.<br />"); return false;
		}
	elseif (!$result["dobyear"])
		{
		echo("Users must be over 18 years old<br />"); return false;
		}	
	elseif (!$result["natcountry"])
		{
		echo("Please select your nationality.<br />"); return false;
		}
	elseif (!$result["rcountry"])
		{
		echo("Please select your country of residence.<br />"); return false;
		}
	elseif (!$result["postcode"])
		{
		echo("Please enter your postcode.<br />"); return false;
		}
	elseif (!$result["industry"])
		{
		echo("Please select your industry.<br />"); return false;
		}
	else
		{
		return true;
		}
		

	if ($fname=='enter firstname')
		{
		echo("Please enter your first name.<br />");return false;
		}
	elseif ($lname=='enter surname')
		{
		echo("Please enter your last name.<br />"); return false;
		}
	elseif ($email=='enter email address')
		{
		echo("Email address is not valid.<br />"); return false;
		}
	elseif ($cemail=='confirm email address' OR $cemail=='!email')
		{
		echo("Your email addresses do not match.<br />"); return false;
		}
	elseif ($pword='password')
		{
		echo("Please ensure your password includes a number between 0-9.<br />"); return false;
		}
	elseif ($cpword=='password' OR $cpword=='!pword')
		{
		echo("Please ensure your password includes a number between 0-9.<br />"); return false;
		}
	elseif ($DOByear=='please select')
		{
		echo("Users must be over 18 years old<br />"); return false;
		}	
	elseif ($natcountry=='please select')
		{
		echo("Please select your nationality.<br />"); return false;
		}
	elseif ($rcountry=='please select')
		{
		echo("Please select your country of residence.<br />"); return false;
		}
	elseif ($postcode=='enter postcode')
		{
		echo("Please enter your postcode.<br />"); return false;
		}
	elseif ($industry=='please select')
		{
		echo("Please select your industry.<br />"); return false;
		}
	else
		{
		return true;
		}

function check_input($value)
{
if (get_magic_quotes_gpc())
	{
	$value=stripslashes($value);
	}
	
if (!is_numeric($value))
	{
	$value = "'" . mysql_real_escape_string($value) . "'";
	}
return $value;
}

	$con = mysql_connect("localhost","user","password");
	if (!$con)
		{
		die('Could not connect: ' . mysql_error());
		}

	mysql_select_db("my_db", $con);

	$sql="INSERT INTO members(fname, lname, email, cemail, pword, cpword, sex, DOBMonth, DOBDay, DOBYear, natcountry, rcountry, postcode, industry, other, date)
		VALUES
	('$_POST[fname]','$_POST[lname]','$_POST[email]','$_POST[cemail]','$_POST[pword]','$_POST[cpword]','$_POST[sex]','$_POST[DoBMonth]','$_POST[DOBDay]','$_POST[DoBYear]','$_POST[sex]','$_POST[ncountry]','$_POST[postcode]','$_POST[industry]','$_POST[other]','$_GET[CURDATE]')";

	if (!mysql_query($sql,$con))
		{
		die('Error: ' . mysql_error);
		}

	mysql_close($con);

?>

</body>
</html>
Last edited by califdon on Wed Sep 08, 2010 2:54 pm, edited 1 time in total.
Reason: Changed [code] to [syntax=php] tag for readability
User avatar
califdon
Jack of Zircons
Posts: 4484
Joined: Thu Nov 09, 2006 8:30 pm
Location: California, USA

Re: Validating and Sanitizing PHP DB INPUT HELP PLEASE

Post by califdon »

I haven't even tried to look at your entire script, but I simply don't understand what you are trying do with that $filters array, nor all those if - elseif's. The best I can do is try to help you clear your mind about what should be very simple operations:

The place you need to protect data entered into a web form is when you extract them from the $_POST array. So just use either the PHP function filter_var() (ref. http://www.w3schools.com/PHP/func_filter_var.asp) or (my preference) the PHP function mysql_real_escape_string() (ref. http://php.net/manual/en/function.mysql ... string.php) if you have already connected to a mysql server, for each variable, like this:

Code: Select all

$name = filter_var($_POST['name']);
//  or
$name = mysql_real_escape_string($_POST['name']);
I don't understand why you are creating these arrays.

MD5 is a checksum that is often used to store the checksum for a password, rather than storing the password itself. Current practice is to use SHA instead of MD5, but both are widely used for this purpose. You can compare the checksum of what the user entered against the stored checksum to provide validation, but the password itself is NOT stored anywhere, which is why you have to change your password if you forget it, because even the system administrator has no way to know what your password was.
Jenny Dithe
Forum Newbie
Posts: 2
Joined: Wed Sep 08, 2010 7:13 am

Re: Validating and Sanitizing PHP DB INPUT HELP PLEASE

Post by Jenny Dithe »

Thank you so much.

That makes life significantly simpler. Does this adequately protect my databases if I don't have any other security measures?

I looked at the guidelines. Can I do the below to check all fields or do I need to write each one individually?

Also I am getting mysql Error when I go to my page? Is there anything clearly sticking out as wrong?

Code: Select all

<html>
<head>

</head>
<body>
<?php
function check_input($value)
{
if (get_magic_quotes_gpc())
	{
	$value=stripslashes($value);
	}
	
if (!is_numeric($value))
	{
	$value = "'" . mysql_real_escape_string($value) . "'";
	}
return $value;
}

	$con = mysql_connect("localhost","user","password");
	if (!$con)
		{
		die('Could not connect: ' . mysql_error());
		}

	mysql_select_db("my_db", $con);

	$sql="INSERT INTO table(fname, lname, email, cemail, pword, cpword, sex, DOBMonth, DOBDay, DOBYear, natcountry, rcountry, postcode, industry, other, date)
		VALUES
	('$_POST[fname]','$_POST[lname]','$_POST[email]','$_POST[cemail]','$_POST[pword]','$_POST[cpword]','$_POST[sex]','$_POST[DoBMonth]','$_POST[DOBDay]','$_POST[DoBYear]','$_POST[sex]','$_POST[ncountry]','$_POST[postcode]','$_POST[industry]','$_POST[other]','$_GET[CURDATE]')";

	if (!mysql_query($sql,$con))
		{
		die('Error: ' . mysql_error);
		}

	mysql_close($con);

?>

</body>
</html>
User avatar
califdon
Jack of Zircons
Posts: 4484
Joined: Thu Nov 09, 2006 8:30 pm
Location: California, USA

Re: Validating and Sanitizing PHP DB INPUT HELP PLEASE

Post by califdon »

No, somehow you're missing the point. You have to use something like mysql_real_escape_string() on EVERY VALUE. Look at your code: you are directly feeding the unescaped $_POST values into your SQL statement. That's the very thing that is dangerous! Make variables for each one that sanitize them, THEN use the variables in your SQL. Like this:

Code: Select all

...
$fname = mysql_real_escape_string($_POST['fname'];
$lname = mysql_real_escape_string($_POST['lname'];
...
...
$sql = "INSERT INTO table (fname, lname, ...
...
VALUES ($fname, $lname, ...
I'm not a security expert and I would hesitate to say that there are not other protections that you could use, but the above is a pretty standard way to defeat the most common "sql injection" hacks.

You have defined a function called "check_input", but you haven't used it anywhere, so it is useless. To use it, you would have to call the function for each of your variables. Then you would have a problem with the fact that the function adds quotes around non-numeric values, then you are inserting quotes around them when you build your SQL statement, resulting in 2 quotes, which would produce a syntax error. I would just eliminate that function.
User avatar
califdon
Jack of Zircons
Posts: 4484
Joined: Thu Nov 09, 2006 8:30 pm
Location: California, USA

Re: Validating and Sanitizing PHP DB INPUT HELP PLEASE

Post by califdon »

No, somehow you're missing the point. You have to use something like mysql_real_escape_string() on EVERY VALUE. Look at your code: you are directly feeding the unescaped $_POST values into your SQL statement. That's the very thing that is dangerous! Make variables for each one that sanitize them, THEN use the variables in your SQL. Like this:

Code: Select all

...
$fname = mysql_real_escape_string($_POST['fname']);
$lname = mysql_real_escape_string($_POST['lname']);
...
...
$sql = "INSERT INTO table (fname, lname, ...
...
VALUES ('$fname', '$lname', ...
I'm not a security expert and I would hesitate to say that there are not other protections that you could use, but the above is a pretty standard way to defeat the most common "sql injection" hacks.

You have defined a function called "check_input", but you haven't used it anywhere, so it is useless. To use it, you would have to call the function for each of your variables. Then you would have a problem with the fact that the function adds quotes around non-numeric values, then you are inserting quotes around them when you build your SQL statement, resulting in 2 quotes, which would produce a syntax error. I would just eliminate that function.

When you are posting PHP code here, please use the "PHP Code" button at the top of the editing screen to make your posts more readable. I have fixed both of your posts.
Post Reply