Download | Plain Text | No Line Numbers
- This patch is based on http://kyberdigi.cz/projects/execdir/ but instead trying
- to sanitize the exec command string inside PHP this job is handled by bash and
- a special restricted PHP-mode which strips off all path informations.
-
- This patch depends on:
- - bash restricted php mode patch
- https://manuel.mausz.at/coding/patches/php/bash-4.2-restricted-php.patch
-
- No warranty!
- diff -Naur php-7.4.4.orig/ext/standard/exec.c php-7.4.4/ext/standard/exec.c
- --- php-7.4.4.orig/ext/standard/exec.c 2020-03-17 11:40:33.000000000 +0100
- +++ php-7.4.4/ext/standard/exec.c 2020-03-19 14:36:43.456447593 +0100
- @@ -96,21 +96,30 @@
- char *buf;
- size_t l = 0;
- int pclose_return;
- - char *b, *d=NULL;
- + char *cmd_p, *b, *d=NULL;
- php_stream *stream;
- size_t buflen, bufl = 0;
- #if PHP_SIGCHILD
- void (*sig_handler)() = NULL;
- #endif
-
- + if (PG(exec_dir) && strlen(PG(exec_dir))) {
- + zend_string *cmd_esc = php_escape_shell_arg(cmd);
- + spprintf(&d, 0, "PATH=%s /bin/bash --php -rc %s", PG(exec_dir), ZSTR_VAL(cmd_esc));
- + zend_string_release(cmd_esc);
- + cmd_p = d;
- + } else {
- + cmd_p = cmd;
- + }
- +
- #if PHP_SIGCHILD
- sig_handler = signal (SIGCHLD, SIG_DFL);
- #endif
-
- #ifdef PHP_WIN32
- - fp = VCWD_POPEN(cmd, "rb");
- + fp = VCWD_POPEN(cmd_p, "rb");
- #else
- - fp = VCWD_POPEN(cmd, "r");
- + fp = VCWD_POPEN(cmd_p, "r");
- #endif
- if (!fp) {
- php_error_docref(NULL, E_WARNING, "Unable to fork [%s]", cmd);
- @@ -521,7 +530,7 @@
- PHP_FUNCTION(shell_exec)
- {
- FILE *in;
- - char *command;
- + char *command, *command_p;
- size_t command_len;
- zend_string *ret;
- php_stream *stream;
- @@ -530,14 +539,24 @@
- Z_PARAM_STRING(command, command_len)
- ZEND_PARSE_PARAMETERS_END();
-
- + if (PG(exec_dir) && strlen(PG(exec_dir))) {
- + zend_string *cmd_esc = php_escape_shell_arg(command);
- + spprintf(&command_p, 0, "PATH=%s /bin/bash --php -rc %s", PG(exec_dir), ZSTR_VAL(cmd_esc));
- + zend_string_release(cmd_esc);
- + } else {
- + command_p = estrdup(command);
- + }
- +
- #ifdef PHP_WIN32
- - if ((in=VCWD_POPEN(command, "rt"))==NULL) {
- + if ((in=VCWD_POPEN(command_p, "rt"))==NULL) {
- #else
- - if ((in=VCWD_POPEN(command, "r"))==NULL) {
- + if ((in=VCWD_POPEN(command_p, "r"))==NULL) {
- #endif
- php_error_docref(NULL, E_WARNING, "Unable to execute '%s'", command);
- + efree(command_p);
- RETURN_FALSE;
- }
- + efree(command_p);
-
- stream = php_stream_fopen_from_pipe(in, "rb");
- ret = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0);
- diff -Naur php-7.4.4.orig/ext/standard/file.c php-7.4.4/ext/standard/file.c
- --- php-7.4.4.orig/ext/standard/file.c 2020-03-17 11:40:30.000000000 +0100
- +++ php-7.4.4/ext/standard/file.c 2020-03-19 14:36:43.457447585 +0100
- @@ -952,7 +952,16 @@
- }
- #endif
-
- - fp = VCWD_POPEN(command, posix_mode);
- + if (PG(exec_dir) && strlen(PG(exec_dir))) {
- + zend_string *cmd_esc = php_escape_shell_arg(command);
- + char *tmp;
- + spprintf(&tmp, 0, "PATH=%s /bin/bash --php -rc %s", PG(exec_dir), ZSTR_VAL(cmd_esc));
- + fp = VCWD_POPEN(tmp, posix_mode);
- + efree(tmp);
- + zend_string_release(cmd_esc);
- + } else {
- + fp = VCWD_POPEN(command, posix_mode);
- + }
- if (!fp) {
- php_error_docref2(NULL, command, posix_mode, E_WARNING, "%s", strerror(errno));
- efree(posix_mode);
- diff -Naur php-7.4.4.orig/ext/standard/filestat.c php-7.4.4/ext/standard/filestat.c
- --- php-7.4.4.orig/ext/standard/filestat.c 2020-03-17 11:40:30.000000000 +0100
- +++ php-7.4.4/ext/standard/filestat.c 2020-03-19 14:36:43.458447578 +0100
- @@ -769,13 +769,14 @@
- "size", "atime", "mtime", "ctime", "blksize", "blocks"
- };
- const char *local;
- + char local_safe[MAXPATHLEN];
- php_stream_wrapper *wrapper;
-
- if (!filename_length) {
- RETURN_FALSE;
- }
-
- - if ((wrapper = php_stream_locate_url_wrapper(filename, &local, 0)) == &php_plain_files_wrapper && php_check_open_basedir(local)) {
- + if ((wrapper = php_stream_locate_url_wrapper(filename, &local, 0)) == &php_plain_files_wrapper && type != FS_IS_X && php_check_open_basedir(local)) {
- RETURN_FALSE;
- }
-
- @@ -800,6 +801,19 @@
- #endif
- #ifdef X_OK
- case FS_IS_X:
- + if (PG(exec_dir) && strlen(PG(exec_dir))) {
- + if (strstr(local, "..")) {
- + RETURN_FALSE;
- + } else {
- + char *b = strrchr(local, PHP_DIR_SEPARATOR);
- + if (b) {
- + snprintf(local_safe, MAXPATHLEN, "%s%s", PG(exec_dir), b);
- + } else {
- + snprintf(local_safe, MAXPATHLEN, "%s%c%s", PG(exec_dir), PHP_DIR_SEPARATOR, local);
- + }
- + local = (char *)&local_safe;
- + }
- + }
- RETURN_BOOL(VCWD_ACCESS(local, X_OK) == 0);
- break;
- #endif
- diff -Naur php-7.4.4.orig/ext/standard/proc_open.c php-7.4.4/ext/standard/proc_open.c
- --- php-7.4.4.orig/ext/standard/proc_open.c 2020-03-17 11:40:33.000000000 +0100
- +++ php-7.4.4/ext/standard/proc_open.c 2020-03-19 14:36:43.458447578 +0100
- @@ -543,8 +543,17 @@
- RETURN_FALSE;
- }
- #else
- - argv = safe_emalloc(sizeof(char *), num_elems + 1, 0);
- + argv = safe_emalloc(sizeof(char *), num_elems + 1 + 5, 0);
- i = 0;
- + if (PG(exec_dir) && strlen(PG(exec_dir))) {
- + command = pestrdup("/bin/bash", is_persistent);
- + argv[i++] = estrdup("/bin/bash");
- + argv[i++] = estrdup("--php");
- + argv[i++] = estrdup("-rc");
- + argv[i++] = estrdup("exec \"$@\"");
- + argv[i++] = estrdup("bash");
- + argv[i] = NULL;
- + }
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(command_zv), arg_zv) {
- zend_string *arg_str = get_valid_arg_string(arg_zv, i + 1);
- if (!arg_str) {
- @@ -609,6 +618,15 @@
- }
- #endif
-
- + zval envpath;
- + if (PG(exec_dir) && strlen(PG(exec_dir))) {
- + if (!environment || zend_hash_num_elements(Z_ARRVAL_P(environment)) == 0) {
- + array_init_size(&envpath, 1);
- + environment = &envpath;
- + }
- + add_assoc_string(environment, "PATH", PG(exec_dir));
- + }
- +
- if (environment) {
- env = _php_array_to_envp(environment, is_persistent);
- }
- @@ -1057,10 +1075,14 @@
- }
- execvp(command, argv);
- } else {
- - if (env.envarray) {
- - execle("/bin/sh", "sh", "-c", command, NULL, env.envarray);
- + if (PG(exec_dir) && strlen(PG(exec_dir))) {
- + execle("/bin/bash", "bash", "--php", "-rc", command, NULL, env.envarray);
- } else {
- - execl("/bin/sh", "sh", "-c", command, NULL);
- + if (env.envarray) {
- + execle("/bin/sh", "sh", "-c", command, NULL, env.envarray);
- + } else {
- + execl("/bin/sh", "sh", "-c", command, NULL);
- + }
- }
- }
- _exit(127);
- diff -Naur php-7.4.4.orig/main/main.c php-7.4.4/main/main.c
- --- php-7.4.4.orig/main/main.c 2020-03-19 14:34:35.398407536 +0100
- +++ php-7.4.4/main/main.c 2020-03-19 14:36:43.459447570 +0100
- @@ -820,6 +820,7 @@
- STD_PHP_INI_ENTRY("syslog.facility", "LOG_USER", PHP_INI_SYSTEM, OnSetFacility, syslog_facility, php_core_globals, core_globals)
- STD_PHP_INI_ENTRY("syslog.ident", "php", PHP_INI_SYSTEM, OnUpdateString, syslog_ident, php_core_globals, core_globals)
- STD_PHP_INI_ENTRY("syslog.filter", "no-ctrl", PHP_INI_ALL, OnSetLogFilter, syslog_filter, php_core_globals, core_globals)
- + STD_PHP_INI_ENTRY("exec_dir", NULL, PHP_INI_SYSTEM, OnUpdateString, exec_dir, php_core_globals, core_globals)
- PHP_INI_END()
- /* }}} */
-
- diff -Naur php-7.4.4.orig/main/php_globals.h php-7.4.4/main/php_globals.h
- --- php-7.4.4.orig/main/php_globals.h 2020-03-17 11:40:21.000000000 +0100
- +++ php-7.4.4/main/php_globals.h 2020-03-19 14:36:43.460447563 +0100
- @@ -170,6 +170,8 @@
- char *syslog_ident;
- zend_bool have_called_openlog;
- zend_long syslog_filter;
- +
- + char *exec_dir;
- };
-
-
- diff -Naur php-7.4.4.orig/php.ini-development php-7.4.4/php.ini-development
- --- php-7.4.4.orig/php.ini-development 2020-03-17 11:40:21.000000000 +0100
- +++ php-7.4.4/php.ini-development 2020-03-19 14:36:43.460447563 +0100
- @@ -306,6 +306,10 @@
- ; http://php.net/open-basedir
- ;open_basedir =
-
- +; Only executables located in the exec_dir will be allowed to be executed
- +; via the exec family of functions.
- +exec_dir =
- +
- ; This directive allows you to disable certain functions.
- ; It receives a comma-delimited list of function names.
- ; http://php.net/disable-functions
- diff -Naur php-7.4.4.orig/php.ini-production php-7.4.4/php.ini-production
- --- php-7.4.4.orig/php.ini-production 2020-03-17 11:40:21.000000000 +0100
- +++ php-7.4.4/php.ini-production 2020-03-19 14:36:43.461447555 +0100
- @@ -306,6 +306,10 @@
- ; http://php.net/open-basedir
- ;open_basedir =
-
- +; Only executables located in the exec_dir will be allowed to be executed
- +; via the exec family of functions.
- +exec_dir =
- +
- ; This directive allows you to disable certain functions.
- ; It receives a comma-delimited list of function names.
- ; http://php.net/disable-functions
-