Predefined Variables

PHP provides a large number of predefined variables to any script
which it runs. Many of these variables, however, cannot be fully
documented as they are dependent upon which server is running, the
version and setup of the server, and other factors. Some of these
variables will not be available when PHP is run on the
command line.
For a listing of these variables, please see the section on
Reserved Predefined Variables.

PHP also provides an additional set of predefined arrays
containing variables from the web server (if applicable), the
environment, and user input. These arrays are rather special
in that they are automatically global - i.e., automatically
available in every scope. For this reason, they are often known as
"superglobals". (There is no mechanism in PHP for
user-defined superglobals.) The superglobals can be found
here;
however, for a listing of their contents and further discussion on
PHP predefined variables and their natures, please see the section
Reserved Predefined Variables.

Note:

Prior to PHP 5.4, the old way of retrieving information
related to the HTTP request with the HTTP_*_VARS
variables instead of superglobals was still possible.
This feature could be disabled as of PHP 5.0.0 with the
register_long_arrays
directive.

User Contributed Notes 20 notes

I haven't found it anywhere else in the manual, so I'll make a note of it here - PHP will automatically replace any dots ('.') in an incoming variable name with underscores ('_'). So if you have dots in your incoming variables, e.g.:

example.com/page.php?chuck.norris=nevercries

you can not reference them by the name used in the URI://INCORRECTecho $_GET['chuck.norris'];

