fat Sat, 08 Oct 2011 13:42:31 +0000
Revision: http://svn.php.net/viewvc?view=revision&revision=317894
Log:
- Backported FR #55181 from 5.4 branch (Enhance security by limiting access to
user defined extensions)
Bug: https://bugs.php.net/55181 (Analyzed) Enhance security by limiting the
script extension
Changed paths:
U php/php-src/branches/PHP_5_3/NEWS
U php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_conf.c
U php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_conf.h
U php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_main.c
U php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_php.c
U php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_php.h
U php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_worker_pool.h
U php/php-src/branches/PHP_5_3/sapi/fpm/php-fpm.conf.in
Modified: php/php-src/branches/PHP_5_3/NEWS
===================================================================
--- php/php-src/branches/PHP_5_3/NEWS 2011-10-08 13:38:28 UTC (rev 317893)
+++ php/php-src/branches/PHP_5_3/NEWS 2011-10-08 13:42:31 UTC (rev 317894)
@@ -75,6 +75,8 @@
. Fixed bug #53872 (internal corruption of phar). (Hannes)
- PHP-FPM SAPI:
+ . Backported FR #55181 from 5.4 branch (Enhance security by limiting access
+ to user defined extensions). (fat)
. Backported FR #54098 from 5.4 branch (Lowered process manager
default value). (fat)
. Backported FR #52052 from 5.4 branch (Added partial syslog support). (fat)
Modified: php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_conf.c
===================================================================
--- php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_conf.c 2011-10-08 13:38:28 UTC (rev 317893)
+++ php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_conf.c 2011-10-08 13:42:31 UTC (rev 317894)
@@ -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,56 @@
}
}
+ if (!wp->config->security_limit_extensions) {
+ wp->config->security_limit_extensions = strdup(".php");
+ }
+
+ if (*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);
+ }
+
+ /* 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 +1432,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);
Modified: php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_conf.h
===================================================================
--- php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_conf.h 2011-10-08 13:38:28 UTC (rev 317893)
+++ php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_conf.h 2011-10-08 13:42:31 UTC (rev 317894)
@@ -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;
Modified: php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_main.c
===================================================================
--- php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_main.c 2011-10-08 13:38:28 UTC (rev 317893)
+++ php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_main.c 2011-10-08 13:42:31 UTC (rev 317894)
@@ -1878,6 +1878,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 {
Modified: php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_php.c
===================================================================
--- php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_php.c 2011-10-08 13:38:28 UTC (rev 317893)
+++ php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_php.c 2011-10-08 13:42:31 UTC (rev 317894)
@@ -19,7 +19,10 @@
#include "fpm_php.h"
#include "fpm_cleanup.h"
#include "fpm_worker_pool.h"
+#include "zlog.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 +222,38 @@
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++;
+ }
+
+
+ zlog(ZLOG_NOTICE, "Access to the file '%s' has been denied (see security.limit_extensions)", path);
+ return 1; /* extension not found: not allowed */
+}
+/* }}} */
Modified: php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_php.h
===================================================================
--- php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_php.h 2011-10-08 13:38:28 UTC (rev 317893)
+++ php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_php.h 2011-10-08 13:42:31 UTC (rev 317894)
@@ -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
Modified: php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_worker_pool.h
===================================================================
--- php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_worker_pool.h 2011-10-08 13:38:28 UTC (rev 317893)
+++ php/php-src/branches/PHP_5_3/sapi/fpm/fpm/fpm_worker_pool.h 2011-10-08 13:42:31 UTC (rev 317894)
@@ -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();
Modified: php/php-src/branches/PHP_5_3/sapi/fpm/php-fpm.conf.in
===================================================================
--- php/php-src/branches/PHP_5_3/sapi/fpm/php-fpm.conf.in 2011-10-08 13:38:28 UTC (rev 317893)
+++ php/php-src/branches/PHP_5_3/sapi/fpm/php-fpm.conf.in 2011-10-08 13:42:31 UTC (rev 317894)
@@ -421,6 +421,14 @@
; process time (several ms).
; Default Value: no
;catch_workers_output = yes
+
+; Limits the extensions of the main script 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.
+; Note: set an empty value to allow all extensions.
+; Default Value: .php
+;security.limit_extensions = .php .php3 .php4 .php5
; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php