</dd>
</dl>
+
+ <dt><code>AllowAnyURI</code></dt>
+ <dd>
+
+ <p>When <directive module="mod_rewrite">RewriteRule</directive>
+ is used in <code>VirtualHost</code> or server context with
+ version 2.2.22 or later of httpd, <module>mod_rewrite</module>
+ will only process the rewrite rules if the request URI is a <a
+ href="./directive-dict.html#Syntax">URL-path</a>. This avoids
+ some security issues where particular rules could allow
+ "surprising" pattern expansions (see <a
+ href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3368">CVE-2011-3368</a>
+ and <a
+ href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4317">CVE-2011-4317</a>).
+ To lift the restriction on matching a URL-path, the
+ <code>AllowAnyURI</code> option can be enabled, and
+ <module>mod_rewrite</module> will apply the rule set to any
+ request URI string, regardless of whether that string matches
+ the URL-path grammar required by the HTTP specification.</p>
+
+ <note type="warning">
+ <title>Security Warning</title>
+
+ <p>Enabling this option will make the server vulnerable to
+ security issues if used with rewrite rules which are not
+ carefully authored. It is <strong>strongly recommended</strong>
+ that this option is not used. In particular, beware of input
+ strings containing the '<code>@</code>' character which could
+ change the interpretation of the transformed URI, as per the
+ above CVE names.</p>
+ </note>
+ </dd>
+
+ </dl>
+
</usage>
</directivesynopsis>
#define OPTION_NONE 1<<0
#define OPTION_INHERIT 1<<1
+#define OPTION_ANYURI 1<<4
#ifndef RAND_MAX
#define RAND_MAX 32767
apr_array_header_t *rewriteconds; /* the RewriteCond entries (temp.) */
apr_array_header_t *rewriterules; /* the RewriteRule entries */
server_rec *server; /* the corresponding server indicator */
+ unsigned int state_set:1;
+ unsigned int options_set:1;
} rewrite_server_conf;
typedef struct {
apr_array_header_t *rewriterules; /* the RewriteRule entries */
char *directory; /* the directory where it applies */
const char *baseurl; /* the base-URL where it applies */
+ unsigned int state_set:1;
+ unsigned int options_set:1;
+ unsigned int baseurl_set:1;
} rewrite_perdir_conf;
/* the (per-child) cache structures.
base = (rewrite_server_conf *)basev;
overrides = (rewrite_server_conf *)overridesv;
- a->state = overrides->state;
- a->options = overrides->options;
+ a->state = (overrides->state_set == 0) ? base->state : overrides->state;
+ a->state_set = overrides->state_set || base->state_set;
+ a->options = (overrides->options_set == 0) ? base->options : overrides->options;
+ a->options_set = overrides->options_set || base->options_set;
+
a->server = overrides->server;
if (a->options & OPTION_INHERIT) {
base = (rewrite_perdir_conf *)basev;
overrides = (rewrite_perdir_conf *)overridesv;
- a->state = overrides->state;
- a->options = overrides->options;
- a->directory = overrides->directory;
- a->baseurl = overrides->baseurl;
+ a->state = (overrides->state_set == 0) ? base->state : overrides->state;
+ a->state_set = overrides->state_set || base->state_set;
+ a->options = (overrides->options_set == 0) ? base->options : overrides->options;
+ a->options_set = overrides->options_set || base->options_set;
+ a->baseurl = (overrides->baseurl_set == 0) ? base->baseurl : overrides->baseurl;
+ a->baseurl_set = overrides->baseurl_set || base->baseurl_set;
+
+ a->directory = overrides->directory;
if (a->options & OPTION_INHERIT) {
a->rewriteconds = apr_array_append(p, overrides->rewriteconds,
sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module);
- if (cmd->path == NULL) { /* is server command */
+ /* server command? set both global scope and base directory scope */
+ if (cmd->path == NULL) {
sconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED);
+ sconf->state_set = 1;
+ dconf->state = sconf->state;
+ dconf->state_set = 1;
}
- else /* is per-directory command */ {
+ /* directory command? set directory scope only */
+ else {
dconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED);
+ dconf->state_set = 1;
}
return NULL;
"LimitInternalRecursion directive and will be "
"ignored.");
}
+ else if (!strcasecmp(w, "allowanyuri")) {
+ options |= OPTION_ANYURI;
+ }
else {
return apr_pstrcat(cmd->pool, "RewriteOptions: unknown option '",
w, "'", NULL);
}
}
- /* put it into the appropriate config */
+ /* server command? set both global scope and base directory scope */
if (cmd->path == NULL) { /* is server command */
- rewrite_server_conf *conf =
+ rewrite_perdir_conf *dconf = in_dconf;
+ rewrite_server_conf *sconf =
ap_get_module_config(cmd->server->module_config,
&rewrite_module);
- conf->options |= options;
+ sconf->options |= options;
+ sconf->options_set = 1;
+ dconf->options |= options;
+ dconf->options_set = 1;
}
+ /* directory command? set directory scope only */
else { /* is per-directory command */
- rewrite_perdir_conf *conf = in_dconf;
+ rewrite_perdir_conf *dconf = in_dconf;
- conf->options |= options;
+ dconf->options |= options;
+ dconf->options_set = 1;
}
return NULL;
}
dconf->baseurl = a1;
+ dconf->baseurl_set = 1;
return NULL;
}
*/
static int hook_uri2file(request_rec *r)
{
+ rewrite_perdir_conf *dconf;
rewrite_server_conf *conf;
const char *saved_rulestatus;
const char *var;
*/
conf = ap_get_module_config(r->server->module_config, &rewrite_module);
+ dconf = (rewrite_perdir_conf *)ap_get_module_config(r->per_dir_config,
+ &rewrite_module);
+
/*
* only do something under runtime if the engine is really enabled,
* else return immediately!
*/
- if (conf->state == ENGINE_DISABLED) {
+ if (!dconf || dconf->state == ENGINE_DISABLED) {
return DECLINED;
}
return DECLINED;
}
- if ((r->unparsed_uri[0] == '*' && r->unparsed_uri[1] == '\0')
- || !r->uri || r->uri[0] != '/') {
+ /* Unless the anyuri option is set, ensure that the input to the
+ * first rule really is a URL-path, avoiding security issues with
+ * poorly configured rules. See CVE-2011-3368, CVE-2011-4317. */
+ if ((dconf->options & OPTION_ANYURI) == 0
+ && ((r->unparsed_uri[0] == '*' && r->unparsed_uri[1] == '\0')
+ || !r->uri || r->uri[0] != '/')) {
+ rewritelog((r, 8, NULL, "Declining, request-URI '%s' is not a URL-path. "
+ "Consult the manual entry for the RewriteOptions directive "
+ "for options and caveats about matching other strings.",
+ r->uri));
return DECLINED;
}
* only do something under runtime if the engine is really enabled,
* for this directory, else return immediately!
*/
- if (dconf->state == ENGINE_DISABLED) {
+ if (!dconf || dconf->state == ENGINE_DISABLED) {
return DECLINED;
}