Advisory Text :
-----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-----