From:             roel at qsp dot nl
Operating system: FreeBSD 6
PHP version:      5.1.6
PHP Bug Type:     Session related
Bug description:  Extra options in session.save_path cause verification on 
update to fail

Description:
------------
Introduction
------------

The file based session handler uses the session.save_path ini variable to
determine where to write it's session files.

However, it also attempts to parse two other bits of information out of
session.save_path, iff session.save_path contains one or two semi-colons.
The format is:

"[x;[y;]]pathname"

Where both x and y are optional and x is a directory hashing depth for
session files (defaults to 0) and y is the create mode for new session
files, defaults to 0700.

Whenever session.save_path is updated, a verification function is called.
For this variable, this is the funtion "static
PHP_INI_MH(OnUpdateSaveDir)" contained in ext/session/session.c.

There is no verification in this function if PHP is running in regular
mode. However, when in safe-mode, this function performs two
verifications. First, it attempts to check ownership of the directory, and
secondly, it does a php_check_open_basedir() on the path supplied.

Problem description
-------------------

In this function, OnUpdateSaveDir() in ext/session/session.c, no attempt
is made to recognize and take out the optional parameters contained in the
supplied new session.save_path value.

So, when setting session.save_path to "0;0707;/whatever", PHP will supply
php_checkuid() and php_check_open_basedir with the entire string, not just
with /whatever. This causes the check to fail.

Patch
------

The following patch should be applied to ext/session/session.c to fix this
problem:

*** ext/session/session.orig.c  Fri Sep 29 11:35:05 2006
--- ext/session/session.c       Fri Sep 29 12:39:26 2006
***************
*** 133,145 ****
  
  static PHP_INI_MH(OnUpdateSaveDir)
  {
        /* Only do the safemode/open_basedir check at runtime */
        if (stage == PHP_INI_STAGE_RUNTIME) {
!               if (PG(safe_mode) && (!php_checkuid(new_value, NULL,
CHECKUID_ALLOW_ONLY_DIR))) {
                        return FAILURE;
                }
  
!               if (php_check_open_basedir(new_value TSRMLS_CC)) {
                        return FAILURE;
                }
        }
--- 133,150 ----
  
  static PHP_INI_MH(OnUpdateSaveDir)
  {
+       char *p, *q;
+       int i;
        /* Only do the safemode/open_basedir check at runtime */
        if (stage == PHP_INI_STAGE_RUNTIME) {
!               /* Parse out optional hash level & file mode */
!               for (i=0, q=new_value; i<2 && (p=strchr(q, ';'))!=NULL;
q=p+1, i++);
! 
!               if (PG(safe_mode) && (!php_checkuid(q, NULL,
CHECKUID_ALLOW_ONLY_DIR))) {
                        return FAILURE;
                }
  
!               if (php_check_open_basedir(q TSRMLS_CC)) {
                        return FAILURE;
                }
        }

Remarks
--------

Both parameters are, at least for the most part, undocumented. It would
not be a bad idea to update
the session.save_path description with information about these two
variables.

Submitted: 29/9/2006
Patch author: Roel Bouwman <[EMAIL PROTECTED]>

Reproduce code:
---------------
<?php
 /* Preconditions:
  *  - server running in safe mode
  *  - /whatever and this script owned by samed user.
  */

  ini_set("session.save_path","0;0707;/whatever");
?>

Expected result:
----------------
1. PHP checking wether "/whatever" is owned by script owner.
2. PHP performing basepath check for "/whatever"
3. session.save_path set to "0;0707;/whatever".

Actual result:
--------------
PHP will produce an error claiming that it cannot open the save_path
directory as the uid check is performed not just for /whatever, but for
the entire string.

Result is that session.save_path will not be modified.

-- 
Edit bug report at http://bugs.php.net/?id=38993&edit=1
-- 
Try a CVS snapshot (PHP 4.4): 
http://bugs.php.net/fix.php?id=38993&r=trysnapshot44
Try a CVS snapshot (PHP 5.2): 
http://bugs.php.net/fix.php?id=38993&r=trysnapshot52
Try a CVS snapshot (PHP 6.0): 
http://bugs.php.net/fix.php?id=38993&r=trysnapshot60
Fixed in CVS:                 http://bugs.php.net/fix.php?id=38993&r=fixedcvs
Fixed in release:             
http://bugs.php.net/fix.php?id=38993&r=alreadyfixed
Need backtrace:               http://bugs.php.net/fix.php?id=38993&r=needtrace
Need Reproduce Script:        http://bugs.php.net/fix.php?id=38993&r=needscript
Try newer version:            http://bugs.php.net/fix.php?id=38993&r=oldversion
Not developer issue:          http://bugs.php.net/fix.php?id=38993&r=support
Expected behavior:            http://bugs.php.net/fix.php?id=38993&r=notwrong
Not enough info:              
http://bugs.php.net/fix.php?id=38993&r=notenoughinfo
Submitted twice:              
http://bugs.php.net/fix.php?id=38993&r=submittedtwice
register_globals:             http://bugs.php.net/fix.php?id=38993&r=globals
PHP 3 support discontinued:   http://bugs.php.net/fix.php?id=38993&r=php3
Daylight Savings:             http://bugs.php.net/fix.php?id=38993&r=dst
IIS Stability:                http://bugs.php.net/fix.php?id=38993&r=isapi
Install GNU Sed:              http://bugs.php.net/fix.php?id=38993&r=gnused
Floating point limitations:   http://bugs.php.net/fix.php?id=38993&r=float
No Zend Extensions:           http://bugs.php.net/fix.php?id=38993&r=nozend
MySQL Configuration Error:    http://bugs.php.net/fix.php?id=38993&r=mysqlcfg

Reply via email to