Web Hosting Forum | Lunarpages


*
Welcome, Guest. Please login or register.
Did you miss your activation email?



Login with username, password and session length
April 22, 2014, 11:19:22 PM

Pages: [1] 2   Go Down
  Print  
Author Topic: PHP and Register Global Variables  (Read 69949 times)
MrPhil
Senior Moderator
Berserker Poster
*****
Offline Offline

Posts: 5811



« on: February 27, 2008, 06:29:28 PM »

1. What are Register Global Variables?

It is a frequent necessity to transfer variable values between pages. You may have an HTML <form> which asks for user input to named fields. These fields (as well as hidden variables) will be transferred to a PHP page for processing. This may be the same page that defines the form, or a different one. A method of either 'post' or 'get' must be given in the form tag.

Another way to transfer variable data to another page is make an HTML link (such as with <a href="target_page.php?var_name_1=data&var_name_2=data">click this link</a>).This of course can be entered on the browser's address line, too. This information (the stuff after the ?, or "var_name_1=data&var_name_2=data") is known as a URL Query String ("UQS") and can be treated like a "GET" form submission.

So, how do these variables and their data get into my PHP code?

Once upon a time, most PHP programmers simply grabbed variables and values by using them in their code. Let's say you had two fields in a form, named "user_name" and "user_email". You could simply use $user_name and $user_email in your code (the receiving, or target, page), and they would have the values filled in by the user in the form. Life was simple, wasn't it? $user_name and $user_email were examples of a special kind of PHP variable, called a register global variable. You simply used it, and it was magically there to pull in data transferred from a form or a link on another page.
Logged

Visit My Site

E-mail Me
  
-= From the ashes shall rise a sooty tern =-
MrPhil
Senior Moderator
Berserker Poster
*****
Offline Offline

Posts: 5811



« Reply #1 on: February 27, 2008, 06:31:19 PM »

2. So what's the problem, or why doesn't my code work anymore?

You've been happily using register global variables for years, and all of a sudden, your code doesn't work anymore. You might get PHP or MySQL errors, or a blank page, or your system just isn't working as expected. Maybe you added some debug print statements, and discovered that these register global variables are now simply undefined (have no value).

What happened? Well, the short story is that you just can't trust people on the Web like you used to. I won't go into the gory details, but when using register global variables, anyone can invoke your page from their own form or the browser address line with fake variable data. That is, they can define variables with values that shouldn't be. This is considered a serious security hole, especially if you fail to initialize your PHP variables and just assume a null initial value. Someone can "plant" a bogus starting value and you wouldn't realize it.

