From: Eric Covener Date: Tue, 12 May 2009 13:17:29 +0000 (+0000) Subject: backport 772997, 773322, 773342 from trunk. X-Git-Tag: 2.2.12~132 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6471e670e676c5c3538fc5fd9caa09207d0d1db9;p=thirdparty%2Fapache%2Fhttpd.git backport 772997, 773322, 773342 from trunk. Reviewed By: jorton, rpluem, covener Security fix for CVE-2009-1195: fix Options handling such that 'AllowOverride Options=IncludesNoExec' does not permit Includes with exec= enabled to be configured in an .htaccess file: * include/http_core.h: Change semantics of Includes/IncludeNoExec options bits to be additive; OPT_INCLUDES now means SSI is enabled without exec=. OPT_INCLUDES|OPT_INC_WITH_EXEC means SSI is enabled with exec=. * server/core.c (create_core_dir_config): Remove defunct OPT_INCNOEXEC from default override_opts; no functional change. (merge_core_dir_configs): Update logic to ensure that exec= is disabled in a context where IncludesNoexec is configured, even if Includes-with-exec is permitted in the inherited options set. (set_allow_opts, set_options): Update to reflect new semantics of OPT_INCLUDES, OPT_INC_WITH_EXEC. * server/config.c: Update to remove OPT_INCNOEXEC from default override_opts; no functional change. * modules/filters/mod_include.c (includes_filter): Update to reflect new options semantics - disable exec= support if the OPT_INC_WITH_EXEC bit is not set. Submitted by: Jonathan Peatfield , jorton Thanks to: Vincent Danon git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@773881 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 66edc645d4e..c57757aabf5 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,12 @@ Changes with Apache 2.2.12 *) mod_rewrite: When evaluating a proxy rule in directory context, do escape the filename by default. PR 46428 [Joe Orton] + *) SECURITY: CVE-2009-1195 (cve.mitre.org) + Prevent the "Includes" Option from being enabled in an .htaccess + file if the AllowOverride restrictions do not permit it. + [Jonathan Peatfield , Joe Orton, + Ruediger Pluem] + *) mod_proxy_ajp: Check more strictly that the backend follows the AJP protocol. [Mladen Turk] diff --git a/STATUS b/STATUS index d35ae82ea1c..4692d961de3 100644 --- a/STATUS +++ b/STATUS @@ -87,16 +87,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - * CVE-2009-1195 security fix for Includes merging. - trunk version of patch: - http://svn.apache.org/viewvc?rev=772997&view=rev - http://svn.apache.org/viewvc?rev=773322&view=rev - http://svn.apache.org/viewvc?rev=773342&view=rev - 2.2.x patch: - http://people.apache.org/~jorton/2.2.x-CVE-2009-1195.patch - (unmodified merge from trunk + CHANGES entry) - +1: jorton, rpluem, covener - PATCHES PROPOSED TO BACKPORT FROM TRUNK: [ New proposals should be added at the end of the list ] diff --git a/include/http_core.h b/include/http_core.h index 395ac4214c2..b39898cea00 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -65,7 +65,7 @@ extern "C" { #define OPT_NONE 0 /** Indexes directive */ #define OPT_INDEXES 1 -/** Includes directive */ +/** SSI is enabled without exec= permission */ #define OPT_INCLUDES 2 /** FollowSymLinks directive */ #define OPT_SYM_LINKS 4 @@ -73,14 +73,14 @@ extern "C" { #define OPT_EXECCGI 8 /** directive unset */ #define OPT_UNSET 16 -/** IncludesNOEXEC directive */ -#define OPT_INCNOEXEC 32 +/** SSI exec= permission is permitted, iff OPT_INCLUDES is also set */ +#define OPT_INC_WITH_EXEC 32 /** SymLinksIfOwnerMatch directive */ #define OPT_SYM_OWNER 64 /** MultiViews directive */ #define OPT_MULTI 128 /** All directives */ -#define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_SYM_LINKS|OPT_EXECCGI) +#define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_INC_WITH_EXEC|OPT_SYM_LINKS|OPT_EXECCGI) /** @} */ /** diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c index a174529e191..6a14f66a93f 100644 --- a/modules/filters/mod_include.c +++ b/modules/filters/mod_include.c @@ -3565,7 +3565,7 @@ static apr_status_t includes_filter(ap_filter_t *f, apr_bucket_brigade *b) intern->seen_eos = 0; intern->state = PARSE_PRE_HEAD; ctx->flags = (SSI_FLAG_PRINTING | SSI_FLAG_COND_TRUE); - if (ap_allow_options(r) & OPT_INCNOEXEC) { + if ((ap_allow_options(r) & OPT_INC_WITH_EXEC) == 0) { ctx->flags |= SSI_FLAG_NO_EXEC; } intern->accessenable = conf->accessenable; diff --git a/server/config.c b/server/config.c index 9747c284a63..101d0e4ed06 100644 --- a/server/config.c +++ b/server/config.c @@ -1510,7 +1510,7 @@ static const char *process_command_config(server_rec *s, parms.temp_pool = ptemp; parms.server = s; parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT); - parms.override_opts = OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER | OPT_MULTI; + parms.override_opts = OPT_ALL | OPT_SYM_OWNER | OPT_MULTI; parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives", &arr_parms, NULL, @@ -1617,7 +1617,7 @@ static const char *process_resource_config_nofnmatch(server_rec *s, parms.temp_pool = ptemp; parms.server = s; parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT); - parms.override_opts = OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER | OPT_MULTI; + parms.override_opts = OPT_ALL | OPT_SYM_OWNER | OPT_MULTI; rv = ap_pcfg_openfile(&cfp, p, fname); if (rv != APR_SUCCESS) { @@ -1755,7 +1755,7 @@ AP_DECLARE(int) ap_process_config_tree(server_rec *s, parms.temp_pool = ptemp; parms.server = s; parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT); - parms.override_opts = OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER | OPT_MULTI; + parms.override_opts = OPT_ALL | OPT_SYM_OWNER | OPT_MULTI; parms.limited = -1; errmsg = ap_walk_config(conftree, &parms, s->lookup_defaults); diff --git a/server/core.c b/server/core.c index 3b1b01b7d31..3123846f513 100644 --- a/server/core.c +++ b/server/core.c @@ -108,8 +108,7 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir) conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL; conf->opts_add = conf->opts_remove = OPT_NONE; conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL; - conf->override_opts = OPT_UNSET | OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER - | OPT_MULTI; + conf->override_opts = OPT_UNSET | OPT_ALL | OPT_SYM_OWNER | OPT_MULTI; conf->content_md5 = 2; conf->accept_path_info = 3; @@ -242,8 +241,15 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv) conf->opts_remove = (conf->opts_remove & ~new->opts_add) | new->opts_remove; conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add; - if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES)) { - conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES; + + /* If Includes was enabled with exec in the base config, but + * was enabled without exec in the new config, then disable + * exec in the merged set. */ + if (((base->opts & (OPT_INCLUDES|OPT_INC_WITH_EXEC)) + == (OPT_INCLUDES|OPT_INC_WITH_EXEC)) + && ((new->opts & (OPT_INCLUDES|OPT_INC_WITH_EXEC)) + == OPT_INCLUDES)) { + conf->opts &= ~OPT_INC_WITH_EXEC; } } else { @@ -1304,10 +1310,12 @@ static const char *set_allow_opts(cmd_parms *cmd, allow_options_t *opts, opt = OPT_INDEXES; } else if (!strcasecmp(w, "Includes")) { - opt = OPT_INCLUDES; + /* If Includes is permitted, both Includes and + * IncludesNOEXEC may be changed. */ + opt = (OPT_INCLUDES | OPT_INC_WITH_EXEC); } else if (!strcasecmp(w, "IncludesNOEXEC")) { - opt = (OPT_INCLUDES | OPT_INCNOEXEC); + opt = OPT_INCLUDES; } else if (!strcasecmp(w, "FollowSymLinks")) { opt = OPT_SYM_LINKS; @@ -1428,10 +1436,10 @@ static const char *set_options(cmd_parms *cmd, void *d_, const char *l) opt = OPT_INDEXES; } else if (!strcasecmp(w, "Includes")) { - opt = OPT_INCLUDES; + opt = (OPT_INCLUDES | OPT_INC_WITH_EXEC); } else if (!strcasecmp(w, "IncludesNOEXEC")) { - opt = (OPT_INCLUDES | OPT_INCNOEXEC); + opt = OPT_INCLUDES; } else if (!strcasecmp(w, "FollowSymLinks")) { opt = OPT_SYM_LINKS;