Write a secure script with PHP 4.2!

Source: Internet
Author: User
Tags array arrays html form http post variables php and php code access
Security | Script Original: Kevin Yank from: www.linuxforum.net (Congratulations again this open)

For a long time, one of the biggest selling points of PHP as a server-side scripting language is the automatic creation of a global variable for the value submitted from the form. In PHP 4.1, the producers of PHP recommend an alternative way to access the submitted data. In PHP 4.2, they canceled the old practice! As I will explain in this article, the purpose of making such a change is for security reasons. We'll look at new ways in which PHP handles form submission and other data, and explains why doing so increases the security of your code.

What's wrong here?

Look at the following PHP script, which is used to authorize access to a Web page when the username and password are entered correctly:
<?php
Check User name and password
if ($username = = ' Kevin ' and $password = ' secret ')
$authorized = true;
?>
<?php if (! $authorized):?>
<!--unauthorized users will be given a prompt here-->
<p>please Enter your username and password:</p>
<form action= "<?= $PHP _self?>" method= "POST" >
<p>username: <input type= "text" name= "Username"/><br
Password: <input type= "Password" name= "Password"/><br/>
<input type= "Submit"/></p>
</form>
<?php Else:?>
<!--HTML content with security requirements-->
<?php endif;?>
OK, I'm sure about half of the readers would disdain to say, "It's stupid--I'm not going to make that mistake!" "But I promise a lot of readers will think," Hey, no problem, I'll write that too! "Of course there will be a few people who will be puzzled by this question (" What is PHP?) ”)。 PHP is designed as a "good and easy" scripting language that beginners can learn to use in a very short period of time, and it should also be able to avoid mistakes made by beginners.
To get back to the problem, the problem with the above code is that you can easily access the power without having to provide the correct username and password. Just add authorized=1 to the end of your browser's address bar. Because PHP automatically creates a variable for each committed value-whether it comes from moving a submitted form, a URL query string, or a cookie-this will set the $authorized to 1 so that an unauthorized user can break the security limit.
So, how to solve this problem simply? Simply set the $authorized default to False at the beginning of the program. The problem does not exist! $authorized is a variable that is created entirely in program code; But why should developers worry about the variables submitted by each malicious user?

What changes did PHP 4.2 make?

In PHP 4.2, the register_globals option in the newly installed PHP is turned off by default, so the Egpcs value (EGPCS is the abbreviation for environment, GET, Post, Cookies, server)- This is the entire range of external variable sources in PHP and is not created as a global variable. Of course, this option can also be turned on by hand, but the PHP developer recommends that you turn it off. To carry out their intentions, you need to use other methods to get these values.
Starting with PHP 4.1, the Egpcs value can be obtained from a set of specified arrays:
$_env--Contains system environment variables
$_get--Contains the variables in the query string, and the variables in the form that the method is submitted to get
$_post--Contains variables in forms that are submitted as POST
$_cookie--Contains all COOKIE variables
$_server--Contains server variables, such as Http_user_agent
$_request-Full content containing $_get, $_post, and $_cookie
$_session--Contains all registered session variables
Before PHP 4.1, when developers turned off the register_globals option (which was also considered a way to improve PHP performance), they had to use nasty names such as $http_get_vars to get these variables. These new variable names are not only short, but they have other advantages as well.
First, let's rewrite the code mentioned above in PHP 4.2 (that is, turn off the register_globals option):
<?php
$username = $_request[' username '];
$password = $_request[' password '];

Check User name and password
if ($username = = ' Kevin ' and $password = ' secret ')
$authorized = true;
?>
<?php if (! $authorized):?>
<!--unauthorized users will be given a prompt here-->
<p>please Enter your username and password:</p>
<form action= "<?= $PHP _self?>" method= "POST" >
<p>username: <input type= "text" name= "Username"/><br
Password: <input type= "Password" name= "Password"/><br/>
<input type= "Submit"/></p>
</form>
<?php Else:?>
<!--HTML content with security requirements-->
<?php endif;?>
As you can see, all I need to do is add the following two lines to the beginning of the code:
$username = $_request[' username '];
$password = $_request[' password '];
Because we want the user name and password to be submitted by the user, we get these values from the $_request array. Using this array allows the user to freely choose how to pass through URL query strings (such as allowing users to enter their certificates automatically when they create bookmarks), through a submitted form, or through a cookie. If you want to limit the submission of certificates only through the form (or, more precisely, through an HTTP POST request), you can use the $_post array:
$username = $_post[' username '];
$password = $_post[' password '];
In addition to the "Introduction" of these two variables, the program code does not change anything. Simply turning off the register_globals option prompts developers to learn more about which data is from external (untrusted) resources.
Please note that there is a small problem: the default error_reporting setting in PHP is still E_all & ~e_notice, so if the values "username" and "password" are not committed, try to get from the $_request array or Getting these two values in the $_post array does not incur any error messages. If your PHP program requires rigorous error checking, you will need to add some code to check the variables first.