The PHP development community has decided that this is such a serious security problem that they are actively discouraging the use of register global variables. Up through PHP version 4.1, register global variables were enabled ("on") by default. Starting in PHP 4.2, installations are being encouraged to turn register global variables off by default, but Lunarpages began doing this only recently, long after PHP 5 was released, and is turning register global variables off during PHP upgrades. PHP 5 is the current production level of PHP (although Lunarpages still offers PHP 4 on many servers). PHP version 6 will be out in the near future (although Lunarpages will undoubtedly stay at version 5 until it's satisfied that PHP 6 is stable enough for production use). PHP 6 won't even permit you to use register global variables, so you'll need to fix your code by then.

So, at some point, Lunarpages upgraded PHP (or even, without an upgrade) on your server, and turned off register global variables. This means that these variables, when used in your code, no longer show up with the intended values, but are undefined (empty, in practical terms). This tends to break code that ran well for years, but is an unfortunate necessity in today's world, which is filled with hackers probing for weaknesses in your PHP scripts.

If your PHP code has been working fine for ages, and all of a sudden isn't (with or without explicit error messages), it's a pretty good bet that you're using register global variables and they've been turned off, breaking your code. It's easy enough (see the following section) to try turning "on" register global variables and seeing if that fixes the problem.

Edit per corrections by JeremyD
« Last Edit: February 28, 2008, 03:08:02 PM by MrPhil » Logged

Visit My Site

E-mail Me
  
-= From the ashes shall rise a sooty tern =-
MrPhil
Senior Moderator
Berserker Poster
*****
Offline Offline

Posts: 5811



« Reply #2 on: February 27, 2008, 06:34:23 PM »

3. The Quick and Dirty way to keep using register global variables

If your Web site isn't going to exist much longer, or is due for a major rewrite soon anyway, or uses scripts that you don't feel like patching (e.g., osCommerce 2.2 MS2), you can still turn on register global variables (for the time being).

Note: this discussion assumes that you are on a shared server running Linux and Apache server (Basic and Business plans). If you are on a Virtual Private Server (VPS), dedicated server, or Windows-based server, these instructions may not apply, and you'll need to find out how to do it on your server. For example, on a Linux/Apache VPS or dedicated server, you may have your PHP settings in a file named httpd.conf instead. Maybe.

First, you need a file called php.ini that contains various settings for the use of PHP. You may already have one if you needed to, say, set larger limits for uploaded files. If not, you will have to create a new file named php.ini somewhere. It is simplest to put it in /home/YOUR_ACCOUNT_NAME/public_html/, but you should take measures to keep others from peeking into this file. Some people like to put it in /home/YOUR_ACCOUNT_NAME/ instead -- that's secure against prying eyes. It is possible to have just one php.ini that applies to your entire site, or you can have different php.ini files for the use of different subsystems. Of course, different php.ini files need to be placed in different directories, usually the "root" directory of the system that needs its particular settings.

The php.ini file, whether new or existing, and wherever it is, needs to contain the line:

register_globals = on

(Capitalization doesn't really matter.) The permissions are usually "644".

Second, you need to add lines to your .htaccess file to tell PHP where to find your applicable php.ini file. Let's say you put it in /home/YOUR_ACCOUNT_NAME/public_html/. The entry in .htaccess would be:

suPHP_ConfigPath  /home/YOUR_ACCOUNT_NAME/public_html

Obviously, YOUR_ACCOUNT_NAME in these instructions is replaced by your account name (the one you sign onto cPanel with). It's not the server name. You can have multiple .htaccess files in different directories to control your site, so make sure each one points to the appropriate php.ini file (a simple matter if you have only one). If you put your php.ini file in /home/YOUR_ACCOUNT_NAME/, that's all you need to do. However, if it was placed in any directory in or below /home/YOUR_ACCOUNT_NAME/public_html/, any browser will be able to look at it unless you add the following lines to the .htaccess file:

<Files php.ini>
order allow,deny
deny from all
</Files>


That should keep out snoopers.

So, now you have a php.ini file controlling your PHP usage, with settings that include a request to turn register global variables back on so you can use them. Please note that in doing this, you are making your PHP code somewhat less secure than it would otherwise be. You also have an entry in the .htaccess file telling PHP where to find its php.ini file with the settings to use.

A final note: some old PHP books and instructions will tell you to put a line in .htaccess similar to:

php_value register_globals on

Don't do this. "php_value" doesn't work anymore on Lunarpages servers. Put PHP settings into your php.ini file.
Logged

Visit My Site

E-mail Me
  
-= From the ashes shall rise a sooty tern =-
MrPhil
Senior Moderator
Berserker Poster
*****
Offline Offline

Posts: 5811



« Reply #3 on: February 27, 2008, 06:38:12 PM »

4. The proper way to eliminate register global variables

While you can still turn register globals on using the instructions above, that is not a good long-term solution.

1) It keeps open a security hole that someone may be able to exploit, especially if you are using a canned script that hackers have the source to.

2) Eventually, Lunarpages will upgrade to PHP 6 and you won't even be able to turn register global variables on.

For PHP code that is going to be around for a while, you should upgrade it to no longer use register global variables. In a nutshell, you need to explicitly import POST or GET variables before using them. The easiest way is to have a section of code near the top of the receiving (target) page that defines your variables (the ones that are currently register global variables). In the example given earlier, where a form passes user_name and user_email to your page, if the form method is POST, you would write:

$user_name = $_POST['user_name'];
$user_email = $_POST['user_email'];


If the form method is GET, you would write:

$user_name = $_GET['user_name'];
$user_email = $_GET['user_email'];


There is a shortcut, so long as you are not using both GET and POST with the same named variables being passed (supposedly this is possible, but it sounds messy and ripe for problems to me). The $_REQUEST array is a combination (union) of $_GET and $_POST, so you can write instead:

$user_name = $_REQUEST['user_name'];
$user_email = $_REQUEST['user_email'];


and not have to worry about whether it was passed as GET or POST.

A few important notes:

1) URL Query String variables can be imported using either $_GET or $_REQUEST. You cannot use $_POST with UQS variables.

2) With register global variables, if the variable was not defined in a form or UQS, it would not be set. Once you put in the above code (e.g., $user_name = $_REQUEST['user_name'];), $user_name will be set (but empty) if that variable (user_name) wasn't passed in from the form! You will need to test $_REQUEST['user_name'] itself (with the isset() function), rather than testing the $user_name local variable.

3) You don't have to set a local variable to $_xxx['var_name'] -- you can simply use $_REQUEST['user_name'] in your code instead of $user_name. It's just that it's usually neater (and less typing) to load up a local variable ($user_name in this example) than to repeatedly type in the longer form. If you changing from using register global variables, you'll already have the $user_name throughout your code anyway -- why bother changing it?

