Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/libexec/httpd updates and bozohttpd 20160415:



details:   https://anonhg.NetBSD.org/src/rev/83588d660666
branches:  trunk
changeset: 344753:83588d660666
user:      mrg <mrg%NetBSD.org@localhost>
date:      Fri Apr 15 17:57:21 2016 +0000

description:
updates and bozohttpd 20160415:
o  add search-word support for CGI
o  fix a security issue in CGI suffix handler support which would
   allow remote code execution, from shm%netbsd.org@localhost
o  -C option supports now CGI scripts only

diffstat:

 libexec/httpd/CHANGES     |    6 +
 libexec/httpd/bozohttpd.8 |    7 +-
 libexec/httpd/bozohttpd.c |   20 ++--
 libexec/httpd/bozohttpd.h |    3 +-
 libexec/httpd/cgi-bozo.c  |  183 +++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 193 insertions(+), 26 deletions(-)

diffs (truncated from 376 to 300 lines):

diff -r 0e3e6e1b8ae8 -r 83588d660666 libexec/httpd/CHANGES
--- a/libexec/httpd/CHANGES     Fri Apr 15 17:55:58 2016 +0000
+++ b/libexec/httpd/CHANGES     Fri Apr 15 17:57:21 2016 +0000
@@ -1,5 +1,11 @@
 $eterna: CHANGES,v 1.78 2011/11/18 01:25:11 mrg Exp $
 
+changes in bozohttpd 20160415:
+       o  add search-word support for CGI
+       o  fix a security issue in CGI suffix handler support which would
+          allow remote code execution, from shm%netbsd.org@localhost
+       o  -C option supports now CGI scripts only
+
 changes in bozohttpd 20151028:
        o  add CGI support for ~user translation (-E switch)
        o  add redirects to ~user translation
diff -r 0e3e6e1b8ae8 -r 83588d660666 libexec/httpd/bozohttpd.8
--- a/libexec/httpd/bozohttpd.8 Fri Apr 15 17:55:58 2016 +0000
+++ b/libexec/httpd/bozohttpd.8 Fri Apr 15 17:57:21 2016 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: bozohttpd.8,v 1.58 2015/12/27 10:21:35 mrg Exp $
+.\"    $NetBSD: bozohttpd.8,v 1.59 2016/04/15 17:57:21 mrg Exp $
 .\"
 .\"    $eterna: bozohttpd.8,v 1.101 2011/11/18 01:25:11 mrg Exp $
 .\"
@@ -507,7 +507,7 @@
 option to specify a CGI handler for a particular file type.
 Typically this will be like:
 .Bd -literal
-httpd -C .php /usr/pkg/bin/php /var/www
+httpd -C .php /usr/pkg/bin/php-cgi /var/www
 .Ed
 .Sh SEE ALSO
 .Xr inetd.conf 5 ,
@@ -615,7 +615,8 @@
 .Aq Mt shm%NetBSD.org@localhost
 fixed memory leaks, various issues with userdir support,
 information disclosure issues, added support for using CGI handlers
-with directory indexing and provided various other fixes.
+with directory indexing, found several security issues and provided
+various other fixes.
 .It
 .An Arnaud Lacombe
 .Aq Mt alc%NetBSD.org@localhost
diff -r 0e3e6e1b8ae8 -r 83588d660666 libexec/httpd/bozohttpd.c
--- a/libexec/httpd/bozohttpd.c Fri Apr 15 17:55:58 2016 +0000
+++ b/libexec/httpd/bozohttpd.c Fri Apr 15 17:57:21 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bozohttpd.c,v 1.79 2016/01/02 20:35:59 elric Exp $     */
+/*     $NetBSD: bozohttpd.c,v 1.80 2016/04/15 17:57:21 mrg Exp $       */
 
 /*     $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $      */
 
@@ -109,7 +109,7 @@
 #define INDEX_HTML             "index.html"
 #endif
 #ifndef SERVER_SOFTWARE
-#define SERVER_SOFTWARE                "bozohttpd/20151231"
+#define SERVER_SOFTWARE                "bozohttpd/20160415"
 #endif
 #ifndef DIRECT_ACCESS_FILE
 #define DIRECT_ACCESS_FILE     ".bzdirect"
@@ -1288,19 +1288,17 @@
 }
 
 /* this fixes the %HH hack that RFC2396 requires.  */
