<<< Date Index >>>     <<< Thread Index >>>

PHP 5.2.0 session.save_path safe_mode and open_basedir bypass



-----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
- - Public: 08.12.2006
SecurityAlert Id: 43
CVE: CVE-2006-6383
SecurityRisk: High
Affected Software: PHP 5.2.0
Advisory URL: http://securityreason.com/achievement_securityalert/43
Vendor: http://www.php.net

- --- 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 

3. 
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 ";".

- --- 2. How to fix ---
http://cvs.php.net/viewcvs.cgi/php-src/NEWS

- --- 3. Greets ---

For: sp3x
and
l5x, p_e_a, lorddav, pi3

- --- 4. Contact ---
Author: SecurityReason.Com [ Maksymilian Arciemowicz ( cXIb8O3 ) ]
Email: cxib [at] securityreason [dot] com
GPG: http://securityreason.com/key/Arciemowicz.Maksymilian.gpg

Regards 
SecurityReason

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

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