4) Old timers in the PHP world have a habit of dropping the apostrophes around the associative array element name (e.g., $_REQUEST[user_name] instead of $_REQUEST['user_name']). This is a bad habit that has long been tolerated by PHP, but may not be for much longer. Get in the habit of making associative array element names as proper strings ('name' or "name").

By the way, osCommerce 2.2 RC1 and later no longer requires register global variables to be "on". Unfortunately, it may be a while before Fantastico upgrades beyond 2.2 MS2 (they may choose to wait until 2.2 final is released). You will need to manually install 2.2 RC2a or later to get rid of the need for register global variables. Most other PHP packages, if not already free of register global variables, should be in the process of eliminating them. PHP 5 and news of the withdrawl of register global variables have been out long enough that any actively maintained package should be well on its way to no longer using register global variables.
Logged

Visit My Site

E-mail Me
  
-= From the ashes shall rise a sooty tern =-
Mitch
Berserker Poster
*****
Offline Offline

Posts: 12641


WWW
« Reply #4 on: February 27, 2008, 07:01:02 PM »

Wow, great work MrPhil! Thanks for the write up on this!
Logged

New to Web Site Hosting? Check Out the Lunarpages Blog Hosting Guide!


Follow us @lunarpages on Twitter!
Important Threads: Read This Before Posting! | Lunarforums Rules! | Mitch's Link of the Day!
Also, be sure to check out and subscribe to the Lunartics Blog and the Lunarpages Newsletter !

Need Web Hosting Help? Check out the Lunarpages Web Hosting Wiki. It has tons of tips, tutorials and resources!
JeremyD
SleePy...
Jabba the Hutt
*****
Offline Offline

Posts: 733

SMF Team Member


WWW
« Reply #5 on: February 27, 2008, 08:20:08 PM »

MrPhill,

Just so you are not wrong:
PHP 4.2.0    April 22, 2002    Disabled register_globals by default
http://en.wikipedia.org/wiki/Php

People should also note that in php6 magic quotes are being removed. As well as the so called "safe" mode which does nothing to what it implies.

There is also another dirty method of getting the variables back without enabling register globals again
http://php.net/import-request-variables
You can do this method right in php, but its just a work around for disabled register globals basically.

I have in the past used a foreach loop to quickly set my variables that I needed with this
Code:
$get_vars = array('user_name', 'user_email');
foreach ($get_vars as $var)
     $$var = isset($_GET[$var]) ? $_GET[$var] : null;

Which same method could be applied to just get $_POST variables.

Really though I suggest actually cleaning variables if you are going to be setting them like this. For one it is a time saver and two, it ensures your scripts are a little more secure with the variables already cleaned up before they ever get used.
Such as
Code:
$member_id = (int) $_GET['member_id'];

Which in turns prevents people from putting non integer strings into the member_id request. There are other checks for many other things, and it is sometimes even better to create your own check if you need to lots of things or recursively (for multi-dimensional arrays).

Logged

MrPhil
Senior Moderator
Berserker Poster
*****
Offline Offline

Posts: 5811



« Reply #6 on: February 28, 2008, 03:10:44 PM »

Thanks for the correction regarding when PHP started discouraging register global variables. I have updated the posting.
Logged

Visit My Site

E-mail Me
  
-= From the ashes shall rise a sooty tern =-
mr.shiv
Newbie
*
Offline Offline

Posts: 4


« Reply #7 on: March 27, 2008, 07:36:15 AM »

Here's another quick-n-dirty TEMPORARY fix: use extract() on $_GET or $_POST. You'll run the risk of variable name collision, but if your code is written with the assumption that register_glogals is on, it should be using unique variable names anyway; and you can (& should) add switches to prevent name collision. Just add one line near the top of your script:

extract( $_POST, EXTR_SKIP );

There are security risks here as well, as usual with any user input. We're all validating all of our user inputs, right?
Logged
StonedRoses
Intergalactic Superstar
*****
Offline Offline

Posts: 128



WWW
« Reply #8 on: March 27, 2008, 01:50:56 PM »

So okay, the whole world has to change their script not to use UQS. That's fine for pages with a form posting to elsewhere.php, but what about when you want to end a php script and have it send resulting vars to another php page?

Without storing the data on file I'm not sure what to do. I can think of many bodged get arounds as well as some helpful examples provided. This sounds like it wont have a pretty solution... I think its time for a think and some tea.  Mmm Coffee

Thanks Guys
Logged

http://www.sebby.co.uk - Your online supplier of discount fashion jewellery, gemstone jewellery, ladies dress watches, giftware and more.
MrPhil
Senior Moderator
Berserker Poster
*****
Offline Offline

