Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:15342
HistoryDec 09, 2006 - 12:00 a.m.

PHP 5.2.0 session.save_path safe_mode and open_basedir bypass

2006-12-0900:00:00
vulners.com
102

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

[PHP 5.2.0 session.save_path safe_mode and open_basedir bypass]

Author: Maksymilian Arciemowicz (SecurityReason)
Date:

    • Written: 02.10.2006
  • — 0.Description —
    PHP is an HTML-embedded scripting language. Much of its syntax is borrowed from C, Java and Perl with a couple of
    unique PHP-specific features thrown in. The goal of the language is to allow web developers to write dynamically
    generated pages quickly.

A nice introduction to PHP by Stig Sather Bakken can be found at http://www.zend.com/zend/art/intro.php on the Zend
website. Also, much of the PHP Conference Material is freely available.

Session support in PHP consists of a way to preserve certain data across subsequent accesses. This enables you to
build more customized applications and increase the appeal of your web site.

A visitor accessing your web site is assigned a unique id, the so-called session id. This is either stored in a cookie
on the user side or is propagated in the URL.

session.save_path defines the argument which is passed to the save handler. If you choose the default files handler,
this is the path where the files are created. Defaults to /tmp. See also session_save_path().

There is an optional N argument to this directive that determines the number of directory levels your session files
will be spread around in. For example, setting to '5;/tmp' may end up creating a session file and location like
/tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174If . In order to use N you must create all of these directories
before use. A small shell script exists in ext/session to do this, it's called mod_files.sh. Also note that if N is
used and greater than 0 then automatic garbage collection will not be performed, see a copy of php.ini for further
information. Also, if you use N, be sure to surround session.save_path in "quotes" because the separator (;) is also
used for comments in php.ini.

  • — 1. session.save_path safe mode and open basedir bypass —
    session.save_path can be set in ini_set(), session_save_path() function. In session.save_path there must be path where
    you will save yours tmp file. But syntax for session.save_path can be:

[/PATH]

OR

[N;/PATH]

N - can be a string.

EXAMPLES:

  1. session_save_path("/DIR/WHERE/YOU/HAVE/ACCESS")
  2. session_save_path("5;/DIR/WHERE/YOU/HAVE/ACCESS")

and

  1. session_save_path("/DIR/WHERE/YOU/DONT/HAVE/ACCESS\0;/DIR/WHERE/YOU/HAVE/ACCESS")
  • -1477-1493— Code from PHP520 ext/session/session.c [START]
    PHP_FUNCTION(session_save_path)
    {
    zval **p_name;
    int ac = ZEND_NUM_ARGS();
    char *old;

      if (ac < 0 || ac > 1 || zend_get_parameters_ex(ac, &p_name) == FAILURE)
              WRONG_PARAM_COUNT;
      
      old = estrdup(PS(save_path));
    
      if (ac == 1) {
              convert_to_string_ex(p_name);
              zend_alter_ini_entry("session.save_path", sizeof("session.save_path"), Z_STRVAL_PP(p_name),
    

Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
}

    RETVAL_STRING(old, 0);

}

  • -1477-1493— Code from PHP520 ext/session/session.c [END]

Values are set to hash_memory (but before that, safe_mode and open_basedir check this value).
And if you are starting session (for example session_start()), that value from session.save_path is checked by
function PS_OPEN_FUNC(files).

  • -242-300— Code from PHP520 ext/session/mod_files.c [START]
    PS_OPEN_FUNC(files)
    {
    ps_files *data;
    const char *p, *last;
    const char *argv[3];
    int argc = 0;
    size_t dirdepth = 0;
    int filemode = 0600;

      if (*save_path == '\0') {
              /* if save path is an empty string, determine the temporary dir */
              save_path = php_get_temporary_directory();
      }
      
      /* split up input parameter */
      last = save_path;
      p = strchr(save_path, ';');
      while (p) {
              argv[argc++] = last;
              last = ++p;
              p = strchr(p, ';');
              if (argc > 1) break;
      }
      argv[argc++] = last;
    
      if (argc > 1) {
              errno = 0;
              dirdepth = (size_t) strtol(argv[0], NULL, 10);
              if (errno == ERANGE) {
                      php_error(E_WARNING, 
                                      "The first parameter in session.save_path is invalid");
                      return FAILURE;
              }
      }
      
      if (argc > 2) {
              errno = 0;
              filemode = strtol(argv[1], NULL, 8);
              if (errno == ERANGE || filemode < 0 || filemode > 07777) {
                      php_error(E_WARNING, 
                                      "The second parameter in session.save_path is invalid");
                      return FAILURE;
              }
      }
      save_path = argv[argc - 1];
    
      data = emalloc(sizeof(*data));
      memset(data, 0, sizeof(*data));
      
      data->fd = -1;
      data->dirdepth = dirdepth;
      data->filemode = filemode;
      data->basedir_len = strlen(save_path);
      data->basedir = estrndup(save_path, data->basedir_len);
      
      PS_SET_MOD_DATA(data);
      
      return SUCCESS;
    

}

  • -242-300— Code from PHP520 ext/session/mod_files.c [END]

Because in session.save_path there is a NULL byte before ";", strchr() doesn't see ";" and path is
/DIR/WHERE/YOU/DONT/HAVE/ACCESS.

Problem exists because safe_mode and open_basedir check what is after ;. And it is needed to set correct path after
";".

For: sp3x
and
l5x, p_e_a, lorddav, pi3

Regards
SecurityReason

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (FreeBSD)

iD8DBQFFedKL3Ke13X/fTO4RAms1AKCTSc8CNZmHWhXvOdjtTBcIgdHTuwCgkvrz
9KnewH0rOVFfmPRx2f1x5W4=
=YAP9
-----END PGP SIGNATURE-----