Monday, January 14, 2013

9:17 AM
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: