|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2000-07-29 15:16 UTC] waldschrott@php.net
[2000-08-01 00:24 UTC] waldschrott@php.net
[2000-10-18 19:23 UTC] djm at web dot us dot uu dot net
[2002-05-24 20:33 UTC] derick@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 16:00:01 2025 UTC |
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);