Posts: 5811



« Reply #9 on: March 27, 2008, 05:39:52 PM »

So okay, the whole world has to change their script not to use UQS. That's fine for pages with a form posting to elsewhere.php, but what about when you want to end a php script and have it send resulting vars to another php page?

Eh? Where did you get that idea? My only point was that you should explicitly import such variables from the UQS (or a form), using the $_GET array. Has someone documented that UQSs are somehow bad?
Logged

Visit My Site

E-mail Me
  
-= From the ashes shall rise a sooty tern =-
JeremyD
SleePy...
Jabba the Hutt
*****
Offline Offline

Posts: 733

SMF Team Member


WWW
« Reply #10 on: March 27, 2008, 07:16:08 PM »

I play my own rule of thumb that if you are using register globals, you have most likely not cleaned all of your inputs. If your lazy enough to try to get around register globals this long, then why wouldn't you be not lazy and clean your inputs?

I take the time while getting my inputs to clean them. Such as:
Code:
$this_int = (int) $_GET['number'];

So I have cleaned my input and I am not at all using the dirty one at all. Though mainly in my coding I use arrays as they are easier to pass between multiple functions, so Its usually an array that my cleaned variables are going into so I sometimes cheat and use a foreach loop with all expected inputs and their types.
Logged

StonedRoses
Intergalactic Superstar
*****
Offline Offline

Posts: 128



WWW
« Reply #11 on: March 28, 2008, 03:14:16 AM »

Perhaps either I've misunderstood, or I've explained my worry incorrectly.

After reading all of the above, I'm left with these understandings.

- Register Globals is turned off as a default in the interest of safety.
- Register Globals can still be used for now, but not when php 6 is out and installed by lunar.
- Register globals is only potentially unsafe if people have not validated and cleaned the values given from UQS.



If all of that is correct... Then there is no problem with a form sending data to a php file for processing, using _REQUEST to obtain that information. What happens when at the end of that processing where i might normally have a forward with UQS values for the next page to read?

For example:
Code:
echo "<meta http-equiv='refresh' content='0;URL=http://www.example.com/improbablywrong.php?quite=likely'>";

Normally in my code after that ide simply use quite.
Code:
$new_var_to_use = $quite;
« Last Edit: March 28, 2008, 04:51:38 AM by StonedRoses » Logged

http://www.sebby.co.uk - Your online supplier of discount fashion jewellery, gemstone jewellery, ladies dress watches, giftware and more.
MrPhil
Senior Moderator
Berserker Poster
*****
Offline Offline

Posts: 5811



« Reply #12 on: March 28, 2008, 06:22:51 PM »

Either $new_var_to_use = $_GET['quite']; or $new_var_to_use = $_REQUEST['quite']; should work. $_GET is used for UQS variables, and $_REQUEST includes everything in $_GET.
Logged

Visit My Site

E-mail Me
  
-= From the ashes shall rise a sooty tern =-
StonedRoses
Intergalactic Superstar
*****
Offline Offline

Posts: 128



WWW
« Reply #13 on: March 29, 2008, 05:59:32 AM »

That all makes sense in the mean time (before php6), im asking about what will be the occurance when php 6 arrives. If no values can be sent through the URL, will everyone be forced to send this information with hidden form feilds?

Perhaps im missing the whole point, but to me it seems that when php 6 arrives we will have to stop using values sent in a URL. Is this correct? if so, im trying to workout what is the best method to acheive the same results.

Thankyou.
Logged

http://www.sebby.co.uk - Your online supplier of discount fashion jewellery, gemstone jewellery, ladies dress watches, giftware and more.
scanman20
Senior Moderator
▄ber Jedi
*****
Offline Offline

Posts: 1543



WWW
« Reply #14 on: March 29, 2008, 07:00:15 AM »

You're misunderstanding the effect of eliminating register globals. You'll still be able to send variables in the URL querystring, you just won't be able to refernce them directly the way register globals allowed you to. You see the old way, with register globals on, if you had a URL like www.example.com/page.php?a=1, then in your script you could use the variable $a directly without having to do a thing. That's what register globals did. Without register globals you can still use www.example.com/page.php?a=1 but to use the variable in a script, you'd have to use $_GET['a'] or $_REQUEST['a'].

There are literally thousands of examples of why register globals is bad but here's a quick link to an easy to follow example of why: http://phpsecurity.wordpress.com/2007/11/07/evil-register-globals-on/
Logged

Even a broken clock is right twice a day.
NotOneBit.com
MCSE - MCSA - MCP
Pages: [1] 2   Go Up
  Print  
 
Jump to: