okey, here is the patch. i have been unable to detect any
security flaws in my testing. please apply and test this
as fixing the existing issue in a 'good enough' way until
a rework/redesign of the filesystem intertwingling is addressed.
in addition to 2.1 (where it might become obviated by a
better solution), i would like to put this into 2.0 and
possibly 1.3. and, if it doesn't open any security exposures,
i don't see why that shouldn't happen.
Index: include/ap_mmn.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/ap_mmn.h,v
retrieving revision 1.52
diff -u -r1.52 ap_mmn.h
--- include/ap_mmn.h 3 Sep 2002 23:39:43 -0000 1.52
+++ include/ap_mmn.h 14 Jan 2003 16:49:53 -0000
@@ -111,6 +111,7 @@
* 20020625 (2.0.40-dev) Changed conn_rec->keepalive to an enumeration
* 20020628 (2.0.40-dev) Added filter_init to filter registration functions
* 20020903 (2.0.41-dev) APR's error constants changed
+ * 20020903.1 (2.0.44-dev) allow_encoded_slashes added to core_dir_config
*/
#define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */
@@ -118,7 +119,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20020903
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 1 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
Index: include/http_core.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/http_core.h,v
retrieving revision 1.71
diff -u -r1.71 http_core.h
--- include/http_core.h 15 Dec 2002 20:05:23 -0000 1.71
+++ include/http_core.h 14 Jan 2003 16:49:53 -0000
@@ -539,7 +539,8 @@
#define ENABLE_SENDFILE_ON (1)
#define ENABLE_SENDFILE_UNSET (2)
unsigned int enable_sendfile : 2; /* files in this dir can be mmap'ed */
-
+ unsigned int allow_encoded_slashes : 1; /* URLs may contain %2f w/o being
+ * pitched indiscriminately */
} core_dir_config;
/* Per-server core configuration */
Index: include/httpd.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/httpd.h,v
retrieving revision 1.191
diff -u -r1.191 httpd.h
--- include/httpd.h 8 Nov 2002 17:19:10 -0000 1.191
+++ include/httpd.h 14 Jan 2003 16:49:53 -0000
@@ -1314,10 +1314,16 @@
/**
* Unescape a URL
- * @param url The url to unescapte
+ * @param url The url to unescape
* @return 0 on success, non-zero otherwise
*/
AP_DECLARE(int) ap_unescape_url(char *url);
+/**
+ * Unescape a URL, but leaving %2f (slashes) escaped
+ * @param url The url to unescape
+ * @return 0 on success, non-zero otherwise
+ */
+AP_DECLARE(int) ap_unescape_url_keep2f(char *url);
/**
* Convert all double slashes to single slashes
* @param name The string to convert
Index: server/core.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/core.c,v
retrieving revision 1.227
diff -u -r1.227 core.c
--- server/core.c 14 Jan 2003 03:01:51 -0000 1.227
+++ server/core.c 14 Jan 2003 16:49:54 -0000
@@ -182,6 +182,7 @@
conf->enable_mmap = ENABLE_MMAP_UNSET;
conf->enable_sendfile = ENABLE_SENDFILE_UNSET;
+ conf->allow_encoded_slashes = 0;
return (void *)conf;
}
@@ -452,6 +453,8 @@
conf->enable_sendfile = new->enable_sendfile;
}
+ conf->allow_encoded_slashes = new->allow_encoded_slashes;
+
return (void*)conf;
}
@@ -2087,6 +2090,19 @@
return NULL;
}
+static const char *set_allow2f(cmd_parms *cmd, void *d_, int arg)
+{
+ core_dir_config *d = d_;
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+
+ if (err != NULL) {
+ return err;
+ }
+
+ d->allow_encoded_slashes = arg != 0;
+ return NULL;
+}
+
static const char *set_hostname_lookups(cmd_parms *cmd, void *d_,
const char *arg)
{
@@ -3080,6 +3096,8 @@
AP_INIT_ITERATE2("AddOutputFilterByType", add_ct_output_filters,
(void *)APR_OFFSETOF(core_dir_config, ct_output_filters), OR_FILEINFO,
"output filter name followed by one or more content-types"),
+AP_INIT_FLAG("AllowEncodedSlashes", set_allow2f, NULL, RSRC_CONF,
+ "Allow URLs containing '/' encoded as '%2F'"),
/*
* These are default configuration directives that mpms can/should
Index: server/request.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/request.c,v
retrieving revision 1.122
diff -u -r1.122 request.c
--- server/request.c 12 Dec 2002 07:05:54 -0000 1.122
+++ server/request.c 14 Jan 2003 16:49:54 -0000
@@ -147,13 +147,22 @@
/* Ignore embedded %2F's in path for proxy requests */
if (!r->proxyreq && r->parsed_uri.path) {
- access_status = ap_unescape_url(r->parsed_uri.path);
+ core_dir_config *d;
+ d = ap_get_module_config(r->per_dir_config, &core_module);
+ if (d->allow_encoded_slashes) {
+ access_status = ap_unescape_url_keep2f(r->parsed_uri.path);
+ }
+ else {
+ access_status = ap_unescape_url(r->parsed_uri.path);
+ }
if (access_status) {
if (access_status == HTTP_NOT_FOUND) {
- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
- "found %%2f (encoded '/') in URI "
- "(decoded='%s'), returning 404",
- r->parsed_uri.path);
+ if (! d->allow_encoded_slashes) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
+ "found %%2f (encoded '/') in URI "
+ "(decoded='%s'), returning 404",
+ r->parsed_uri.path);
+ }
}
return access_status;
}
Index: server/util.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/util.c,v
retrieving revision 1.134
diff -u -r1.134 util.c
--- server/util.c 8 Dec 2002 21:05:57 -0000 1.134
+++ server/util.c 14 Jan 2003 16:49:54 -0000
@@ -1595,6 +1595,57 @@
return OK;
}
+AP_DECLARE(int) ap_unescape_url_keep2f(char *url)
+{
+ register int badesc, badpath;
+ char *x, *y;
+
+ badesc = 0;
+ badpath = 0;
+ /* Initial scan for first '%'. Don't bother writing values before
+ * seeing a '%' */
+ y = strchr(url, '%');
+ if (y == NULL) {
+ return OK;
+ }
+ for (x = y; *y; ++x, ++y) {
+ if (*y != '%') {
+ *x = *y;
+ }
+ else {
+ if (!apr_isxdigit(*(y + 1)) || !apr_isxdigit(*(y + 2))) {
+ badesc = 1;
+ *x = '%';
+ }
+ else {
+ char decoded;
+ decoded = x2c(y + 1);
+ if (IS_SLASH(decoded)) {
+ *x++ = *y++;
+ *x = *y;
+ }
+ else {
+ *x = decoded;
+ y += 2;
+ if (decoded == '\0') {
+ badpath = 1;
+ }
+ }
+ }
+ }
+ }
+ *x = '\0';
+ if (badesc) {
+ return HTTP_BAD_REQUEST;
+ }
+ else if (badpath) {
+ return HTTP_NOT_FOUND;
+ }
+ else {
+ return OK;
+ }
+}
+
AP_DECLARE(char *) ap_construct_server(apr_pool_t *p, const char *hostname,
apr_port_t port, const request_rec *r)
{
--
#ken P-)}
Ken Coar, Sanagendamgagwedweinini http://Golux.Com/coar/
Author, developer, opinionist http://Apache-Server.Com/
"Millennium hand and shrimp!"