summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2004-06-07 04:21:31 +0000
committerBrad Smith <brad@cvs.openbsd.org>2004-06-07 04:21:31 +0000
commit5471e36167ce7726986a9671756bec18dbc3f751 (patch)
tree2a520d1ea7522c843d22df094752d5ce8ba571eb
parent9f3dbbea2f319a65018b490ed540ee11c380cfb6 (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.h2
-rw-r--r--usr.sbin/httpd/src/main/http_log.c12
-rw-r--r--usr.sbin/httpd/src/main/util.c63
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)
{