But does this mean more input?

Yes, in a simple program like the above, using PHP 4.2 often increases the amount of input. But look on the bright side-your program is safer!
But seriously, the designers of PHP did not completely ignore your pain. There is a special feature in these new arrays that other PHP variables do not have, and they are complete global variables. How is that going to help you? Let's start with an extension of our example.
To enable multiple pages in the site to use username/password justification, we write our user authentication program to an include file (protectme.php):
<?php/* protectme.php *
function Authorize_user ($authuser, $authpass)
{
$username = $_post[' username '];
$password = $_post[' password '];
Check User name and password
if ($username!= $authuser or $password!= $authpass):
?>
<!--unauthorized users will be given a prompt here-->
<p>please Enter your username and password:</p>
<form action= "<?= $PHP _self?>" method= "POST" >
<p>username: <input type= "text" name= "Username"/><br
Password: <input type= "Password" name= "Password"/><br/>
<input type= "Submit"/></p>
</form>
<?php
Exit ();
endif
}
?>
Now, the page we just looked at will look like this:
<?php
Require (' protectme.php ');
Authorize_user (' Kevin ', ' secret ');
?>
<!--HTML content with security requirements-->
It's simple, it's clear, right? Now is the time to test your eyesight and experience-what's missing in the Authorize_user function?
No declaration in function $_post is a global variable! In PHP 4.0, when Register_globals is turned on, you need to add a line of code to get the $username and $password variables in the function:
function Authorize_user ($authuser, $authpass)
{
Global $username, $password;
...
In PHP, unlike any other language with a similar syntax, a variable outside of a function is not automatically obtained in a function, and you need to add a row to specify that it comes from the global scope as described above.
In PHP 4.0, when you turn off register_globals to provide security, you can use the $http_post_vars array to get the value of your form submission, but you still need to import the array from the global scope:
function Authorize_user ($authuser, $authpass)
{
Global $HTTP _post_vars;
$username = $HTTP _post_vars[' username '];
$password = $HTTP _post_vars[' password '];
However, in PHP 4.1 and later versions, special $_post variables (and the other variables mentioned above) can be used in all scopes. This is why you do not need to declare the $_post variable to be a global variable in the function:
function Authorize_user ($authuser, $authpass)
{
$username = $_post[' username '];
$password = $_post[' password '];

What effect does this have on the session?

The introduction of a special $_session array actually helps to simplify the session code. You don't have to declare the session variable as a global variable, and then pay attention to which variables are registered, and you can now simply refer to all of your session variables from $_session[' varname '.
Now let's look at another example of user authentication. This time, we use sessions to mark a user who has been authenticated by a user who has continued to stay on your site. First, let's look at the PHP 4.0 version (open register_globals):
<?php
Session_Start ();
if ($username = = ' Kevin ' and $password = ' secret ')
{
$authorized = true;
Session_register (' authorized ');
}
?>
<?php if (! $authorized):?>
<!--display an HTML form to prompt the user to log in-->
<?php Else:?>
<!--HTML content with security requirements-->
<?php endif;?>
As with the first program, this program also has a security vulnerability, at the end of the URL plus? authorized=1 can bypass security measures to directly access page content. Developers can view $authorized as a session variable and ignore the easy way to set the same variable through user input.
When we add our special array (PHP 4.1) and close register_globals (PHP 4.2), our program will be like this:
<?php
Session_Start ();
if ($username = = ' Kevin ' and $password = ' secret ')
$_session[' authorized '] = true;
?>
<?php if (!$_session[' authorized ']):?>
<!--display an HTML form to prompt the user to log in-->
<?php Else:?>
<!--HTML content with security requirements-->
<?php endif;?>
Is it even simpler? You no longer need to register an ordinary variable as a session variable, you just set the session variable directly (in the $_session array), and then use it in the same way. The program gets shorter, and the variables that are session variables do not cause confusion!

Summarize

In this article, I explain the underlying reasons for the changes in the PHP scripting language. In PHP 4.1, a special set of data is added to access external data. These arrays can be invoked in any scope, which makes access to external data more convenient. In PHP 4.2, register_globals is closed by default to encourage the use of these arrays to prevent inexperienced developers from writing unsafe PHP code.


--------------------
I believe it will be helpful to everyone.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.