-static int
-fix_url_percent(bozo_httpreq_t *request)
+int
+bozo_decode_url_percent(bozo_httpreq_t *request, char *str)
 {
        bozohttpd_t *httpd = request->hr_httpd;
-       char    *s, *t, buf[3], *url;
+       char    *s, *t, buf[3];
        char    *end;   /* if end is not-zero, we don't translate beyond that */
 
-       url = request->hr_file;
-
-       end = url + strlen(url);
+       end = str + strlen(str);
 
        /* fast forward to the first % */
-       if ((s = strchr(url, '%')) == NULL)
+       if ((s = strchr(str, '%')) == NULL)
                return 0;
 
        t = s;
@@ -1352,7 +1350,7 @@
        } while (*s);
        *t = '\0';
 
-       debug((httpd, DEBUG_FAT, "fix_url_percent returns %s in url",
+       debug((httpd, DEBUG_FAT, "bozo_decode_url_percent returns `%s'",
                        request->hr_file));
 
        return 0;
@@ -1383,7 +1381,7 @@
        file = NULL;
        *isindex = 0;
        debug((httpd, DEBUG_FAT, "tf_req: file %s", request->hr_file));
-       if (fix_url_percent(request)) {
+       if (bozo_decode_url_percent(request, request->hr_file)) {
                goto bad_done;
        }
        if (check_virtual(request)) {
diff -r 0e3e6e1b8ae8 -r 83588d660666 libexec/httpd/bozohttpd.h
--- a/libexec/httpd/bozohttpd.h Fri Apr 15 17:55:58 2016 +0000
+++ b/libexec/httpd/bozohttpd.h Fri Apr 15 17:57:21 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bozohttpd.h,v 1.44 2016/01/02 18:40:13 elric Exp $     */
+/*     $NetBSD: bozohttpd.h,v 1.45 2016/04/15 17:57:21 mrg Exp $       */
 
 /*     $eterna: bozohttpd.h,v 1.39 2011/11/18 09:21:15 mrg Exp $       */
 
@@ -227,6 +227,7 @@
                          const char *);
 char   *bozo_escape_rfc3986(bozohttpd_t *httpd, const char *url, int absolute);
 char   *bozo_escape_html(bozohttpd_t *httpd, const char *url);
+int    bozo_decode_url_percent(bozo_httpreq_t *, char *);
 
 /* these are similar to libc functions, no underscore here */
 void   bozowarn(bozohttpd_t *, const char *, ...)
diff -r 0e3e6e1b8ae8 -r 83588d660666 libexec/httpd/cgi-bozo.c
--- a/libexec/httpd/cgi-bozo.c  Fri Apr 15 17:55:58 2016 +0000
+++ b/libexec/httpd/cgi-bozo.c  Fri Apr 15 17:57:21 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cgi-bozo.c,v 1.32 2015/12/31 04:39:16 mrg Exp $        */
+/*     $NetBSD: cgi-bozo.c,v 1.33 2016/04/15 17:57:21 mrg Exp $        */
 
 /*     $eterna: cgi-bozo.c,v 1.40 2011/11/18 09:21:15 mrg Exp $        */
 
@@ -212,6 +212,136 @@
                "append_index_html: url adjusted to `%s'", *url));
 }
 
