[PHP-DEV] PHP 4.0 Bug #3076: system and popen are ok in safe_mode, not backquotes From: djm <email protected>
Date: 12/31/99

From: djm <email protected>
Operating system: all
PHP version: 4.0 Beta 3
PHP Bug Type: Misbehaving function
Bug description: system and popen are ok in safe_mode, not backquotes

Support for shell escapes is inconsistent in safe_mode. Functions that use _Exec are ok, but backquotes are disallowed for no good reason I can see. They don't seem to be any more dangerous than exec, system, or popen.
I have adapted the safe_mode_exec_dir code from _Exec to shell_exec.
I also made the detection of references to parent directories more accurate,
screening out false matches (e.g., it would disallow a program called "do...stuff").
I am curious why on Windows, _Exec uses binary mode but shell_exec uses text mode. I didn't do anything about that, but it deserves at least a comment in the code.

--- ext/standard/exec.c 1999/12/30 22:31:15 1.1.1.2
+++ ext/standard/exec.c 1999/12/31 22:55:09
@@ -62,7 +62,7 @@
                overflow_limit = l;
                c = strchr(cmd, ' ');
                if (c) *c = '\0';
- if (strstr(cmd, "..")) {
+ if (!strncmp(cmd, "../", 3) || strstr(cmd, "/../")) {
                        php_error(E_WARNING, "No '..' components allowed in path");
                        efree(buf);
                        return -1;
@@ -367,6 +367,7 @@
 {
        FILE *in;
        int readbytes,total_readbytes=0,allocated_space;
+ char *scmd;
        pval *cmd;
        PLS_FETCH();
 
@@ -374,18 +375,59 @@
                WRONG_PARAM_COUNT;
        }
        
- if (PG(safe_mode)) {
- php_error(E_WARNING,"Cannot execute using backquotes in safe mode");
- RETURN_FALSE;
- }
-
        convert_to_string(cmd);
+ scmd = cmd->value.str.val;
+
+ if (PG(safe_mode)) {
+ int l;
+ int overflow_limit, lcmd, ldir;
+ char *b, *c, *d=NULL, *tmp=NULL;
+
+ lcmd = strlen(scmd);
+ ldir = strlen(PG(safe_mode_exec_dir));
+ l = lcmd + ldir + 2;
+ overflow_limit = l;
+ c = strchr(scmd, ' ');
+ if (c) *c = '\0';
+ if (!strncmp(scmd, "../", 3) || strstr(scmd, "/../")) {
+ php_error(E_WARNING, "No '..' components allowed in path");
+ RETURN_FALSE;
+ }
+ d = emalloc(l);
+ strcpy(d, PG(safe_mode_exec_dir));
+ overflow_limit -= ldir;
+ b = strrchr(scmd, '/');
+ if (b) {
+ strcat(d, b);
+ overflow_limit -= strlen(b);
+ } else {
+ strcat(d, "/");
+ strcat(d, scmd);
+ overflow_limit-=(strlen(scmd)+1);
+ }
+ if (c) {
+ *c = ' ';
+ strncat(d, c, overflow_limit);
+ }
+ tmp = _php3_escapeshellcmd(d);
+ efree(d);
+ d = tmp;
+#if WIN32|WINNT
+ in = popen(d, "rt");
+#else
+ in = popen(d, "r");
+#endif
+ if (!in)
+ php_error(E_WARNING,"Unable to execute '%s'", d);
+ efree(d);
+ } else { /* not safe_mode */
 #if WIN32|WINNT
- if ((in=popen(cmd->value.str.val,"rt"))==NULL) {
+ in = popen(scmd,"rt");
 #else
- if ((in=popen(cmd->value.str.val,"r"))==NULL) {
+ in = popen(scmd,"r");
 #endif
- php_error(E_WARNING,"Unable to execute '%s'",cmd->value.str.val);
+ if (!in)
+ php_error(E_WARNING,"Unable to execute '%s'",scmd);
        }
        allocated_space = EXEC_INPUT_BUF;
        return_value->value.str.val = (char *) emalloc(allocated_space);

-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: php-dev-unsubscribe <email protected>
For additional commands, e-mail: php-dev-help <email protected>
To contact the list administrators, e-mail: php-list-admin <email protected>