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