[17254] in bugtraq

home help back first fref pref prev next nref lref last post

Re: Security vulnerability in Apache mod_rewrite

daemon@ATHENA.MIT.EDU (Tony Finch)
Wed Oct 18 14:17:09 2000

Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Message-Id:  <20001018162749.F3582@hand.dotat.at>
Date:         Wed, 18 Oct 2000 16:27:49 +0000
Reply-To: Tony Finch <dot@DOTAT.AT>
From: Tony Finch <dot@DOTAT.AT>
To: BUGTRAQ@SECURITYFOCUS.COM
In-Reply-To:  <20001006154024.C4488@hand.dotat.at>

Since the Apache Group released 1.3.14 (which incorporates the
mod_rewrite security "fix") we have been informed that it breaks most
configurations that use RewriteMaps, because the lookup key is no
longer expanded. See <http://bugs.apache.org/index.cgi/full/6671>,
which includes a patch to restore the lost functionality. I have also
included the patch below.

Redistributors of Apache should update their packages to incorporate
1.3.14 with this patch.

Tony.
--
en oeccget g mtcaa    f.a.n.finch
v spdlkishrhtewe y    dot@dotat.at
eatp o v eiti i d.    fanf@covalent.net


? diff
Index: mod_rewrite.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_rewrite.c,v
retrieving revision 1.162
retrieving revision 1.163
diff -u -r1.162 -r1.163
--- mod_rewrite.c	2000/09/22 20:47:19	1.162
+++ mod_rewrite.c	2000/10/18 04:26:43	1.163
@@ -2258,30 +2258,50 @@
 	/* now we have a '$' or a '%' */
 	if (inp[1] == '{') {
 	    char *endp;
-	    endp = strchr(inp, '}');
+	    endp = find_closing_bracket(inp+2, '{', '}');
 	    if (endp == NULL) {
 		goto skip;
 	    }
 	    *endp = '\0';
 	    if (inp[0] == '$') {
 		/* ${...} map lookup expansion */
+		/*
+		 * To make rewrite maps useful the lookup key and
+		 * default values must be expanded, so we make
+		 * recursive calls to do the work. For security
+		 * reasons we must never expand a string that includes
+		 * verbatim data from the network. The recursion here
+		 * isn't a problem because the result of expansion is
+		 * only passed to lookup_map() so it cannot be
+		 * re-expanded, only re-looked-up. Another way of
+		 * looking at it is that the recursion is entirely
+		 * driven by the syntax of the nested curly brackets.
+		 */
 		char *key, *dflt, *result;
+		char xkey[MAX_STRING_LEN];
+		char xdflt[MAX_STRING_LEN];
+		char *empty = "";
 		key = strchr(inp, ':');
 		if (key == NULL) {
 		    goto skip;
 		}
 		*key++ = '\0';
 		dflt = strchr(key, '|');
-		if (dflt) {
+		if (dflt == NULL) {
+		    dflt = empty;
+		}
+		else {
 		    *dflt++ = '\0';
 		}
-		result = lookup_map(r, inp+2, key);
+		do_expand(r, key,  xkey,  sizeof(xkey),  briRR, briRC);
+		do_expand(r, dflt, xdflt, sizeof(xdflt), briRR, briRC);
+		result = lookup_map(r, inp+2, xkey);
 		if (result == NULL) {
-		    result = dflt ? dflt : "";
+		    result = xdflt;
 		}
 		span = ap_cpystrn(outp, result, space) - outp;
 		key[-1] = ':';
-		if (dflt) {
+		if (dflt != empty) {
 		    dflt[-1] = '|';
 		}
 	    }
@@ -4141,6 +4161,28 @@
         }
     }
     return 0;
+}
+
+/*
+**
+**  Find end of bracketed expression
+**  s points after the opening bracket
+**
+*/
+
+static char *find_closing_bracket(char *s, int left, int right)
+{
+    int depth;
+
+    for (depth = 1; *s; ++s) {
+	if (*s == right && --depth == 0) {
+	    return s;
+	}
+	else if (*s == left) {
+	    ++depth;
+	}
+    }
+    return NULL;
 }

 /*EOF*/
Index: mod_rewrite.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_rewrite.h,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- mod_rewrite.h	2000/09/29 17:32:32	1.72
+++ mod_rewrite.h	2000/10/18 04:26:43	1.73
@@ -496,6 +496,9 @@
     /* Lexicographic Comparison */
 static int compare_lexicography(char *cpNum1, char *cpNum2);

+    /* Find end of bracketed expression */
+static char *find_closing_bracket(char *s, int left, int right);
+
 #endif /* _MOD_REWRITE_H */

 /*EOF*/

home help back first fref pref prev next nref lref last post