+/* This function parse search-string according to section 4.4 of RFC3875 */
+static char **
+parse_search_string(bozo_httpreq_t *request, const char *query, size_t *args_len)
+{
+       struct  bozohttpd_t *httpd = request->hr_httpd;
+       size_t i;
+       char *s, *str, **args;
+       
+       *args_len = 0;
+
+       /* URI MUST not contain any unencoded '=' - RFC3875, section 4.4 */
+       if (strchr(query, '=')) {
+               return NULL;
+       }
+
+       str = bozostrdup(httpd, request, query);
+
+       /*
+        * there's no more arguments than '+' chars in the query string as it's
+        * the separator
+        */
+       *args_len = 1;
+       /* count '+' in str */
+       for (s = str; (s = strchr(s, '+')); (*args_len)++);
+       
+       args = bozomalloc(httpd, sizeof(*args) * (*args_len + 1));
+ 
+       args[0] = str;
+       args[*args_len] = NULL;
+       for (s = str, i = 0; (s = strchr(s, '+'));) {
+               *s = '\0';
+               s++;
+               args[i++] = s;
+       }
+
+       /*
+        * check if search-strings are valid:
+        *
+        * RFC3875, section 4.4:
+        *
+        * search-string = search-word *( "+" search-word )
+        * search-word   = 1*schar
+        * schar                 = unreserved | escaped | xreserved
+        * xreserved     = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "," |
+        *                 "$"
+        * 
+        * section 2.3:
+        *
+        * hex        = digit | "A" | "B" | "C" | "D" | "E" | "F" | "a" |
+        *              "b" | "c" | "d" | "e" | "f"
+        * escaped    = "%" hex hex
+        * unreserved = alpha | digit | mark
+        * mark       = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
+        *
+        * section 2.2:
+        *
+        * alpha        = lowalpha | hialpha
+        * lowalpha     = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" |
+        *                "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" |
+        *                "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" |
+        *                "y" | "z"
+        * hialpha      = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" |
+        *                "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" |
+        *                "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" |
+        *                "Y" | "Z"  
+        * digit        = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
+        *                "8" | "9"
+        */
+#define        UNRESERVED_CHAR "-_.!~*'()"
+#define        XRESERVED_CHAR  ";/?:@&=,$"
+
+       for (i = 0; i < *args_len; i++) {
+               s = args[i];
+               /* search-word MUST have at least one schar */
+               if (*s == '\0')
+                       goto parse_err;
+               while(*s) {
+                       /* check if it's unreserved */
+                       if (isalpha((int)*s) || isdigit((int)*s) ||
+                           strchr(UNRESERVED_CHAR, *s)) {
+                               s++;
+                               continue;
+                       }
+
+                       /* check if it's escaped */
+                       if (*s == '%') {
+                               if (s[1] == '\0' || s[2] == '\0')
+                                       goto parse_err;
+                               if (!isxdigit((int)s[1]) ||
+                                   !isxdigit((int)s[2]))
+                                       goto parse_err;
+                               s += 3;
+                               continue;
+                       }
+
+                       /* check if it's xreserved */
+
+                       if (strchr(XRESERVED_CHAR, *s)) {
+                               s++;
+                               continue;
+                       }
+
+                       goto parse_err;
+               }
+       }
+
+       /* decode percent encoding */
+       for (i = 0; i < *args_len; i++) {
+               if (bozo_decode_url_percent(request, args[i]))
+                       goto parse_err;
+       }
+
+       /* allocate each arg separately */
+       for (i = 0; i < *args_len; i++)
+               args[i] = bozostrdup(httpd, request, args[i]);
+       free(str);
+
+       return args;
+
+parse_err:
+
+       free (*args);
+       free (str);
+       *args = NULL;
+       *args_len = 0;
+
+       return 0;
+
+}
+
 void
 bozo_cgi_setbin(bozohttpd_t *httpd, const char *path)
 {
@@ -249,9 +379,9 @@
        bozoheaders_t *headp;
        const char *type, *clen, *info, *cgihandler;
        char    *query, *s, *t, *path, *env, *command, *file, *url;
-       char    **envp, **curenvp, *argv[4];
+       char    **envp, **curenvp, **argv, **search_string_argv = NULL;
        char    *uri;
-       size_t  len;
+       size_t  i, len, search_string_argc = 0;
        ssize_t rbytes;
        pid_t   pid;
        int     envpsize, ix, nph;
@@ -312,12 +442,25 @@
        } else if (len - 1 == CGIBIN_PREFIX_LEN)        /* url is "/cgi-bin/" */
                append_index_html(httpd, &file);
 
+       /* RFC3875  sect. 4.4. - search-string support */
+       if (query != NULL) {
+               search_string_argv = parse_search_string(request, query,
+                   &search_string_argc);
+       }
+
+       debug((httpd, DEBUG_NORMAL, "parse_search_string args no: %lu",
+           search_string_argc));
+       for (i = 0; i < search_string_argc; i++) {
+               debug((httpd, DEBUG_FAT,
+                   "search_string[%lu]: `%s'", i, search_string_argv[i]));
+       }
+
+       argv = bozomalloc(httpd, sizeof(*argv) * (3 + search_string_argc));
+
        ix = 0;
        if (cgihandler) {



Home | Main Index | Thread Index | Old Index