diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2004-06-07 04:21:31 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2004-06-07 04:21:31 +0000 |
commit | 5471e36167ce7726986a9671756bec18dbc3f751 (patch) | |
tree | 2a520d1ea7522c843d22df094752d5ce8ba571eb | |
parent | 9f3dbbea2f319a65018b490ed540ee11c380cfb6 (diff) |
Apache does not filter terminal escape sequences from its error logs, which
could make it easier for attackers to insert those sequences into terminal
emulators containing vulnerabilities related to escape sequences.
CAN-2003-0020
ok henning@
-rw-r--r-- | usr.sbin/httpd/src/include/httpd.h | 2 | ||||
-rw-r--r-- | usr.sbin/httpd/src/main/http_log.c | 12 | ||||
-rw-r--r-- | usr.sbin/httpd/src/main/util.c | 63 |
3 files changed, 76 insertions, 1 deletions
diff --git a/usr.sbin/httpd/src/include/httpd.h b/usr.sbin/httpd/src/include/httpd.h index 3dd3bb44c3b..3e2f6ec6bd8 100644 --- a/usr.sbin/httpd/src/include/httpd.h +++ b/usr.sbin/httpd/src/include/httpd.h @@ -1072,6 +1072,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/usr.sbin/httpd/src/main/http_log.c b/usr.sbin/httpd/src/main/http_log.c index 21d00c95d2d..fcd019d165a 100644 --- a/usr.sbin/httpd/src/main/http_log.c +++ b/usr.sbin/httpd/src/main/http_log.c @@ -1,4 +1,4 @@ -/* $OpenBSD: http_log.c,v 1.14 2003/08/21 13:11:35 henning Exp $ */ +/* $OpenBSD: http_log.c,v 1.15 2004/06/07 04:21:30 brad Exp $ */ /* ==================================================================== * The Apache Software License, Version 1.1 @@ -316,6 +316,9 @@ static void log_error_core(const char *file, int line, int level, const char *fmt, va_list args) { char errstr[MAX_STRING_LEN]; +#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED + char scratch[MAX_STRING_LEN]; +#endif size_t len; int save_errno = errno; FILE *logf; @@ -447,7 +450,14 @@ static void log_error_core(const char *file, int line, int level, } #endif +#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED + if (ap_vsnprintf(scratch, sizeof(scratch) - len, fmt, args)) { + len += ap_escape_errorlog_item(errstr + len, scratch, + sizeof(errstr) - len); + } +#else len += ap_vsnprintf(errstr + len, sizeof(errstr) - len, fmt, args); +#endif /* NULL if we are logging to syslog */ if (logf) { diff --git a/usr.sbin/httpd/src/main/util.c b/usr.sbin/httpd/src/main/util.c index 9151379ea3f..f7cb18f8fdd 100644 --- a/usr.sbin/httpd/src/main/util.c +++ b/usr.sbin/httpd/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) { |