This article deals with two issues - securing your script against a possible exploit; and
how to write your scripts so that they will be compatible with later versions of PHP.
These apparently unrelated issues are dealt together for reasons you will see later in
this article.
Security Hole
As PHP script writers already know, one of the conveniences in using PHP is that you don't have
to do anything special to access variables set by your forms. For example, if your form has an
<input> variable called "email", your script will automatically inherit a global variable
called $email. Unfortunately, this convenience also leads to a potential security hole.
By "security hole", I do not mean that PHP itself has a security hole. Rather, the
security issue is actually created by writers of PHP scripts who inadvertently create a
bug through which others can exploit.
Take the following code as an example:
if (input_is_okay()) {
$valid_input = 1 ;
}
if ($valid_input) {
show_financial_data();
}
else {
show_order_form();
}
The code calls input_is_okay() to check whether the visitor has entered all the necessary
fields in a form correctly. If he/she has, input_is_okay() would give a non-zero response,
and the routine would set the variable $valid_input to 1.
The next bit of code checks if $valid_input is non-zero. If so, it will call the
function show_financial_data() which presumably displays some information that the visitor
is authorized to view. Otherwise, if $valid_input is zero, the visitor will be
greeted with an order form where he can pay for the service.
The problem with the above code, as of course you will have realised, is that if an
unscrupulous visitor calls your script with the variable "valid_input" set to 1, he
can bypass your security checking routine input_is_okay(). This is trivial to do.
For example, if your script is called stockprices.php, he can simply type
http://yourdomain.com/stockprices.php?valid_input=1
into his browser. In the default configuration for PHP 4.1 and below, PHP will automatically
change the valid_input in the HTTP request line to a variable by the name of $valid_input,
and set it to the value given, ie, 1.
That means, that user will always be able to cause your script to display the information
printed by show_financial_data() regardless of how he completed your form.
Plugging the Security Hole (Works on All PHP Versions)
As noted earlier, this is not a problem with PHP. This is a problem with the script; or,
to put it bluntly, the script is potentially buggy. If you wrote code like the above in
a different programming language and ran it through a modern compiler (like a C compiler),
chances are that the compiler will flag the code with a warning to the effect that you
may be using an uninitialized variable in the code.
One solution to the security hole in the above code is to make sure that you initialise
every variable that you use in your script (unless of course the variable is supposed to
contain input given by the visitor). For example, if you must use code like the above,
you can fix the "hole" by changing the start of the code to the above.
if (input_is_okay()) {
$valid_input = 1 ;
}
else {
$valid_input = 0 ;
}
This way, even if the visitor calls the script with
http://yourdomain.com/stockprices.php?valid_input=1
your security checks in input_is_okay() will not be circumvented. By setting $valid_input
to either 0 or 1 in your script, the $valid_input value given in the HTTP request is
overridden by your internal variable assignment.
PHP 4.1.0 and Above: How it Helps
With PHP 4.1.0, the developers of PHP have provided script writers another way (yeah, yet
another way!) to access global variables. For example, to access the form variable "email"
in your scripts from a form submitted with the "get" action, you can simply read $_GET["email"]
for the information. If your form uses the "post" action, just access the information
by reading $_POST["email"]. Cookies can be accessed using the $_COOKIE array. If you don't
really want to distinguish between the three types of input, simply use the $_REQUEST
array, as for example, in the following statement:
echo "Your input was " . $_REQUEST["email"] ;
The intention behind creating this plethora of arrays (there are more!) is to eventually remove
the default action of automatically converting form variables into script variables.
This automatic conversion is controlled by the php.ini configuration variable
"register_globals". If set to 1 (which is the default even up to PHP 4.1.0), all form variables
are automatically converted to global variables in the script. Future semi-major versions of
PHP will not make this the default.
0 comments:
Post a Comment