If you have register_globals on (I will be happy when PHP6 does away with that) and you do not have base_url set then someone can sneak in XSS. Fixing that is easy...

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

chx’s picture

FileSize
339 bytes
chx’s picture

FileSize
561 bytes

Well, this I found not really adequate. There are other places where I would need to think whether they can do havoc or. Instead of thinking...

chx’s picture

FileSize
431 bytes
webchick’s picture

Status: Reviewed & tested by the community » Needs review

Nope, sorry chx. :(

With this patch applied, I am unable to create UID 1:

* You must enter a username.
* You must enter an e-mail address.

Even when they are both clearly entered.

webchick’s picture

Status: Needs review » Needs work
chx’s picture

Status: Needs work » Needs review
FileSize
660 bytes
chx’s picture

thanks webchick for helping me on this issue.

webchick’s picture

Status: Needs review » Reviewed & tested by the community

I applied the patch and tested several forms, all looks good now. +1 and RTBC.

chx’s picture

FileSize
717 bytes
markus_petrux’s picture

If you run a "register globals off" emmulator from a place where any expected global is known, you could do something like this:

http://ca.php.net/manual/en/faq.misc.php#53961

Well, you need to adapt the contents of $knownglobals and remove the stuff related to $_SESSION. Probably at this point in bootstrap time session_start() has not been run yet.

markus_petrux’s picture

Maybe something like this?

if( (bool)@ini_get('register_globals') )
{
	$superglobals = array(&$_ENV, &$_GET, &$_POST, &$_COOKIE, &$_FILES, &$_SERVER);
	$protected = array(
		//
		// PHP superglobals:
		//
		'_ENV', '_GET', '_POST', '_COOKIE', '_FILES', '_SERVER', '_SESSION', '_REQUEST',

		//
		// Global variables used by this code snippet:
		//
		'superglobals', 'protected', 'superglobal', 'global', 'void',

		//
		// Known globals defined before this code snippet is reached.
		//
		'anything here ???',
	);
	foreach( $superglobals as $superglobal )
	{
		foreach( $superglobal as $global => $void )
		{
			if( !in_array($global, $protected) )
			{
				unset($GLOBALS[$global]);
			}
		}
	}
	unset($superglobals, $protected, $superglobal, $global, $void);
}

Note this one uses & to populate $superglobals (avoids a copy of the superglobals and works in PHP4 and PHP5).

markus_petrux’s picture

This is using Drupal coding guidelines and removed some stuff, not really necessary when running this code from within a function.

if ((bool)@ini_get('register_globals')) {
  $superglobals = array(&$_ENV, &$_GET, &$_POST, &$_COOKIE, &$_FILES, &$_SERVER);
  $protected = array(
    // PHP superglobals:
    '_ENV', '_GET', '_POST', '_COOKIE', '_FILES', '_SERVER', '_REQUEST',
    // Known globals defined before this code snippet is reached.
    'anything here ???',
  );
  foreach ($superglobals as $superglobal) {
    foreach ($superglobal as $global => $void) {
      if (!in_array($global, $protected)) {
        unset($GLOBALS[$global]);
      }
    }
  }
}
Uwe Hermann’s picture

Status: Reviewed & tested by the community » Needs review

Looks like this needs some more discussion.

chx’s picture

Priority: Critical » Minor
Status: Needs review » Reviewed & tested by the community

Some PHP versions apparently has _GLOBALS["GLOBAL']. That needs protection too. And who knows what. I oppose markus' approach. My code works as it unsets any all-lowercase variable which happens to be the only variables we need to unset.

chx’s picture

Priority: Minor » Critical

This is not minor.

markus_petrux’s picture

Status: Reviewed & tested by the community » Needs work

// we only allow uppercase letters and underscore

This code is going to unset $access_check defined on top of update.php.

chx’s picture

Assigned: chx » Unassigned
Status: Needs work » Active

then submit a patch. i unassigned from myself.

markus_petrux’s picture

What about using a constant in place of $access_check ?

markus_petrux’s picture

Also, what about moving the "register globals off emmulator" on top of bootstrap.inc ? ie. off any other function. At that there shouldn't be any other globals than those provided by PHP itself.

Then, it doesn't matter yours or mine code snippet to do the job.

Agree?

markus_petrux’s picture

Last, but not least. What about doing fix_gpc_magic() here as well?

This is actually invoked from common.inc::_drupal_bootstrap_full() at DRUPAL_BOOTSTRAP_FULL time. This is not done when page cache is enabled. I think that could be a problem, depending on what's being done in init/exit hooks and things like that?

chx’s picture

Status: Active » Reviewed & tested by the community
FileSize
755 bytes

Markus, we do not put code in global scope anymore. However, you were close to this version and thanks for the access_check finding.

markus_petrux’s picture

Status: Reviewed & tested by the community » Needs work

Oops! '_REQUEST' needs to be added to $allowed ?

markus_petrux’s picture

if fix_gpc_magic() was called here, it would cover the case when page cache is enabled?

chx’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
772 bytes

Yes request is needed. No fix_gpc_magic is not needed here because it'd be too early.

eaton’s picture

FileSize
796 bytes

Two minor bugs in the patch kept me from testing. Here's a rerolled version (files =>1, open bracket on line 141)

markus_petrux’s picture

Looks good. I have opened another issue to discuss about fix_gpc_mafic(). :-/

Dries’s picture

Can't we unset $base_url just before settings.php is loaded? (I don't like the proposed solution.)

Does this need fixing in 4.6? If not, why not?

I don't unserstand why we fix this in conf_init() and not in a separate function similar to fix_gpc_magic().

chx’s picture

The whole issue arose when Steven made $base_url optional, so 4.6 is not a problem. The patch in #1 does just the single unset, yes. But then I thought "maybe there are uninit'd globals in Drupal" and started grepping around. Then lost heart. There are a ton of globals and I did not want to check each and every of them for init. Of course, I can move the unsetter to another function, sure.

chx’s picture

FileSize
1.06 KB

Moved to a separate function.

killes@www.drop.org’s picture

Status: Reviewed & tested by the community » Fixed

applied

Anonymous’s picture

Status: Fixed » Closed (fixed)