tony2001 Tue Apr 10 22:30:07 2007 UTC
Modified files: (Branch: PHP_5_2)
/php-src NEWS
/php-src/main fopen_wrappers.c
Log:
fix #40931 (open_basedir bypass via symlink and move_uploaded_file())
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.634&r2=1.2027.2.547.2.635&diff_format=u
Index: php-src/NEWS
diff -u php-src/NEWS:1.2027.2.547.2.634 php-src/NEWS:1.2027.2.547.2.635
--- php-src/NEWS:1.2027.2.547.2.634 Tue Apr 10 20:28:48 2007
+++ php-src/NEWS Tue Apr 10 22:30:07 2007
@@ -57,6 +57,8 @@
- Fixed bug #40998 (long session array keys are truncated). (Tony)
- Implement feature request #40947, allow a single filter as argument
for filter_var_array (Pierre)
+- Fixed bug #40931 (open_basedir bypass via symlink and move_uploaded_file()).
+ (Tony)
- Fixed bug #40921 (php_default_post_reader crashes when post_max_size is
exceeded). (trickie at gmail dot com, Ilia)
- Fixed bug #40915 (addcslashes unexpected behavior with binary input). (Tony)
http://cvs.php.net/viewvc.cgi/php-src/main/fopen_wrappers.c?r1=1.175.2.3.2.9&r2=1.175.2.3.2.10&diff_format=u
Index: php-src/main/fopen_wrappers.c
diff -u php-src/main/fopen_wrappers.c:1.175.2.3.2.9
php-src/main/fopen_wrappers.c:1.175.2.3.2.10
--- php-src/main/fopen_wrappers.c:1.175.2.3.2.9 Sat Feb 24 02:17:28 2007
+++ php-src/main/fopen_wrappers.c Tue Apr 10 22:30:07 2007
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: fopen_wrappers.c,v 1.175.2.3.2.9 2007/02/24 02:17:28 helly Exp $ */
+/* $Id: fopen_wrappers.c,v 1.175.2.3.2.10 2007/04/10 22:30:07 tony2001 Exp $ */
/* {{{ includes
*/
@@ -90,8 +90,12 @@
char resolved_name[MAXPATHLEN];
char resolved_basedir[MAXPATHLEN];
char local_open_basedir[MAXPATHLEN];
+ char path_tmp[MAXPATHLEN];
+ char *path_file;
int resolved_basedir_len;
int resolved_name_len;
+ int path_len;
+ int nesting_level = 0;
/* Special case basedir==".": Use script-directory */
if (strcmp(basedir, ".") || !VCWD_GETCWD(local_open_basedir,
MAXPATHLEN)) {
@@ -99,8 +103,64 @@
strlcpy(local_open_basedir, basedir,
sizeof(local_open_basedir));
}
- /* Resolve the real path into resolved_name */
- if ((expand_filepath(path, resolved_name TSRMLS_CC) != NULL) &&
(expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL)) {
+ path_len = strlen(path);
+ if (path_len > (MAXPATHLEN - 1)) {
+ /* empty and too long paths are invalid */
+ return -1;
+ }
+
+ /* normalize and expand path */
+ if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) {
+ return -1;
+ }
+
+ path_len = strlen(resolved_name);
+ memcpy(path_tmp, resolved_name, path_len + 1); /* safe */
+
+ while (VCWD_REALPATH(path_tmp, resolved_name) == NULL) {
+#ifdef HAVE_SYMLINK
+ if (nesting_level == 0) {
+ int ret;
+ char buf[MAXPATHLEN];
+
+ ret = readlink(path_tmp, buf, MAXPATHLEN - 1);
+ if (ret < 0) {
+ /* not a broken symlink, move along.. */
+ } else {
+ /* put the real path into the path buffer */
+ memcpy(path_tmp, buf, ret);
+ path_tmp[ret] = '\0';
+ }
+ }
+#endif
+
+#if defined(PHP_WIN32) || defined(NETWARE)
+ path_file = strrchr(path_tmp, DEFAULT_SLASH);
+ if (!path_file) {
+ path_file = strrchr(path_tmp, '/');
+ }
+#else
+ path_file = strrchr(path_tmp, DEFAULT_SLASH);
+#endif
+ if (!path_file) {
+ /* none of the path components exist. definitely not in
open_basedir.. */
+ return -1;
+ } else {
+ path_len = path_file - path_tmp + 1;
+#if defined(PHP_WIN32) || defined(NETWARE)
+ if (path_len > 1 && path_tmp[path_len - 2] == ':') {
+ /* this is c:\, */
+ path_tmp[path_len] = '\0';
+ }
+#else
+ path_tmp[path_len - 1] = '\0';
+#endif
+ }
+ nesting_level++;
+ }
+
+ /* Resolve open_basedir to resolved_basedir */
+ if (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) !=
NULL) {
/* Handler for basedirs that end with a / */
resolved_basedir_len = strlen(resolved_basedir);
if (basedir[strlen(basedir) - 1] == PHP_DIR_SEPARATOR) {
@@ -110,7 +170,7 @@
}
}
- if (path[strlen(path)-1] == PHP_DIR_SEPARATOR) {
+ if (path_tmp[path_len - 1] == PHP_DIR_SEPARATOR) {
resolved_name_len = strlen(resolved_name);
if (resolved_name[resolved_name_len - 1] !=
PHP_DIR_SEPARATOR) {
resolved_name[resolved_name_len] =
PHP_DIR_SEPARATOR;
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php