PHP Forms Preventing Global Variable Injection - Web Development and Design | Tutorial for Java, PHP, HTML, Javascript PHP Forms Preventing Global Variable Injection - Web Development and Design | Tutorial for Java, PHP, HTML, Javascript

Breaking

Post Top Ad

Post Top Ad

Tuesday, June 4, 2019

PHP Forms Preventing Global Variable Injection

PHP Forms


Preventing Global Variable Injection


Problem

You are using an old version of PHP and want to access form input variables without allowing malicious users to set arbitrary global variables in your program.

Solution

The easiest solution is to use PHP version 5.4.0 or later. Starting with that version, the register_globals configuration directive—the source of this global variable injection problem—is removed.

If you’re using an earlier version of PHP, disable the register_globals configuration directive and access variables only from the $_GET, $_POST, and $_COOKIE arrays to make sure you know exactly where your variables are coming from.

To do this, make sure register_globals = Off appears in your php.ini file. If you do not have permission to write to your php.ini file and it has register_globals turned on, then you need to have a serious conversation with your system administrator or find a new hosting provider that is not relying on incorrect settings which are more than a decade old. If you are using PHP with Apache and Apache is configured to use per directory .htaccess files, you can turn register_globals by adding php_flag register_globals off to your .htaccess file.

Discussion

When register_globals is set to on, external variables, including those from forms and cookies, are imported directly into the global namespace. This is a great convenience, but it can also open up some security holes if you’re not very diligent about checking your variables and where they’re defined. Why? Because there may be a variable you use internally that isn’t supposed to be accessible from the outside but has its value rewritten without your knowledge.

Example  Insecure register_globals code

       $username = $dbh->quote($_GET['username']);
       $password = $dbh->quote($_GET['password']);

       $sth = $dbh->query("SELECT id FROM users WHERE username = $username AND
                                               password = $password");

        if (1 == $sth->numRows()) {
             $row = $sth->fetchRow(DB_FETCHMODE_OBJECT);
             $id = $row->id;
        } else {
             "Print bad username and password";
        }

        if (!empty($id)) {
             $sth = $dbh->query("SELECT * FROM profile WHERE id = $id");
        }

Normally, $id is set only by your program and is a result of a verified database lookup.However, if someone alters the query string, and passes in a value for $id, you’ll have problems. With register_globals enabled, your script could still execute the second database query and return results even after a bad username and password lookup. Without register_globals, $id remains unset because only $_REQUEST['id'] and $_GET['id'] are set.

Of course, there are other ways to solve this problem, even when using register_globals. You can restructure your code not to allow such a loophole.

Example  Avoiding register_globals problems

        $sth = $dbh->query("SELECT id FROM users WHERE username = $username AND
                                               password = $password");

        if (1 == $sth->numRows()) {
             $row = $sth->fetchRow(DB_FETCHMODE_OBJECT);
             $id = $row->id;
             if (!empty($id)) {
                  $sth = $dbh->query("SELECT * FROM profile WHERE id = $id");
             }
        } else {
             "Print bad username and password";
        }

In Example $id has a value only when it’s been explicitly set from a database call. Sometimes, however, it is difficult to do this because of how your program is laid out. Another solution is to manually unset() or initialize all variables at the top of your script. This removes the bad $id value before it gets a chance to affect your code. However, because PHP doesn’t require variable initialization, it’s possible to forget to do this in one place; a bug can then slip in without a warning from PHP.

For all of these reasons, it’s best to just turn register_globals off.



No comments:

Post a Comment

Post Top Ad