Validation can be done not only on data types but also on other aspects of the
user input. However, the type validation is more of a security concern than the
actual meaning of the value in your application context. For example, say the user
fills out a form field called “age” with a value of 3000. Because we have yet to find
a person anywhere (on Earth or anywhere else) who lived 3,000 years, the age value
is invalid. However, it isn’t an invalid data type. In this case, you may want to com-
bine all your validity checking in a single isValidAge() function.
One of the best ways to validate data is to use regular expressions. Following are
some of the regular expression functions PHP provides:
preg_match().This function takes a regular expression and searches for
it in the given string. If a match is found, it returns TRUE; otherwise, it
returns FALSE. The matched data can also be returned in an array. It stops
searching after finding the first match. For example, say you want to find
out if a user data field called $userData contains anything other than
digits. You can test it with preg_match(“/[^0-9]/”, $userData). Here,
the regular expression /[^0-9]/ tells preg_match to find anything but
the digits.
preg_match_all().This function is just like preg_match(), except it
continues searching for all regular expression patterns in the string. For
example: preg_match(“/[^0-9]/”, $userData, $matches). Here the
regular expression /[^0-9]/ tells preg_match_all to find anything but
the digits and store them in $matches.
preg_quote().You can use this function to escape a regular expression
that contains regular expression characters. For example, say you want to
find out if a string called $userData contains a pattern such as “[a-z]”.
If you call the preg_match() function as preg_match(“/[a-z]/”,
$userData), it will return wrong results because “[a-z]” happens to be a
valid regular expression itself. Instead, you can use preg_quote() to
escape “[a-z]” and then use it in the preg_match() call. For example,
preg_match(‘/’ . preg_quote(“[a-z]”) . ‘/’ , $userData) will
work.
There are other functions such as preg_grep(), preg_replace(), and so forth,
that are also useful. For example, you can access information on these functions
via http://www.evoknow.com/preg_grep and http://www.evoknow.com/
preg_replace. Instead of writing validation routines for common data types, you
can find free validation classes on the Web. One such class is called Validator,
which can be found at www.thewebmasters.net/php/Validator.phtml.
After you download and install the Validator class per its author’s instructions,
you can use it very easily. For example, Listing 2-5 shows a simple Web form script
called myform.php that uses this validation class to validate user data.
36 Part I: Designing PHP Applications
04 549669 ch02.qxd 4/4/03 9:24 AM Page 36
Listing 2-5: myform.php
<?php
error_reporting(E_ALL);
define(‘DEBUG’, FALSE);
include(“class.Validator.php3”);
// Create a Validator object
$check = new Validator ();
// Get User data
$email = (! empty($_REQUEST[‘email’])) ? $_REQUEST[‘email’] : null;
$state = (! empty($_REQUEST[‘state’])) ? $_REQUEST[‘state’] : null;
$phone = (! empty($_REQUEST[‘phone’])) ? $_REQUEST[‘phone’] : null;
$zip = (! empty($_REQUEST[‘zip’])) ? $_REQUEST[‘zip’] : null;
$url = (! empty($_REQUEST[‘url’])) ? $_REQUEST[‘url’] : null;
DEBUG and print “Debug Code here \n”;
// Call validation methods
if (!$check->is_email($email)) { echo “Invalid email format<br>\n”;}
if (!$check->is_state($state)) { echo “Invalid state code<br>\n”; }
if (!$check->is_phone($phone)) { echo “Invalid phone format<br>\n”;}
if (!$check->is_zip($zip)) { echo “Invalid zip code<br>\n”; }
if (!$check->is_url($url)) { echo “Invalid URL format<br>\n”; }
// If form data has errors show error and exit
if ($check->ERROR)
{
echo “$check->ERROR<br>\n”;
exit;
}
// Process form now
echo “Form processing not shown here.<br>”;
?>
The class Validator.php3 is included in the script. The $check variable is a
Validator object, which is used to validate user-supplied data. If there is any error
in any of the validation checks that is, if any of the validation methods return
false the script displays an error message. If no error is found, the script continues
to process the form, which is not shown in this sample code. To learn more about
the validation methods that are available in this class, review the documentation
supplied with the class.
Chapter 2: Understanding and Avoiding Security Risks 37
04 549669 ch02.qxd 4/4/03 9:24 AM Page 37
Not Revealing Sensitive Information
Another major source of security holes in applications is unnecessary disclosure of
information. For example, say you have a script called mysite.php as follows:
<?php
phpinfo();
?>
This script shows all the PHP information about the current site, which is often very
useful in finding various settings. However, if it is made available to the public, you
give malicious hackers a great deal of information that they would love to explore
and potentially exploit.
Such a harmless script can be a security hole. It reveals too much information
about a site. For security purposes, it is extremely important that you don’t reveal
your system-related information about your site to anyone. We recommend that you use
phpinfo() in only development systems which should not be allowed to be accessed by
everyone on the Web. For example, you can use $_SERVER[‘REMOTE_ADDR’] value to
restrict who has access to a sensitive script. Here is an example code segment:
<?php
// Enable all error reporting
error_reporting(E_ALL);
// Create a list of valid IP addresses that can access
// this script
$validIPList = array(‘192.168.1.1’, ‘192.168.1.2’);
// If current remote IP address is not in our valid list of IP
// addresses, do not allow access
if (! in_array($_SERVER[‘REMOTE_ADDR’], $validIPList))
{
echo “You do not access to this script.”;
exit;
}
// OK, we have a valid IP address requesting this script
// so show page
phpinfo();
?>
38 Part I: Designing PHP Applications
04 549669 ch02.qxd 4/4/03 9:24 AM Page 38
Here the script exists whenever a request to this script comes from a remote IP
address that is not in the valid IP list ($validIPList).
Let’s take a look at some other ways in which you can safely conceal informa-
tion about your application:
Remove or disable any debugging information from your application.
Debugging information can provide clues about your application design
(and possibly its weaknesses) to others who may take the opportunity to
exploit them. If you add debugging code, use a global flag to enable and
disable debugging. For example:
<?php
define(‘DEBUG’, FALSE);
DEBUG and print “Debug message goes here.\n”;
?>
Here DEBUG constant is set to FALSE and, therefore, the print statement is
not going to print anything. Setting DEBUG to TRUE enables debug mes-
sages. If all your debug code is enabled or disabled in this manner, you
can easily control DEBUG messages before you put the script in the pro-
duction environment.
Don’t reveal sensitive paths or other information during Web-form
processing. A common misunderstanding that hidden fields are secret,
often causes security-novice developers to reveal sensitive path or other
information during Web-form processing. For example:
<input type=hidden name=”save_path”
value=”/www/secret/upload”>
This line in a HTML form is not hidden from anyone who has a decent
Web browser with the View Source feature. So do not ever rely on hidden
field for security. Use hidden fields only for storing information that are
not secret.
Never store sensitive information on the client side. If you must store
sensitive data, consider using a database or at least a file-based session,
which will store data on the server side. If you must store data on the
client side for some special reason, consider encrypting the data (not just
encoding it). See Chapter 22 for details on data encryption.
Chapter 2: Understanding and Avoiding Security Risks 39
04 549669 ch02.qxd 4/4/03 9:24 AM Page 39
Summary
In this chapter, you learned about the common security risks for PHP applications
and how to deal with them. Most of the security risks are related to user input and
how you handle them in your scripts. Expecting all users will behave politely and
will not try to break your code is not at all realistic. Let’s face it, there are a lot of
people (of all ages) with too much free time and Internet bandwidth these days,
which means there is a lot out there with intents to hack, deface Web sites just for
the sake of it. So do not trust user input to be just what you need to run your appli-
cation. You need to deal with unexpected input as well.
Revealing sensitive information such as software version, server environment
data, etc., can also have a major ill effect on your overall security as such informa-
tion can be used in building attack tools or techniques. The best practice is to reveal
as little as necessary.
40 Part I: Designing PHP Applications
04 549669 ch02.qxd 4/4/03 9:24 AM Page 40