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!"


Reply via email to