--- httpd-2.2.22.orig/modules/mappers/mod_rewrite.c 2012-01-24 19:39:31.000000000 +0000 +++ httpd-2.2.22/modules/mappers/mod_rewrite.c 2012-05-28 12:54:42.296237744 +0100 @@ -3995,7 +3995,7 @@ static int apply_rewrite_rule(rewriterul * i.e. a list of rewrite rules */ static int apply_rewrite_list(request_rec *r, apr_array_header_t *rewriterules, - char *perdir) + char *perdir, int *uricheck) { rewriterule_entry *entries; rewriterule_entry *p; @@ -4008,6 +4008,7 @@ static int apply_rewrite_list(request_re ctx = apr_palloc(r->pool, sizeof(*ctx)); ctx->perdir = perdir; ctx->r = r; + *uricheck=0; /* True if the URI should be made to pass extra checks */ /* * Iterate over all existing rules @@ -4079,6 +4080,9 @@ static int apply_rewrite_list(request_re * last-rule and new-round flags. */ if (p->flags & (RULEFLAG_PROXY | RULEFLAG_LASTRULE)) { + if (p->flags & RULEFLAG_PROXY) { + *uricheck=1; + } break; } @@ -4240,6 +4244,7 @@ static int hook_uri2file(request_rec *r) const char *thisurl; unsigned int port; int rulestatus; + int uricheck=0; /* True if the URI should be made to pass extra checks */ /* * retrieve the config structures @@ -4267,7 +4272,9 @@ static int hook_uri2file(request_rec *r) } if ((r->unparsed_uri[0] == '*' && r->unparsed_uri[1] == '\0') - || !r->uri || r->uri[0] != '/') { + || !r->uri ) { + rewritelog((r, 2, NULL, "uri %s is considered a security risk", + r->uri ? r->uri : "")); return DECLINED; } @@ -4327,7 +4334,8 @@ static int hook_uri2file(request_rec *r) /* * now apply the rules ... */ - rulestatus = apply_rewrite_list(r, conf->rewriterules, NULL); + rulestatus = apply_rewrite_list(r, conf->rewriterules, NULL, + &uricheck); apr_table_set(r->notes,"mod_rewrite_rewritten", apr_psprintf(r->pool,"%d",rulestatus)); } @@ -4363,6 +4371,23 @@ static int hook_uri2file(request_rec *r) return HTTP_FORBIDDEN; } + /* If the rewrite involved PROXY, and the URI seems to risk + * causing an issue mentioned in CVE-2011-4317, then + * FORBID the request. Just disabling the related [P] rewriterule + * could cause a later rule to run with unexpected results. + * Only do the blocking if the executed last rule was PROXY + */ + if (r->uri[0] != '/') { + if (strncmp(r->uri, "http://" , 7) != 0 && + strncmp(r->uri, "https://", 8 )!= 0 && + uricheck == 1) { + rewritelog((r, 2, NULL, + "uri %s is considered a proxy security risk", + r->uri ? r->uri : "")); + return HTTP_FORBIDDEN; + } + } + if (rulestatus == ACTION_NOESCAPE) { apr_table_setn(r->notes, "proxy-nocanon", "1"); } @@ -4521,6 +4546,8 @@ static int hook_fixup(request_rec *r) int n; char *ofilename; int is_proxyreq; + int uricheck=0; /* True if the URI should be made to pass extra checks */ + dconf = (rewrite_perdir_conf *)ap_get_module_config(r->per_dir_config, &rewrite_module); @@ -4595,7 +4622,8 @@ static int hook_fixup(request_rec *r) /* * now apply the rules ... */ - rulestatus = apply_rewrite_list(r, dconf->rewriterules, dconf->directory); + rulestatus = apply_rewrite_list(r, dconf->rewriterules, dconf->directory, + &uricheck); if (rulestatus) { unsigned skip;