php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | |
Patch fpm-extensions.v2.patch for FPM related Bug #55181Patch version 2011-07-11 14:19 UTC Return to Bug #55181 | Download this patchThis patch renders other patches obsolete Obsolete patches: Patch Revisions:Developer: fat@php.netIndex: sapi/fpm/php-fpm.conf.in =================================================================== --- sapi/fpm/php-fpm.conf.in (revision 313131) +++ sapi/fpm/php-fpm.conf.in (working copy) @@ -421,6 +421,12 @@ ; process time (several ms). ; Default Value: no ;catch_workers_output = yes + +; Limits the extensions FPM will allow to parse. This can prevent configuration +; mistakes on the web server side. You should only limit FPM to .php extensions +; to prevent malicious users to use other extensions to exectute php code. +; Default Value: no +;security.limit_extensions = .php ; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from ; the current environment. Index: sapi/fpm/fpm/fpm_conf.c =================================================================== --- sapi/fpm/fpm/fpm_conf.c (revision 313131) +++ sapi/fpm/fpm/fpm_conf.c (working copy) @@ -121,6 +121,7 @@ { "ping.response", &fpm_conf_set_string, WPO(ping_response) }, { "access.log", &fpm_conf_set_string, WPO(access_log) }, { "access.format", &fpm_conf_set_string, WPO(access_format) }, + { "security.limit_extensions", &fpm_conf_set_string, WPO(security_limit_extensions) }, { 0, 0, 0 } }; @@ -599,6 +600,7 @@ free(wpc->prefix); free(wpc->access_log); free(wpc->access_format); + free(wpc->security_limit_extensions); return 0; } @@ -845,6 +847,53 @@ } } + if (wp->config->security_limit_extensions && *wp->config->security_limit_extensions) { + int nb_ext; + char *ext; + char *security_limit_extensions; + char *limit_extensions; + + + /* strdup because strtok(3) alters the string it parses */ + security_limit_extensions = strdup(wp->config->security_limit_extensions); + limit_extensions = security_limit_extensions; + nb_ext = 0; + + /* find the number of extensions */ + while ((ext = strtok(limit_extensions, " \t"))) { + limit_extensions = NULL; + nb_ext++; + } + free(security_limit_extensions); + + /* if something found */ + if (nb_ext > 0) { + + /* malloc the extension array */ + wp->limit_extensions = malloc(sizeof(char *) * (nb_ext + 1)); + if (!wp->limit_extensions) { + zlog(ZLOG_ERROR, "[pool %s] unable to malloc extensions array", wp->config->name); + return -1; + } + + /* strdup because strtok(3) alters the string it parses */ + security_limit_extensions = strdup(wp->config->security_limit_extensions); + limit_extensions = security_limit_extensions; + nb_ext = 0; + + /* parse the string and save the extension in the array */ + while ((ext = strtok(security_limit_extensions, " \t"))) { + security_limit_extensions = NULL; + wp->limit_extensions[nb_ext] = strdup(ext); + nb_ext++; + } + + /* end the array with NULL in order to parse it */ + wp->limit_extensions[nb_ext] = NULL; + free(security_limit_extensions); + } + } + if (wp->config->chroot && *wp->config->chroot) { fpm_evaluate_full_path(&wp->config->chroot, wp, NULL, 1); @@ -1380,6 +1429,7 @@ zlog(ZLOG_NOTICE, "\tslowlog = %s", STR2STR(wp->config->slowlog)); zlog(ZLOG_NOTICE, "\trlimit_files = %d", wp->config->rlimit_files); zlog(ZLOG_NOTICE, "\trlimit_core = %d", wp->config->rlimit_core); + zlog(ZLOG_NOTICE, "\tsecurity.limit_extensions = %s", wp->config->security_limit_extensions); for (kv = wp->config->env; kv; kv = kv->next) { zlog(ZLOG_NOTICE, "\tenv[%s] = %s", kv->key, kv->value); Index: sapi/fpm/fpm/fpm_php.c =================================================================== --- sapi/fpm/fpm/fpm_php.c (revision 313131) +++ sapi/fpm/fpm/fpm_php.c (working copy) @@ -20,6 +20,8 @@ #include "fpm_cleanup.h" #include "fpm_worker_pool.h" +static char **limit_extensions = NULL; + static int fpm_php_zend_ini_alter_master(char *name, int name_length, char *new_value, int new_value_length, int mode, int stage TSRMLS_DC) /* {{{ */ { zend_ini_entry *ini_entry; @@ -219,7 +221,37 @@ 0 > fpm_php_set_allowed_clients(wp)) { return -1; } + + if (wp->limit_extensions) { + limit_extensions = wp->limit_extensions; + } return 0; } /* }}} */ +int fpm_php_limit_extensions(char *path) /* {{{ */ +{ + char **p; + size_t path_len; + + if (!path || !limit_extensions) { + return 0; /* allowed by default */ + } + + p = limit_extensions; + path_len = strlen(path); + while (p && *p) { + size_t ext_len = strlen(*p); + if (path_len > ext_len) { + char *path_ext = path + path_len - ext_len; + if (strcmp(*p, path_ext) == 0) { + return 0; /* allow as the extension has been found */ + } + } + p++; + } + + + return 1; /* extension not found: not allowed */ +} +/* }}} */ Index: sapi/fpm/fpm/fpm_conf.h =================================================================== --- sapi/fpm/fpm/fpm_conf.h (revision 313131) +++ sapi/fpm/fpm/fpm_conf.h (working copy) @@ -66,6 +66,7 @@ char *listen_group; char *listen_mode; char *listen_allowed_clients; + char *security_limit_extensions; struct key_value_s *env; struct key_value_s *php_admin_values; struct key_value_s *php_values; Index: sapi/fpm/fpm/fpm_php.h =================================================================== --- sapi/fpm/fpm/fpm_php.h (revision 313131) +++ sapi/fpm/fpm/fpm_php.h (working copy) @@ -43,6 +43,7 @@ void fpm_php_soft_quit(); int fpm_php_init_main(); int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode); +int fpm_php_limit_extensions(char *path); #endif Index: sapi/fpm/fpm/fpm_worker_pool.h =================================================================== --- sapi/fpm/fpm/fpm_worker_pool.h (revision 313131) +++ sapi/fpm/fpm/fpm_worker_pool.h (working copy) @@ -37,6 +37,7 @@ #endif struct fpm_scoreboard_s *scoreboard; int log_fd; + char **limit_extensions; }; struct fpm_worker_pool_s *fpm_worker_pool_alloc(); Index: sapi/fpm/fpm/fpm_main.c =================================================================== --- sapi/fpm/fpm/fpm_main.c (revision 313131) +++ sapi/fpm/fpm/fpm_main.c (working copy) @@ -1879,6 +1879,12 @@ goto fastcgi_request_done; } + if (fpm_php_limit_extensions(SG(request_info).path_translated)) { + SG(sapi_headers).http_response_code = 403; + PUTS("Access denied.\n"); + goto fastcgi_request_done; + } + /* path_translated exists, we can continue ! */ if (php_fopen_primary_script(&file_handle TSRMLS_CC) == FAILURE) { zend_try { |
Copyright © 2001-2024 The PHP Group All rights reserved. |
Last updated: Thu Nov 21 15:01:30 2024 UTC |