diff options
Diffstat (limited to 'main/lighttpd/0029-escape-all-strings-for-logging-fixes-2646-log-file-i.patch')
-rw-r--r-- | main/lighttpd/0029-escape-all-strings-for-logging-fixes-2646-log-file-i.patch | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/main/lighttpd/0029-escape-all-strings-for-logging-fixes-2646-log-file-i.patch b/main/lighttpd/0029-escape-all-strings-for-logging-fixes-2646-log-file-i.patch new file mode 100644 index 0000000000..20307fb204 --- /dev/null +++ b/main/lighttpd/0029-escape-all-strings-for-logging-fixes-2646-log-file-i.patch @@ -0,0 +1,174 @@ +From 427120b41a141626dbb40a752c848f199fc9f7a8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20B=C3=BChler?= <stbuehler@web.de> +Date: Thu, 28 May 2015 15:47:14 +0000 +Subject: [PATCH 29/29] =?UTF-8?q?escape=20all=20strings=20for=20logging=20?= + =?UTF-8?q?(fixes=20#2646=20log=20file=20injection,=20reported=20by=20Jaan?= + =?UTF-8?q?us=20K=C3=A4=C3=A4p)?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Stefan Bühler <stbuehler@web.de> + +git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2989 152afb58-edef-0310-8abb-c4023f1b3aa9 +--- + NEWS | 5 +++-- + src/buffer.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/buffer.h | 5 ++++- + src/log.c | 8 ++++---- + 4 files changed, 70 insertions(+), 7 deletions(-) + +diff --git a/NEWS b/NEWS +index dd2d1b8..18007fc 100644 +--- a/NEWS ++++ b/NEWS +@@ -19,6 +19,7 @@ NEWS + * [mod_auth] use crypt_r instead of crypt if available + * fix error message for T_CONFIG_ARRAY config values if an entry value is not a string + * fix segfaults in many plugins if they failed configuration ++ * escape all strings for logging (fixes #2646 log file injection, reported by Jaanus Kääp) + + - 1.4.35 - 2014-03-12 + * [network/ssl] fix build error if TLSEXT is disabled +@@ -557,10 +558,10 @@ NEWS + * ignore empty packets from STDERR stream. #998 + * fix a crash for files with an mtime of 0 reported by cubiq on irc [1519] + CVE-2007-1870 +- * allow empty passwords with ldap (Jörg Sonnenberger) [1516] ++ * allow empty passwords with ldap (Jörg Sonnenberger) [1516] + * mod_scgi.c segfault fix #964 [1501] + * Added round-robin support to mod_fastcgi [1500] +- * Handle DragonFlyBSD the same way as Freebsd (Jörg Sonnenberger) [1492,1676] ++ * Handle DragonFlyBSD the same way as Freebsd (Jörg Sonnenberger) [1492,1676] + * added now and weeks support to mod_expire. #943 + * fix cpu hog in certain requests [1473] CVE-2007-1869 + * fix for handling hostnames with trailing dot [1406] +diff --git a/src/buffer.c b/src/buffer.c +index 57c1613..36995a0 100644 +--- a/src/buffer.c ++++ b/src/buffer.c +@@ -731,6 +731,65 @@ void buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer + } + } + ++void buffer_append_string_c_escaped(buffer *b, const char *s, size_t s_len) { ++ unsigned char *ds, *d; ++ size_t d_len, ndx; ++ ++ force_assert(NULL != b); ++ force_assert(NULL != s || 0 == s_len); ++ ++ if (0 == s_len) return; ++ ++ /* count to-be-encoded-characters */ ++ for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) { ++ if ((*ds < 0x20) /* control character */ ++ || (*ds >= 0x7f)) { /* DEL + non-ASCII characters */ ++ switch (*ds) { ++ case '\t': ++ case '\r': ++ case '\n': ++ d_len += 2; ++ break; ++ default: ++ d_len += 4; /* \xCC */ ++ break; ++ } ++ } else { ++ d_len++; ++ } ++ } ++ ++ d = (unsigned char*) buffer_string_prepare_append(b, d_len); ++ buffer_commit(b, d_len); /* fill below */ ++ force_assert('\0' == *d); ++ ++ for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) { ++ if ((*ds < 0x20) /* control character */ ++ || (*ds >= 0x7f)) { /* DEL + non-ASCII characters */ ++ d[d_len++] = '\\'; ++ switch (*ds) { ++ case '\t': ++ d[d_len++] = 't'; ++ break; ++ case '\r': ++ d[d_len++] = 'r'; ++ break; ++ case '\n': ++ d[d_len++] = 'n'; ++ break; ++ default: ++ d[d_len++] = 'x'; ++ d[d_len++] = hex_chars[((*ds) >> 4) & 0x0F]; ++ d[d_len++] = hex_chars[(*ds) & 0x0F]; ++ break; ++ } ++ } else { ++ d[d_len++] = *ds; ++ } ++ } ++} ++ ++ + void buffer_copy_string_encoded_cgi_varnames(buffer *b, const char *s, size_t s_len, int is_http_header) { + size_t i, j; + +diff --git a/src/buffer.h b/src/buffer.h +index b6065d4..5f659df 100644 +--- a/src/buffer.h ++++ b/src/buffer.h +@@ -133,6 +133,9 @@ typedef enum { + + void buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer_encoding_t encoding); + ++/* escape non-printable characters; simple escapes for \t, \r, \n; fallback to \xCC */ ++void buffer_append_string_c_escaped(buffer *b, const char *s, size_t s_len); ++ + /* to upper case, replace non alpha-numerics with '_'; if is_http_header prefix with "HTTP_" unless s is "content-type" */ + void buffer_copy_string_encoded_cgi_varnames(buffer *b, const char *s, size_t s_len, int is_http_header); + +@@ -164,7 +167,7 @@ static inline void buffer_append_slash(buffer *b); /* append '/' no non-empty st + buffer_copy_string_len(x, y, sizeof(y) - 1) + + #define CONST_STR_LEN(x) x, (x) ? sizeof(x) - 1 : 0 +-#define CONST_BUF_LEN(x) (x)->ptr, buffer_string_length(x) ++#define CONST_BUF_LEN(x) ((x) ? (x)->ptr : NULL), buffer_string_length(x) + + + #define UNUSED(x) ( (void)(x) ) +diff --git a/src/log.c b/src/log.c +index 9322d2c..94f4710 100644 +--- a/src/log.c ++++ b/src/log.c +@@ -267,12 +267,12 @@ static void log_buffer_append_printf(buffer *out, const char *fmt, va_list ap) { + switch(*fmt) { + case 's': /* string */ + s = va_arg(ap, char *); +- buffer_append_string(out, s); ++ buffer_append_string_c_escaped(out, s, (NULL != s) ? strlen(s) : 0); + buffer_append_string_len(out, CONST_STR_LEN(" ")); + break; + case 'b': /* buffer */ + b = va_arg(ap, buffer *); +- buffer_append_string_buffer(out, b); ++ buffer_append_string_c_escaped(out, CONST_BUF_LEN(b)); + buffer_append_string_len(out, CONST_STR_LEN(" ")); + break; + case 'd': /* int */ +@@ -293,11 +293,11 @@ static void log_buffer_append_printf(buffer *out, const char *fmt, va_list ap) { + break; + case 'S': /* string */ + s = va_arg(ap, char *); +- buffer_append_string(out, s); ++ buffer_append_string_c_escaped(out, s, (NULL != s) ? strlen(s) : 0); + break; + case 'B': /* buffer */ + b = va_arg(ap, buffer *); +- buffer_append_string_buffer(out, b); ++ buffer_append_string_c_escaped(out, CONST_BUF_LEN(b)); + break; + case 'D': /* int */ + d = va_arg(ap, int); +-- +2.4.5 + |