escape all strings for logging (fixes #2646 log file injection, reported by Jaanus Kääp)

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
This commit is contained in:
Stefan Bühler 2015-05-28 15:47:14 +00:00
parent 33cebeb0f7
commit 427120b41a
4 changed files with 70 additions and 7 deletions

5
NEWS
View File

@ -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]

View File

@ -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;

View File

@ -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) )

View File

@ -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);