I have this function in my main files, it allows for easier SEO for some pages without having to rely on .htaccess and mod_rewrite for some things.<?phpfunction long_to_GET(){/** * This function converts info.php/a/1/b/2/c?d=4 TO * Array ( [d] => 4 [a] => 1 [b] => 2 [c] => ) **/if(isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] != ''){//Split it out.$tmp = explode('/',$_SERVER['PATH_INFO']);//Remove first empty itemunset($tmp[0]);//Loop through and apend it into the $_GET superglobal.for($i=1;$i<=count($tmp);$i+=2){ $_GET[$tmp[$i]] = $tmp[$i+1];} } }?>

Its probably not the most efficient, but it does the job rather nicely.

# this is a follow-up to kasey at cornerspeed's 14-Jun-2004 08:33 post and debabratak at softhome's 14-Mar-2003 12:59 post, minus sessions but including a safety mechanism to block unwanted variables...

# if you are like me and do not want to have to type $_POST[some_var] to get to all your passed variable data, you can safely convert all the data to the variable names (so it is like old style php) by using a pre-defined allowed arg names list like this;

If you're running PHP as a shell script, and you want to use the argv and argc arrays to get command-line arguments, make sure you have register_argc_argv = on. If you're using the 'optimized' php.ini, this defaults to off.

It seems that when you wish to export a varible, you can do it as return $varible, return an array(), or globalise it. If you return something, information for that varible can only travel one way when the script is running, and that is out of the function.

function fn() { $varible = "something";

return $variable;}

echo fn();OR$newvariable = fn();

Although if global was used, it creates a pointer to a varible, whether it existed or not, and makes whatever is created in the function linked to that global pointer. So if the pointer was global $varible, and then you set a value to $varible, it would then be accessible in the global scope. But then what if you later on in the script redefine that global to equal something else. This means that whatever is put into the global array, the information that is set in the pointer, can be set at any point (overiden). Here is an example that might make this a little clearer:

Basically when accessing the global array, you can set it refer to something already defined or set it to something, (a pointer) such as varible you plan to create in the function, and later possibly over ride the pointer with something else.

On the subject of permalinks and queries:Say, you use an inexpensive subdomain of (e.g.) www.nice.net, thus www.very.nice.net, and that the domain owner has simply placed a frame at this particular location, linking to the actual address (ugly and subject-to-change) of your site.Consequently, the actual site URI and various associated hashes and query strings are not immediately visible to the user. Sometimes this is useful, but it also makes bookmarking/permalinking impossible (the browser will only bookmark the static address in the top frame).However, as far as the query strings go, there is workaround. Instead of providing users with permalinks to the actual URI (e.g. prtcl://weird.and.ugly/~very/ugly.php?stuff=here; may even be subject to change), I provide them with this: prtcl://www.very.nice.net?stuff=here.

In brief, I then use the following code to re-populate the $_GET array:

If the actual host address is ever changed, users entering the frame (with the nicer address) will be using the new (and ugly) URI, but this way the old query strings will be available to the new address also. The users will never again be bothered by you moving to another neighborhood.

Your method, though clever, won't work. The problem is the way that PHP handles function scope. If $evalcode contains a function declaration, and runs that function, the "unset"s will be effectively useless inside the body of that function.

Another problem is that the "global" directive will always grant access to global variables. Try this one:

<?php$evalcode='global $a;$a = "compromised";';?>

$a will of course be changed at the global level. I don't know if it's supposed to work this way, but on my system (PHP 4.3.4) you can do the same to any superglobal by importing it using "global".

As far as I can tell, there is NO way to execute potentially unsafe code without a lot of risk. With the sloppy way that PHP deals with function scope etc., there isn't much hope that it ever will be. What we'd need is (at least): - a way to disable the "global" directive (restrictive eval). - a way to shut off any write-access to superglobals within untrusted functions.

The first wouldn't be too hard to implement. The second, on the other hand, is practically impossible IMHO.

- Security Issue and workaround - If You use "eval()" to execute code stored in a database or elsewhere, you might find this tip useful.

Issue:By default, all superglobals are known in every function. Thus, if you eval database- or dynamically generated code (let's call it "potentially unsafe code"), it can use _all_ the values stored in _any_ superglobal.

Workaround:Whenever you want to hide superglobals from use in evaluated code, wrap that eval() in an own function within which you unset() all the superglobals. The superglobals are not deleted by php in all scopes - just within that function. eg:

I have a few points to note to (debabratak at softhome dot net). Firstly, extracting all your variables from the global variable arrays is rather cumbersome and possibly unsafe. This causes longer run times, and wastes more memory. Then, your script is starting the session before it parses the superglobals. Bad things can happen because of this:

// VARIABLES ARE COMPROMISED!// DO NOT USE $secret_access !// USE $_SESSION["secret_access"] instead !!!

?>

Secondly, I would like to point out the fact that all $_POST, $_GET, and $_COOKIE variables are intrinsically unsafe anyway. Users can create their own scripts in the language of their choosing (PHP, ASP, JSP, etc.) that generate those headers to send to your PHP program via socket connections. PHP cannot determine that these headers are any less valid than the ones sent by a web browser, so it parses them and places them in the $_POST, $_GET, or $_COOKIE variables.

The best practice is to use $_SESSION variables to validate the user before making any decisions based on form data. e.g.:

Session variables are orders of magnitude harder to compromise than POST, GET, and COOKIE data, since the server keeps track of session id's, and the session id is unique to each client and somewhat randomly generated. If security is an ultimate concern, then you need to use SSL in case your traffic can be sniffed (since the session cookie is passed plain text to the client).

In summary, extracting out all the superglobals to normal variable names is not a good idea for reasons of security and ambiguity, not to mention wasted CPU cycles. For private applications (ones that you don't want just anyone to be able to access), the only ways you can prevent malicious access is to 1) use sessions to ensure that the user is valid (for that page), and 2) use SSL-encryption to prevent session-hijacking.

Kasey

in reply to:-------------------------------------------------------------- debabratak at softhome dot net14-Mar-2003 12:59After having register_globals = off, I am using the following piece of code to get all the variables created for me. I have put this code in a separate file and just make it require_once() on top of every page.

In consequence, if you manually attempt to add keys to the superglobals, those keys *aren't* automatically superglobal. The above example isn't very sensible, of course, but this can be a huge gotcha if you're juggling user data between functions and you're unwittingly being forced to work inside a function (e.g. via PHP include in TYPO3).

Unfortunately, global $_REQUEST['id'] won't save you, either - it causes a parse error - nor will a global $_REQUEST change anything after you've set the keys... consequently making it hard to conviniently 'hack' outdated scripts by making them believe they're still running in a different environment.

use a preg_replace ( pattern: |\;[^\;]*$i[^\;]*\;|Uis, replacement: ";", where $i is the name of any function/variable you wish to prevent access to.) on the code-to-be-evaled. ideas are "global", "fopen", "mysql_connect", etc. You know, anything that you wouldn't want to give a hyperactive 13 year old access to.

There is one way to safely execute PHP code files without running the risk of compromising your own code. A prior note pointed out that the code being evaluated would still have access to globals using the global keyword. While this is a valid point, there's one other approach to be looked at - one which actually gives you much more ability than just unsetting some variable references. It's known as code parsing.

The specifics would be different and much more complex in a deployed site, but here's an extremely strip-down example of how to restrict access to global variables:

Of course, that's just a rudimentary example, and a deployment version would have much more checking involved, but parsing the file before you eval it lets you remove any code you don't want to let run, thus making it as safe as your parsing rules.