|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2000-03-30 22:49 UTC] djm at web dot us dot uu dot net
Security problem: PHP4 with apache 1.3.12, built as a DSO, allows "admin" values and flags (those marked PHP_INI_SYSTEM in main.c) to be reset in .htaccess files. This bug also existed in PHP4b4 with apache 1.3.9. To demonstrate the problem, in httpd.conf, set something like this: php_admin_flag safe_mode On php_admin_value doc_root "/opt/homes/web/testtest5" php_admin_value open_basedir "/opt/homes/web/testtest5" php_admin_value safe_mode_exec_dir "/opt/homes/web/testtest5/bin" (your textarea made that last line wrap) Create a phpinfo.php file under the document root containing: <?php phpinfo()?> GET phpinfo.php to verify that the settings above have been made. Now, create a .htaccess in that directory containing: php_value open_basedir "/" php_value doc_root "/" php_value safe_mode Off GET phpinfo.php again and note that the values in the .htaccess file have superceded those in the server config file. BTW, there's a related doc bug: --- apidoc-zend.txt 2000/03/31 01:55:33 1.1.1.1 +++ apidoc-zend.txt 2000/03/31 03:44:44 @@ -238,7 +238,7 @@ and "bah" respectively - note that all defaults are always given as strings. That doesn't reduce your ability to use integer values, simply specify them as strings. "foo" is marked so that it can be changed by -anyone at any time (PHP_INI_ALL), whereas "foo" is marked so it can be +anyone at any time (PHP_INI_ALL), whereas "bar" is marked so it can be changed only at startup in the php3.ini only, presumably, by the system administrator (PHP_INI_SYSTEM). When "foo" changes, no function is called. Access to it is done using the PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Nov 06 03:00:01 2025 UTC |
After adding some debugging code, I have a better understanding of what's going on. The values in the .htaccess file are not being used, but they are overwriting in the hash table the values from the httpd.conf, so the compiled-in defaults are taking effect. In sapi/apache/mod_php4.c, php_apache_alter_ini_entries calls php_alter_ini_entry, which does return -1 for the values that aren't settable from a .htaccess file, because they have modify_type PHP_INI_PERDIR (2). But the values set in the httpd.conf (with modify_type PHP_INI_SYSTEM (4)) have disappeared. In the mod_php4.c hash table merging code, php_merge_dir and copy_per_dir_entry shouldn't overwrite a global setting with a disallowed per-directory one. Better yet, php_apache_value_handler_ex shouldn't enter disallowed values into the per-dir hash table in the first place (it should check mode first). Here's a diff that seems to fix the problem, and includes some debugging code to help demonstrate it: --- sapi/apache/mod_php4.c 2000/03/31 01:55:50 1.1.1.1 +++ sapi/apache/mod_php4.c 2000/03/31 07:10:39 @@ -394,7 +394,13 @@ static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry) { - php_alter_ini_entry(per_dir_entry->key, per_dir_entry->key_length+1, per_dir_entry->value, per_dir_entry->value_length+1, per_dir_entry->type, PHP_INI_STAGE_ACTIVATE); + int i; + char msg[8192]; + snprintf(msg, 8192, "altering ini entry %s=%s type=%d", per_dir_entry->key, per_dir_entry->value, per_dir_entry->type); + php_apache_log_message(msg); + i = php_alter_ini_entry(per_dir_entry->key, per_dir_entry->key_length+1, per_dir_entry->value, per_dir_entry->value_length+1, per_dir_entry->type, PHP_INI_STAGE_ACTIVATE); + snprintf(msg, 8192, " => %d", i); + php_apache_log_message(msg); return 0; } @@ -560,6 +566,7 @@ CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode) { php_per_dir_entry per_dir_entry; + php_ini_entry *ini_entry; if (!apache_php_initialized) { sapi_startup(&sapi_module); @@ -574,6 +581,14 @@ per_dir_entry.key_length = strlen(arg1); per_dir_entry.value_length = strlen(arg2); + + ini_entry = get_ini_entry(arg1, per_dir_entry.key_length + 1); + if (ini_entry && !(ini_entry->modifyable & mode)) { + char msg[8192]; + snprintf(msg, 8192, "setting %s to %s in %d is not permitted", arg1, arg2, mode); + php_apache_log_message(msg); + return NULL; + } per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1); memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length);Here's a patch wtih a more user-friendly error message: --- sapi/apache/mod_php4.c 2000/03/31 01:55:50 1.1 +++ sapi/apache/mod_php4.c 2000/03/31 07:24:01 1.2 @@ -560,6 +571,7 @@ CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode) { php_per_dir_entry per_dir_entry; + php_ini_entry *ini_entry; if (!apache_php_initialized) { sapi_startup(&sapi_module); @@ -574,6 +586,20 @@ per_dir_entry.key_length = strlen(arg1); per_dir_entry.value_length = strlen(arg2); + + ini_entry = get_ini_entry(arg1, per_dir_entry.key_length + 1); + if (ini_entry && !(ini_entry->modifyable & mode)) { + char msg[8192], *context; + if (mode == PHP_INI_SYSTEM) + context = "system"; + else if (mode == PHP_INI_PERDIR) + context = "per-directory"; + else + context = "unknown"; + snprintf(msg, 8192, "php: not setting %s=\"%s\"; not permitted in %s configuration", arg1, arg2, context); + php_apache_log_message(msg); + return NULL; + } per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1); memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length);