Php Basic Security

Preview:

Citation preview

Basic security.

• learn how to validate user input and deal with potentially unsafe data.

• when designing an application, developer had to include an input validation routine.

• a failure to do this can result into serious problems, or even cause the application to break when it encounters invalid or corrupt data.

• Tips to validate user input, and provide user notification in understandable and non-threatening way (user friendly)

Introduction

The Common Input Errors1. Empty record -assuming no NOT NULL

constraints on the target table• Solution:• To avoid this, it's important to verify that the

form does, in fact, contain valid data, and only then perform the INSERT query

• the trim() function - used to trim leading and trailing spaces from the field value, then compared with an empty string. If the match is true, the field was submitted empty, and the script dies with an error message before MySQL comes into the picture.

• Example :security2.php

security2.php<html>

<head></head><body><?phpif (!isset($_POST['submit'])) {?>    <form action = '<?php $_SERVER['PHP_SELF'] ?>' method = 'post'>    Which sandwich filling would you like?    <br />    <input type = 'text' name = 'filling'>    <br />    <input type = 'submit' name = 'submit' value = 'Save'>    </form><?php}else {    // check for required data    // die if absent    if (!isset($_POST['filling']) || trim($_POST['filling']) == '') {        die("ERROR: You can't have a sandwich without a filling!");    }    else {        $filling = mysql_escape_string(trim($_POST['filling']));    }

  

  // set database variables    $host = 'localhost';    $user = 'user';    $pass = 'secret';    $db = 'sandwiches';

    // open connection    $connection = mysql_connect($host, $user, $pass) or die('Unable to connect!');

    // select database     mysql_select_db($db) or die('Unable to select database!');

    // create query    $query = 'INSERT INTO orders (filling) VALUES ("$filling")';

    // execute query    $result = mysql_query($query) or die("Error in query: $query. ".mysql_error());

    // close connection    mysql_close($connection);

    // display message    echo "Your {$_POST['filling']} sandwich is coming right up!";}?></body></html>

2. Wrong Data type or size- is_numeric() function-checked if the value is numeric. It tests a string to see if it is a numeric.

- intval() function -to test if it's an integerExample :datatype4.php

datatype4.php<html><head></head><body><?phpif (!isset($_POST['submit'])) {?>    <form action = '<?php $_SERVER['PHP_SELF']?>' method = 'post'>    How many sandwiches would you like? (min 1, max 9)    <br />    <input type = 'text' name = 'quantity'>    <br />    <input type = 'submit' name = 'submit' value = 'Save'>    </form><?php}else {    // check for required data    // die if absent    if (!isset($_POST['quantity']) || trim($_POST['quantity']) == '') {        die ("ERROR: Can't make 'em if you don't say how many!");    }

   

 // check if input is a number    if (!is_numeric($_POST['quantity'])) {        die ("ERROR: Whatever you just said isn't a number!");    }

    // check if input is an integer    if (intval($_POST['quantity']) != $_POST['quantity']) {        die ("ERROR: Can't do halves, quarters or thirds... I'd lose my job!");    }

    // check if input is in the range 1-9    if (($_POST['quantity'] < 1) || ($_POST['quantity'] > 9)) {        die ('ERROR: I can only make between 1 and 9 sandwiches per order!');    }

    // process the data    echo "I'm making you {$_POST['quantity']} sandwiches. Hope you can eat them all!";}?></body></html>

-the strlen() function- returns the length of a string.

Example :strlen5.php

<html><head></head><body><?phpif (!isset($_POST['submit'])) {?>    <form action = '<?php $_SERVER['PHP_SELF']?>' method = 'post'>    Enter a nickname 6-10 characters long:    <br />    <input type = 'text' name = 'nick'>    <br />    <input type = 'submit' name = 'submit' value = 'Save'>    </form><?php}else {  

// check for required data

    // die if absent    if (!isset($_POST['nick']) || trim($_POST['nick']) == '') {         die ('ERROR: Come on, surely you can think of a nickname! How about Pooky?');    }

    // check if input is of the right length    if (!(strlen($_POST['nick']) >= 6 && strlen($_POST['nick']) <= 10)) {        die ("ERROR: That's either too long or too short!");    }

    // process the data    echo "I'll accept the nickname {$_POST['nick']}, seeing as it's you!";}?></body></html>

3. Date validation-important to check that date values provided by the user are valid before using them in a calculation.Eg:29-Feb-2005 or 31-Apr-2005 -the checkdate() function- accepts three arguments - month, day and year - and returns a Boolean value indicating whether or not the date is valid. Example:date6.php

date6.php

<html><head></head><body><?phpif (!isset($_POST['submit'])) {?>    <form action = '<?php $_SERVER['PHP_SELF']?>' method = 'post'>    Enter your date of birth:    <br /><br />    <select name = 'day'>    <?php    // generate day numbers    for ($x = 1; $x <= 31; $x++) {        echo "<option value = $x>$x</option>";    }    ?>    </select>    <select name = 'month'>    <?php    // generate month names    for ($x = 1; $x <= 12; $x++) {        echo "<option value=$x>".date('F', mktime(0, 0, 0, $x, 1, 1)).'</option>';    }      

  ?>    </select>    <select name = 'year'>    <?php  

// generate year values    for ($x = 1950; $x <= 2005; $x++) {        echo "<option value=$x>$x</option>";    }    ?>    </select>    <br /><br />    <input type = 'submit' name = 'submit' value = 'Save'>    </form><?php}else {    // check if date is valid    if (!checkdate($_POST['month'], $_POST['day'], $_POST['year'])) {        die("ERROR: The date {$_POST['day']}-{$_POST['month']}-{$_POST['year']} doesn't exist!");    }

    // process the data    echo "You entered {$_POST['day']}-{$_POST['month']}-{$_POST['year']} - which is a valid date.";}?></body></html>

4. multiple-choice form elements -eg: drop-down list boxes and radio buttons-in cases where it's mandatory to make a choice -to validate: when the form is submitted, selections made are placed in an array, is_array() and sizeof() functions are used to ensure that it contains at least one element. Example:multichoice7.php

multichoice7.php

<html><head></head><body><?phpif (!isset($_POST['submit'])) {?>    <form action = '<?php $_SERVER['PHP_SELF'] ?>' method = 'post'>    Pizza base:    <br />    <input type = 'radio' name = 'base' value = 'thin and crispy'>Thin and crispy    <input type = 'radio' name = 'base' value = 'deep-dish'>Deep-dish    <br />Cheese:    <br />    <select name = 'cheese'>        <option value = 'mozzarella'>Mozzarella</option>        <option value = 'parmesan'>Parmesan</option>        <option value = 'gruyere'>Gruyere</option>    </select>    <br />    Toppings:    <br />    <select multiple name = 'toppings[]'>        <option value = 'tomatoes'>Tomatoes</option>        <option value = 'olives'>Olives</option>        <option value = 'pepperoni'>Pepperoni</option>        <option value = 'onions'>Onions</option>        

<option value = 'peppers'>Peppers</option>        <option value = 'sausage'>Sausage</option>        <option value = 'anchovies'>Anchovies</option>    </select>    <br />    <input type = 'submit' name = 'submit' value = 'Save'>    </form><?php}else {    // check radio button    if (!isset($_POST['base'])) {        die('You must select a base for the pizza');    }

    // check list box    if (!isset($_POST['cheese'])) {        die('You must select a cheese for the pizza');    }

    // check multi-select box    if (!is_array($_POST['toppings']) || sizeof($_POST['toppings']) < 1) {        die('You must select at least one topping for the pizza');    }

    // process the data    echo "One {$_POST['base']} {$_POST['cheese']} pizza with ";    foreach ($_POST['toppings'] as $topping) echo $topping.", ";    echo "coming up!";}?></body></html>

5. regular expressions

-used for pattern matching and substitution

-regular expression matching takes place with the ereg() or preg_match() functions and eregi() for a case-insensitive version

-Example: security9.php,using the email address validator

security9.php

<html><head></head><body><?phpif (!isset($_POST['submit'])) {?>    <form action = '<?php $_SERVER['PHP_SELF'] ?>' method = 'post'>    Email address:    <br />    <input type = 'text' name = 'email'>    <input type = 'submit' name = 'submit' value = 'Save'>    </form><?php}else {    // check email address    if (!ereg('^([a-zA-Z0-9])+([\.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-]+)*\.([a-zA-Z]{2,6})$', $_POST['email'])) {        die("Dunno what that is, but it sure isn't an email address!");    }

    // process the data    echo "The email address {$_POST['email']} has a valid structure. Doesn't mean it works!";}?></body></html>

Sample application

• PHP class that exposes basic object methods for data validation and error handling, and then use it to validate a form.

• Example:classformValidator.php

• consists of 2 components:

a) methods that accept the data to be validated, test the data to see whether it is valid or not

classformValidator.php

<?php// PHP 5

// class definition// class encapsulating data validation functionsclass formValidator {

    // define properties    private $_errorList;

    // define methods    // constructor    public function __construct() {        $this->resetErrorList();    }

    // initialize error list    private function resetErrorList() {        $this->_errorList = array();    }

// check whether input is empty    public function isEmpty($value) {        return (!isset($value) || trim($value) == '') ? true : false;    }

    // check whether input is a string    public function isString($value) {        return is_string($value);    }

    // check whether input is a number    public function isNumber($value) {        return is_numeric($value);    }

    // check whether input is an integer    public function isInteger($value) {        return (intval($value) == $value) ? true : false;    }

• isEmpty() - tests if a value is an empty string • isString() - tests if a value is a string • isNumber() - tests if a value is a numeric string • isInteger() - tests if a value is an integer • isAlpha() - tests if a value consists only of

alphabetic characters • isEmailAddress() - tests if a value is an email

address • isWithinRange() - tests if a value falls within a

numeric range • isInArray() - tests if a value exists in an array

// check whether input is alphabetic    public function isAlpha($value) {        return preg_match('/^[a-zA-Z]+$/', $value);    }

    // check whether input is within a numeric range    public function isWithinRange($value, $min, $max) {        return (is_numeric($value) && $value >= $min && $value <= $max) ? true : false;    }        // check whether input is a valid email address    public function isEmailAddress($value) {        return eregi('^([a-z0-9])+([\.a-z0-9_-])*@([a-z0-9_-])+(\.[a-z0-9_-]+)*\.([a-z]{2,6})$', $value);    }

    // check if a value exists in an array    public function isInArray($array, $value) {        return in_array($value, $array);    }

b) a PHP array that holds a list of all the errors encountered during the validation process

• isError() - check if any errors exist in the error list

• addError() - add an error to the error list • getErrorList() - retrieve the current list of errors • resetErrorList() - reset the error list

  // add an error to the error list    public function addError($field, $message) {        $this->_errorList[] = array('field' => $field, 'message' => $message);    }

    // check if errors exist in the error list    public function isError() {        return (sizeof($this->_errorList) > 0) ? true : false;    }

    // return the error list to the caller    public function getErrorList() {        return $this->_errorList;    }

    // destructor    // de-initialize error list    public function __destruct() {        unset($this->_errorList);    }

// end class definition}

?>

• To process the class, processor.php is needed:• Functions used are listed below:• isEmpty() method -used to test if required fields

have been filled in• isEmailAddress() and isWithinRange() methods-

used for more precise validation.• isInArray() method- check boxes and multiple-select

lists• a foreach() loop iterates over the list of errors and

prints them in a bulleted list.

processor.php

<?php

// include file containing classinclude('class.formValidator.php');

// instantiate object$fv = new formValidator();

// start checking the data

// check nameif ($fv->isEmpty($_POST['name'])) {    $fv->addError('Name', 'Please enter your name');}

// check age and age rangeif (!$fv->isNumber($_POST['age'])) {    $fv->addError('Age', 'Please enter your age');}else if (!$fv->isWithinRange($_POST['age'], 1, 99)) {    $fv->addError('Age', 'Please enter an age value in the numeric range 1-99');}

// check sexif (!isset($_POST['sex'])) {    $fv->addError('Sex', 'Please select your gender');}

// check email addressif (!$fv->isEmailAddress($_POST['email'])) {    $fv->addError('Email address', 'Please enter a valid email address');}

// check colorif ($fv->isEmpty($_POST['color'])) {    $fv->addError('Color', 'Please select one of the listed colors');}

// check insurance typeif ($fv->isEmpty($_POST['insurance'])) {    $fv->addError('Insurance', 'Please select one of the listed insurance types');}

// check optional featuresif (isset($_POST['options'])) {    if ($fv->isInArray($_POST['options'], '4WD') && !$fv->isInArray($_POST['options'], 'PSTR')) {        $fv->addError('Optional features', 'Please also select Power Steering if you would like Four-Wheel Drive');    }}

// check to see if any errors were generatedif ($fv->isError()) {    // print errors    echo '<b>The operation could not be performed because one or more error(s) occurred.</b> <p /> Please resubmit the form after making the following changes:';    echo '<ul>';    foreach ($fv->getErrorList() as $e) {        echo '<li>'.$e['field'].': '.$e['message'];    }    echo '</ul>';}else {    // do something useful with the data    echo 'Data OK';}

?>