From: André Malo Date: Sun, 14 Dec 2003 18:16:50 +0000 (+0000) Subject: SECURITY [CAN-2003-0020]: escape arbitrary data before writing into the X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=349bffbdc916690b9633d59e32754452b9baaf92;p=thirdparty%2Fapache%2Fhttpd.git SECURITY [CAN-2003-0020]: escape arbitrary data before writing into the errorlog. Reviewed by: Mark J Cox, Erik Abele, Jeff Trawick git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@102061 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/CHANGES b/src/CHANGES index c10ca8c60b5..461337f7241 100644 --- a/src/CHANGES +++ b/src/CHANGES @@ -1,5 +1,8 @@ Changes with Apache 1.3.30 + *) SECURITY [CAN-2003-0020]: Escape arbitrary data before writing + into the errorlog. [André Malo] + *) '%X' is now accepted as an alias for '%c' in the LogFormat directive. This allows you to configure logging to still log the connection status even with mod_ssl diff --git a/src/include/ap_mmn.h b/src/include/ap_mmn.h index 19185fbcccb..70cb1c78183 100644 --- a/src/include/ap_mmn.h +++ b/src/include/ap_mmn.h @@ -243,6 +243,7 @@ * ap_note_cleanups_for_file_ex(), * ap_popenf_ex() and ap_psocket_ex(). * 19990320.15 - ap_is_recursion_limit_exceeded() + * 19990320.16 - ap_escape_errorlog_item() */ #define MODULE_MAGIC_COOKIE 0x41503133UL /* "AP13" */ @@ -250,7 +251,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 19990320 #endif -#define MODULE_MAGIC_NUMBER_MINOR 15 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 16 /* 0...n */ /* Useful for testing for features. */ #define AP_MODULE_MAGIC_AT_LEAST(major,minor) \ diff --git a/src/include/httpd.h b/src/include/httpd.h index 5d6a985bf5e..1be4eeafa97 100644 --- a/src/include/httpd.h +++ b/src/include/httpd.h @@ -1028,6 +1028,8 @@ API_EXPORT(char *) ap_escape_html(pool *p, const char *s); API_EXPORT(char *) ap_construct_server(pool *p, const char *hostname, unsigned port, const request_rec *r); API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str); +API_EXPORT(size_t) ap_escape_errorlog_item(char *dest, const char *source, + size_t buflen); API_EXPORT(char *) ap_escape_shell_cmd(pool *p, const char *s); API_EXPORT(int) ap_count_dirs(const char *path); diff --git a/src/main/http_log.c b/src/main/http_log.c index 9906c2006a4..6b20424b7fc 100644 --- a/src/main/http_log.c +++ b/src/main/http_log.c @@ -313,7 +313,7 @@ static void log_error_core(const char *file, int line, int level, const server_rec *s, const request_rec *r, const char *fmt, va_list args) { - char errstr[MAX_STRING_LEN]; + char errstr[MAX_STRING_LEN], scratch[MAX_STRING_LEN]; size_t len; int save_errno = errno; FILE *logf; @@ -445,7 +445,10 @@ static void log_error_core(const char *file, int line, int level, } #endif - len += ap_vsnprintf(errstr + len, sizeof(errstr) - len, fmt, args); + if (ap_vsnprintf(scratch, sizeof(scratch) - len, fmt, args)) { + len += ap_escape_errorlog_item(errstr + len, scratch, + sizeof(errstr) - len); + } /* NULL if we are logging to syslog */ if (logf) { diff --git a/src/main/util.c b/src/main/util.c index 9ef1f348413..5c0df87b540 100644 --- a/src/main/util.c +++ b/src/main/util.c @@ -1520,6 +1520,69 @@ API_EXPORT(char *) ap_escape_logitem(pool *p, const char *str) return ret; } +API_EXPORT(size_t) ap_escape_errorlog_item(char *dest, const char *source, + size_t buflen) +{ + unsigned char *d, *ep; + const unsigned char *s; + + if (!source || !buflen) { /* be safe */ + return 0; + } + + d = (unsigned char *)dest; + s = (const unsigned char *)source; + ep = d + buflen - 1; + + for (; d < ep && *s; ++s) { + + if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) { + *d++ = '\\'; + if (d >= ep) { + --d; + break; + } + + switch(*s) { + case '\b': + *d++ = 'b'; + break; + case '\n': + *d++ = 'n'; + break; + case '\r': + *d++ = 'r'; + break; + case '\t': + *d++ = 't'; + break; + case '\v': + *d++ = 'v'; + break; + case '\\': + *d++ = *s; + break; + case '"': /* no need for this in error log */ + d[-1] = *s; + break; + default: + if (d >= ep - 2) { + ep = --d; /* break the for loop as well */ + break; + } + c2x(*s, d); + *d = 'x'; + d += 3; + } + } + else { + *d++ = *s; + } + } + *d = '\0'; + + return (d - (unsigned char *)dest); +} API_EXPORT(char *) ap_escape_shell_cmd(pool *p, const char *str) {