Insecure PHP Constants and Variables

Web-hosting business can now be started for just $19.95 with unlimited resources. Start your own.

Since the introduction of register_globals feature in PHP, there was a lot of discussion around the web criticizing this feature as a security risk. There established a perception that all websites on servers having register_globals enabled are insecure and vulnerable to hacking/injection. Consequently, the feature went to Off in PHP 4.2, deprecated in PHP 5.3 and completely removed in PHP 5.4 [1]. Even before all this, many web hosts disabled this feature. This caused problems to those not-by-profession PHP coders who rely on ease of use of PHP language to code their business or personal website.




If you are one of those who think that register_globals was insecure, then be prepared to consider PHP Variables and specially Constants equally insecure. I have something for you.

Below is an example code that demonstrates how a script may be compromised when register_globals directive is turned ON. The example was taken from
security.globals.php
:
  1. <?php
  2. // define $authorized = true only if user is authenticated
  3. if (authenticated_user()) {
  4.     $authorized = true;
  5. }
  6.  
  7. // Because we didn't first initialize $authorized as false, this might be
  8. // defined through register_globals, like from GET auth.php?authorized=1
  9. // So, anyone can be seen as authenticated!
  10. if ($authorized) {
  11.     include "/highly/sensitive/data.php";
  12. }
  13. ?>
PHP Code

If the directive is ON, an attacker can use the field-value pair authorized=1 in query string with any value assigned to it - not necessarily 1 (because anything other than a
false
is
true
and passes the
if
check) to access /highly/sensitive/data.php.

What caused this attack to be successful? Is it really register_globals? Lets see.

Suppose we have PHP 5.4 where there is no register_globals. The previous example (after little modifications) and the one given below using constants can still be insecure.
  1. <?php
  2. //Somewhere in the start of script
  3. if(authenticated_user( ) ) {
  4.      define( 'AUTHORIZED' , true );
  5. }
  6.  
  7. // .....
  8. // .....
  9. // .....
  10.  
  11. //Somewhere in the middle of the code
  12. if( AUTHORIZED ) {
  13.     include "/highly/sensitive/data.php";
  14. }
  15. ?>
PHP Code

If the user is authenticated one, the constant AUTHORIZED will be defined as
true
and later on user will be allowed access to highly sensitive data. But what if user is not legitimate? In that case, there will be no constant defined and PHP will issue a Notice: Use of undefined constant AUTHORIZED - assumed 'AUTHORIZED' in /path/to/www/dir/script.php on line 12. The constant AUTHORIZED will be assumed by PHP as a string "AUTHORIZED" that will evaluate to
true
when casted to
bool
by PHP, resulting in everyone to pass the
if( AUTHORIZED )
check, as it is the way PHP works.

User was not authorized to get access to restricted areas, but the script let it do. There was no register_globals, but the same sample script is still insecure. Where is the problem?

The problem lies in Bad Coding Practices. PHP does not require you to initialize variables before using (but it does not mean that you do not have to). However, if you try to use an uninitialized variable, PHP treats it as
null
and issues a Notice that the variable is undefined. On the other hand, undefined constants are treated by PHP as
string
and a Notice is issued.

To avoid such problems, what we have to do is:
  • Make sure that variables are always initialized and constant always defined before they are used;
  • Turn ON all PHP Notices, Warnings and Errors in the development using
    error_reporting( E_ALL | E_STRICT );
    . When you move your code to production server, replace the above line with
    error_reporting(0);ini_set( 'display_errors' , '0' );
    .
    Note: As of PHP 5.4,
    E_ALL
    includes
    E_STRICT
    , so it is sufficient to use
    error_reporting( E_ALL );
    on development servers that have PHP 5.4+.

The secure authentication script should look like:
  1. <?php
  2. $authorized = false;
  3. if (authenticated_user()) {
  4.     $authorized = true;
  5. }
  6.  
  7. if ($authorized) {
  8.     include "/highly/sensitive/data.php";
  9. }
  10. ?>
PHP Code

Or, with constant:
  1. <?php
  2. if(authenticated_user( ) ) {
  3.      define( 'AUTHORIZED' , true );
  4. } else {
  5.      define( 'AUTHORIZED' , false );
  6. }
  7.  
  8. if( AUTHORIZED ) {
  9.     include "/highly/sensitive/data.php";
  10. }
  11. ?>
PHP Code

Properly initializing variables with very strict error reporting always benefits you. It not only improves you coding skills, but also makes your code more secure and reliable. There was no security problem with register_globals but the ease of use of PHP combined with poor coding practices adopted by a coders lead it to become a security threat, causing it to die even when it was still needed by some developers. Now when register_globals is officially dead, your code is still no more secure and even your variables and constants can harm your script depending upon how you use them.



  1. High Performance Hosting is now $3.96 a month
  2. register_globals is Back - PHP Implementation
  3. How to validate ASCII Text - PHP
  4. Implementing QuickSort in PHP
  5. Interesting Use of PHP Super Globals
  6. Remove undesired characters with trim_all() - PHP


© 2012-2017 PageConfig.com - Scripts - Twitter