Using preg_match in my script

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
ironzero
Forum Newbie
Posts: 2
Joined: Thu Dec 21, 2006 7:31 pm

Using preg_match in my script

Post by ironzero »

Below is a script that passes data to a from with a URL, using for example: http://www,site,com/index.php?price=500&title=computer

Code: Select all

<?php
function getIt($value){
  if($_GET[$value]){
    return $_GET[$value];
  }else{
    return "";
  }
}?>

<input type="text" name="price" value="<?php echo getIt("price")?>">
<input type="text" name="title" value="<?php echo getIt("title")?>">
I'm still learning PHP, so my question is this...

I want to validate my input using preg_match, (I'm assuming this would be the easiest and most secure method).

How can I modify my script so that preg_match:

ONLY accepts numbers, dollar signs and periods from:

<input type="text" name="price" value="<?php echo getIt("price")?>">

and ONLY accepts values containing letters and numbers from:

<input type="text" name="title" value="<?php echo getIt("title")?>">


I want to use somthing like this:

if (preg_match('/^\d{5}(-\d{4})?$/',$_GET['zip'])) {
$zip = $_GET['zip'];
} else {
die('Invalid ZIP Code format');
}


Thanks!
User avatar
Kieran Huggins
DevNet Master
Posts: 3635
Joined: Wed Dec 06, 2006 4:14 pm
Location: Toronto, Canada
Contact:

Post by Kieran Huggins »

You can do better than restrict the character types, you can enforce good form:

Code: Select all

$price = '$25.00'; //all these work
$price = '25.00';
$price = '$25';
$price = '25.00';
$price = '$2,500.00';
$price = '2,500.00';
$price = '$2,500';
$price = '2,500';

echo preg_replace('/^\$?([\d,]+)(\.\d{2})?$/',"$1$2",$price);

// and will output a decimal number, with no dollar sign and with or without a period and 2 decimal places, depending on whether or not they were present.
Want to give the 'title' one a try? I'll be here to help you fix it if it's broken.

Cheers,
Kieran
ironzero
Forum Newbie
Posts: 2
Joined: Thu Dec 21, 2006 7:31 pm

Post by ironzero »

Kieran Huggins wrote:You can do better than restrict the character types, you can enforce good form:

Code: Select all

$price = '$25.00'; //all these work
$price = '25.00';
$price = '$25';
$price = '25.00';
$price = '$2,500.00';
$price = '2,500.00';
$price = '$2,500';
$price = '2,500';

echo preg_replace('/^\$?([\d,]+)(\.\d{2})?$/',"$1$2",$price);

// and will output a decimal number, with no dollar sign and with or without a period and 2 decimal places, depending on whether or not they were present.
Want to give the 'title' one a try? I'll be here to help you fix it if it's broken.

Cheers,
Kieran
Thanks, Kieran. :)

Is preg_replace better than preg_match, in terms of security?

Thanks!
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Post by matthijs »

I don't think there's any difference in terms of security between them. It all depends on how you use them. What you are doing is using those functions to validate/filter the input. You want to make sure only data you want is allowed as valid and used in the script.

You might also take a look at htmlentities(), a function used to escape data when you output the data to html.
User avatar
Kieran Huggins
DevNet Master
Posts: 3635
Joined: Wed Dec 06, 2006 4:14 pm
Location: Toronto, Canada
Contact:

Post by Kieran Huggins »

This preg_replace function was designed to return a valid string, if possible. Otherwise, it will return the original string :-(

I should have used the extra parameter so you have a method by which to test the validity:

Code: Select all

$price = preg_replace('/^\$?([\d,]+)(\.\d{2})?$/',"$1$2",$price,'-1',$count);
if($count!=0) // price is valid.. do whatever you want here
Cheers,
Kieran
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

Kieran Huggins wrote:This preg_replace function was designed to return a valid string, if possible. Otherwise, it will return the original string :-(

I should have used the extra parameter so you have a method by which to test the validity:

Code: Select all

$price = preg_replace('/^\$?([\d,]+)(\.\d{2})?$/',"$1$2",$price,'-1',$count);
if($count!=0) // price is valid.. do whatever you want here
Cheers,
Kieran
And why can't preg_match() do this? Kind of what it was intended for isn't it?
User avatar
Kieran Huggins
DevNet Master
Posts: 3635
Joined: Wed Dec 06, 2006 4:14 pm
Location: Toronto, Canada
Contact:

Post by Kieran Huggins »

I figured this would save a little overhead, as the PCRE functions are somewhat costly.
Post Reply