On Thu, 20 Jun 2002, C. McCohy wrote: > it's going about the safe_mode_exec_dir configuration directive, which > allows php script to execute an external command, which is located in > specified directory only. This is able only in safe mode, not in "normal > mode" .. > > What do you think, would it be nice to have this feature outside the > safe mode? I think it would be _very_ nice for some security reasons ...
OK, no answer is better than the negative one ;-))) The patch follows ... I've tested it many times, should work fine ... It provides the "exec_dir" configuration directive which allows user to execute external commands located only in specified directory, if safe mode is disabled. If safe mode is enabled, this directive is forgotten and safe_mode_exec_dir will be used instead. So if you think it is a good idea, add it ... -- Bye .. C. McCohy The killings will not stop until you Karel Roden ----------------------------------------------------------------------- diff -uar php-4.2.1.orig/ext/standard/exec.c php-4.2.1/ext/standard/exec.c --- php-4.2.1.orig/ext/standard/exec.c Thu Apr 25 16:02:51 2002 +++ php-4.2.1/ext/standard/exec.c Fri Jun 21 08:48:51 2002 @@ -111,6 +111,50 @@ return -1; } + } else if (PG(exec_dir)) { + /* _NO_ safe mode with exec_dir enabled */ + + d = emalloc(strlen(PG(exec_dir)) + strlen(cmd) + 2); + c = strchr(cmd, ' '); + if (c) *c = '\0'; + if (strstr(cmd, "..")) { + php_error(E_WARNING, "No '..' components allowed in path"); + efree(d); + efree(buf); + return -1; + } + b = strrchr(cmd, PHP_DIR_SEPARATOR); + strcpy(d, PG(exec_dir)); + if (b) { + strcat(d, b); + } else { + sprintf(d, "%s%c%s", d, PHP_DIR_SEPARATOR, cmd); + } + if (c) { + *c = ' '; + strcat(d, c); + } + tmp = php_escape_shell_cmd(d); + efree(d); + d = tmp; + +#if PHP_SIGCHILD + sig_handler = signal (SIGCHLD, SIG_DFL); +#endif +#ifdef PHP_WIN32 + fp = VCWD_POPEN(d, "rb"); +#else + fp = VCWD_POPEN(d, "r"); +#endif + if (!fp) { + php_error(E_WARNING, "Unable to fork [%s]", d); + efree(d); + efree(buf); +#if PHP_SIGCHILD + signal (SIGCHLD, sig_handler); +#endif + return -1; + } } else { /* not safe_mode */ #if PHP_SIGCHILD sig_handler = signal (SIGCHLD, SIG_DFL); @@ -122,6 +166,7 @@ #endif if (!fp) { php_error(E_WARNING, "Unable to fork [%s]", cmd); + efree(d); efree(buf); #if PHP_SIGCHILD signal (SIGCHLD, sig_handler); @@ -129,6 +174,7 @@ return -1; } } + buf[0] = '\0'; if (type==2) { if (Z_TYPE_P(array) != IS_ARRAY) { @@ -453,13 +499,48 @@ } convert_to_string_ex(cmd); + + if(PG(exec_dir)) { + char *d, *b; + b = strchr(Z_STRVAL_PP(cmd), ' '); + if (!b) { + b = strrchr(Z_STRVAL_PP(cmd), PHP_DIR_SEPARATOR); + } else { + char *c; + c = Z_STRVAL_PP(cmd); + while ((*b != PHP_DIR_SEPARATOR) && (b != c)) { + b--; + } + if (b == c) { + b = NULL; + } + } + + d = emalloc(Z_STRLEN_PP(cmd) + strlen(PG(exec_dir)) + 2); + if (b) { + strcpy(d, PG(exec_dir)); + strcat(d, b); + } else { + sprintf(d, "%s%c%s", PG(exec_dir), PHP_DIR_SEPARATOR, +Z_STRVAL_PP(cmd)); + } + #ifdef PHP_WIN32 - if ((in=VCWD_POPEN(Z_STRVAL_PP(cmd), "rt"))==NULL) { + if ((in=VCWD_POPEN(d, "rt"))==NULL) { #else - if ((in=VCWD_POPEN(Z_STRVAL_PP(cmd), "r"))==NULL) { + if ((in=VCWD_POPEN(d, "r"))==NULL) { #endif - php_error(E_WARNING, "Unable to execute '%s'", Z_STRVAL_PP(cmd)); - RETURN_FALSE; + php_error(E_WARNING, "Unable to execute '%s'", d); + RETURN_FALSE; + } + } else { +#ifdef PHP_WIN32 + if ((in=VCWD_POPEN(Z_STRVAL_PP(cmd), "rt"))==NULL) { +#else + if ((in=VCWD_POPEN(Z_STRVAL_PP(cmd), "r"))==NULL) { +#endif + php_error(E_WARNING, "Unable to execute '%s'", +Z_STRVAL_PP(cmd)); + RETURN_FALSE; + } } allocated_space = EXEC_INPUT_BUF; ret = (char *) emalloc(allocated_space); diff -uar php-4.2.1.orig/ext/standard/file.c php-4.2.1/ext/standard/file.c --- php-4.2.1.orig/ext/standard/file.c Sun May 12 18:08:31 2002 +++ php-4.2.1/ext/standard/file.c Fri Jun 21 08:25:52 2002 @@ -722,6 +722,34 @@ php_error(E_WARNING, "popen(\"%s\", \"%s\") - %s", buf, p, strerror(errno)); RETURN_FALSE; } + } else if (PG(exec_dir)) { + b = strchr(Z_STRVAL_PP(arg1), ' '); + if (!b) { + b = strrchr(Z_STRVAL_PP(arg1), PHP_DIR_SEPARATOR); + } else { + char *c; + c = Z_STRVAL_PP(arg1); + while ((*b != PHP_DIR_SEPARATOR) && (b != c)) { + b--; + } + if (b == c) { + b = NULL; + } + } + if (b) { + snprintf(buf, sizeof(buf), "%s%s", PG(exec_dir), b); + } else { + snprintf(buf, sizeof(buf), "%s%c%s", PG(exec_dir), +PHP_DIR_SEPARATOR, Z_STRVAL_PP(arg1)); + } + + tmp = php_escape_shell_cmd(buf); + fp = VCWD_POPEN(tmp, p); + efree(tmp); + + if (!fp) { + php_error(E_WARNING, "popen(\"%s\", \"%s\") - %s", buf, p, +strerror(errno)); + RETURN_FALSE; + } } else { fp = VCWD_POPEN(Z_STRVAL_PP(arg1), p); if (!fp) { diff -uar php-4.2.1.orig/main/main.c php-4.2.1/main/main.c --- php-4.2.1.orig/main/main.c Sat Mar 9 01:26:40 2002 +++ php-4.2.1/main/main.c Thu Jun 20 12:06:26 2002 @@ -259,6 +259,7 @@ PHP_INI_ENTRY("max_execution_time", "30", PHP_INI_ALL, OnUpdateTimeout) STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, open_basedir, php_core_globals, core_globals) STD_PHP_INI_ENTRY("safe_mode_exec_dir", "1", PHP_INI_SYSTEM, OnUpdateString, safe_mode_exec_dir, php_core_globals, core_globals) + STD_PHP_INI_ENTRY("exec_dir", NULL, +PHP_INI_SYSTEM, OnUpdateString, exec_dir, + php_core_globals, core_globals) STD_PHP_INI_ENTRY("upload_max_filesize", "2M", PHP_INI_ALL, OnUpdateInt, upload_max_filesize, php_core_globals, core_globals) STD_PHP_INI_ENTRY("file_uploads", "1", PHP_INI_ALL, OnUpdateBool, file_uploads, php_core_globals, core_globals) STD_PHP_INI_ENTRY("post_max_size", "8M", PHP_INI_SYSTEM, OnUpdateInt, post_max_size, sapi_globals_struct,sapi_globals) diff -uar php-4.2.1.orig/main/php_globals.h php-4.2.1/main/php_globals.h --- php-4.2.1.orig/main/php_globals.h Thu Feb 28 09:27:03 2002 +++ php-4.2.1/main/php_globals.h Thu Jun 20 09:49:14 2002 @@ -69,6 +69,7 @@ char *unserialize_callback_func; char *safe_mode_exec_dir; + char *exec_dir; long memory_limit; diff -uar php-4.2.1.orig/php.ini-dist php-4.2.1/php.ini-dist --- php-4.2.1.orig/php.ini-dist Mon Apr 8 03:15:16 2002 +++ php-4.2.1/php.ini-dist Thu Jun 20 17:25:53 2002 @@ -390,6 +390,11 @@ ; cause security issues, KNOW WHAT YOU ARE DOING FIRST. ; cgi.redirect_status_env = ; +; Only executables located in the exec_dir will be allowed to be executed +; via the exec family of functions. If safe_mode is enabled, this directive +; is forgotten and safe_mode_exec_dir takes the ride +exec_dir = + ;;;;;;;;;;;;;;;; ; File Uploads ; ;;;;;;;;;;;;;;;; diff -uar php-4.2.1.orig/php.ini-recommended php-4.2.1/php.ini-recommended --- php-4.2.1.orig/php.ini-recommended Wed Apr 24 03:51:50 2002 +++ php-4.2.1/php.ini-recommended Thu Jun 20 17:26:24 2002 @@ -395,7 +395,10 @@ ; cause security issues, KNOW WHAT YOU ARE DOING FIRST. ; cgi.redirect_status_env = ; - +; Only executables located in the exec_dir will be allowed to be executed +; via the exec family of functions. If safe_mode is enabled, this directive +; is forgotten and safe_mode_exec_dir takes the ride +exec_dir = ;;;;;;;;;;;;;;;; ; File Uploads ; -- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php