diff options
author | Mario Sergio Fujikawa Ferreira <lioux@FreeBSD.org> | 2003-03-25 04:23:11 +0000 |
---|---|---|
committer | Mario Sergio Fujikawa Ferreira <lioux@FreeBSD.org> | 2003-03-25 04:23:11 +0000 |
commit | 0025bdf0b2935e18a51f4a900650754c207175a5 (patch) | |
tree | 7843767d8e7a5f47abe9adc65b6afa236e27f1d4 /www/mod_auth_any | |
parent | Bump PORTREVISION by updating audio/speex. (diff) |
o Fix vulnerability that allows execution of arbitrary commands on
the server with the uid of the apache process. Background [1]:
"The module accepts a username and password from the web client,
passes them to a user-space executable (using popen(3), which invokes
a shell) and waits for a response in order to authenticate the user.
The password is quoted on the popen() command line to avoid
interpretation of shell special chars, but the username is not.
Thus a malicious user can execute commands by supplying an appropriately
crafted username. (e.g. "foo&mail me@my.home</etc/passwd")
"The problem is easily fixed by adding quotes (and escaping any
quotes already present) to the username and password in the popen
command line."
o Fix this by adding a escaping function from [2]. Then, modifying
this function appropriately with ideas from [3]. Apply the new
escaping code to mod_auth_any.
o Bump PORTREVISION
Submitted by: Security Officer (nectar),
Red Hat Security Response Team <security@redhat.com> [1]
Obtained from: mod_auth_any CVS [2],
nalin@redhat.com [3]
Notes
Notes:
svn path=/head/; revision=77439
Diffstat (limited to 'www/mod_auth_any')
-rw-r--r-- | www/mod_auth_any/Makefile | 5 | ||||
-rw-r--r-- | www/mod_auth_any/files/bash_single_quote_escape_string.c | 45 | ||||
-rw-r--r-- | www/mod_auth_any/files/patch-mod_auth_any.c | 37 |
3 files changed, 87 insertions, 0 deletions
diff --git a/www/mod_auth_any/Makefile b/www/mod_auth_any/Makefile index 9616135cb8f3..50a0c52c2028 100644 --- a/www/mod_auth_any/Makefile +++ b/www/mod_auth_any/Makefile @@ -7,6 +7,7 @@ PORTNAME= mod_auth_any PORTVERSION= 1.0.2 +PORTREVISION= 1 CATEGORIES= www MASTER_SITES= ftp://ftp.itlab.musc.edu/pub/toolbox/mod_auth_any/ EXTRACT_SUFX= .tgz @@ -20,6 +21,10 @@ RUN_DEPENDS= ${APXS}:${APACHE_PORT} APXS?= ${LOCALBASE}/sbin/apxs APACHE_PORT?= ${PORTSDIR}/www/apache13 +post-patch: + @${CAT} ${FILESDIR}/bash_single_quote_escape_string.c >> \ + ${WRKSRC}/${PORTNAME}.c + do-build: @cd ${WRKSRC} && ${APXS} -c ${PORTNAME}.c diff --git a/www/mod_auth_any/files/bash_single_quote_escape_string.c b/www/mod_auth_any/files/bash_single_quote_escape_string.c new file mode 100644 index 000000000000..439b205c4426 --- /dev/null +++ b/www/mod_auth_any/files/bash_single_quote_escape_string.c @@ -0,0 +1,45 @@ +/* Escape special characters in the input string so that the bash + shell will not interpolate them when the input string is withing + single quotes. + + IN: null-terminated character array containing string to be interpolated + OUT: newly allocate (using malloc) null-terminated character array + containing the input string with the special characters properly + escaped */ +char* bash_single_quote_escape_string(const char *s) { + /* used to count the length of the string and the number of single quotes */ + int str_len, sq_count; + int s_pos, buf_pos; /* copy chars loop counter */ + /* used to hold the final result string */ + char *buf; + const char *escapees = "\"'\\$~` \t|&;()<>"; + + /* Count the single quotes. + LOOP INVARIANT: str_len < (number of chars in string 's') + POSTCONDITION: sq_count == (number of single quotes in string 's') */ + for (str_len = 0, sq_count = 0; s[str_len] != '\0'; str_len++) + if (strchr(escapees, s[str_len]) != NULL) + sq_count++; + + /* Allocate the memory for the final string. + Each ' (one char) will become \' (2 chars), so multiply by 2 + and don't forget to add 1 for terminating null. */ + buf = (char*) malloc(sizeof(char) * (str_len + 1 + sq_count * 2)); + + /* Copy the chars of 's' into 'buf', turning each ' into \' */ + for (s_pos = 0, buf_pos = 0; s_pos < str_len; s_pos++) { + /* If we see a single quote, then put '\'' into 'buf' and advance + buf_pos 4 positions, else put the next char from 's' into 'buf' + and advance buf_pos 1 position. */ + if(strchr(escapees, s[s_pos]) != NULL) { + buf[buf_pos++] = '\\'; + buf[buf_pos++] = s[s_pos]; + } else { + buf[buf_pos++] = s[s_pos]; + } + } + /* don't forget the null terminator */ + buf[buf_pos] = '\0'; + + return buf; +} diff --git a/www/mod_auth_any/files/patch-mod_auth_any.c b/www/mod_auth_any/files/patch-mod_auth_any.c new file mode 100644 index 000000000000..e234b8517b10 --- /dev/null +++ b/www/mod_auth_any/files/patch-mod_auth_any.c @@ -0,0 +1,37 @@ +--- mod_auth_any.c.orig Tue Jan 9 05:48:20 2001 ++++ mod_auth_any.c Tue Mar 25 01:09:55 2003 +@@ -121,6 +121,7 @@ + + */ + ++char* bash_single_quote_escape_string(const char *); + + /* NB: debugging stuff */ + extern int errno; +@@ -180,13 +181,25 @@ + const char *rpw, *w; + FILE* ext_authprog; + FILE* fp; ++ char *escaped_user, *escaped_password; + + l = (char*) malloc (MAX_STRING_LEN * sizeof(char)); ++ memset (l, '\0', MAX_STRING_LEN); + execstr = (char*) malloc (MAX_STRING_LEN * sizeof(char)); + + setenv ("REMOTE_ADDR", r -> connection -> remote_ip, 1); ++ ++ /* escape the user name and the password */ ++ escaped_user = bash_single_quote_escape_string(user); ++ escaped_password = bash_single_quote_escape_string(password); ++ + /* open the program stream */ +- snprintf (execstr, MAX_STRING_LEN, "%s %s \"%s\"", auth_pwfile, user, password); ++ snprintf (execstr, MAX_STRING_LEN, "%s %s %s", auth_pwfile, escaped_user, escaped_password); ++ ++ /* free the escaped user and password before we forget */ ++ free(escaped_user); ++ free(escaped_password); ++ + if (!(ext_authprog = popen (execstr, "r"))) { + + ap_log_rerror (APLOG_MARK, APLOG_ERR, r, "Could not popen() on program: %s: %s", |