diff -u lighttpd-1.4.13~r1370/debian/changelog lighttpd-1.4.13~r1370/debian/changelog --- lighttpd-1.4.13~r1370/debian/changelog +++ lighttpd-1.4.13~r1370/debian/changelog @@ -1,3 +1,28 @@ +lighttpd (1.4.13~r1370-1ubuntu1.2) edgy-security; urgency=low + + * SECURITY UPDATE: remote crash on duplicate header keys with line-wrapping, + various mod_auth bugs, mod_access bug and mod_fastcgi local DOS bug + (LP:#127718) + * debian/patches/06_security_lighttpd-1.4.x_duplicated_headers_with_folding_crash.dpatch: + - Fixes header parsing bug (Lighttpd SA 2007:03) + - Description: http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_03.txt + - Patch: http://www.lighttpd.net/assets/2007/7/24/lighttpd-1.4.x_duplicated_headers_with_folding_crash.patch + * debian/patches/07_security_lighttpd-1.4.x_mod_auth_sec.dpatch: + - Fixes various mod_auth bugs (Lighttpd SA 2007:04-07) + - Description: http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_04.txt, + http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_05.txt, + http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_06.txt, + http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_07.txt + - Patch: http://www.lighttpd.net/assets/2007/7/24/lighttpd-1.4.x_mod_auth_sec.patch + * debian/patches/08_security_lighttpd-1.4.x_mod_access_bypass.dpatch: + - Fixes mod_access bug (Lighttpd SA 2007:08) + - Description: http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_08.txt + - Patch: http://www.lighttpd.net/assets/2007/7/24/lighttpd-1.4.x_mod_access_bypass.patch + * References: + - http://www.lighttpd.net/2007/7/24/1-4-16-let-s-ship-it summarizes + - External references: http://secunia.com/advisories/26130/ + -- Aron Sisak Wed, 08 Aug 2007 12:53:07 +0200 + lighttpd (1.4.13~r1370-1ubuntu1.1) edgy-security; urgency=low * Added security fixes from 1.4.14 (Closes LP: #107628) diff -u lighttpd-1.4.13~r1370/debian/patches/00list lighttpd-1.4.13~r1370/debian/patches/00list --- lighttpd-1.4.13~r1370/debian/patches/00list +++ lighttpd-1.4.13~r1370/debian/patches/00list @@ -2,0 +3,3 @@ +06_security_lighttpd-1.4.x_duplicated_headers_with_folding_crash.dpatch +07_security_lighttpd-1.4.x_mod_auth_sec.dpatch +08_security_lighttpd-1.4.x_mod_access_bypass.dpatch only in patch2: unchanged: --- lighttpd-1.4.13~r1370.orig/debian/patches/06_security_lighttpd-1.4.x_duplicated_headers_with_folding_crash.dpatch +++ lighttpd-1.4.13~r1370/debian/patches/06_security_lighttpd-1.4.x_duplicated_headers_with_folding_crash.dpatch @@ -0,0 +1,129 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 06_security_lighttpd-1.4.x_duplicated_headers_with_folding_crash.dpatch by Aron Sisak +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: Fixes header parsing bug (Lighttpd SA 2007:03) +## DP: * http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_03.txt +## DP: * http://www.lighttpd.net/assets/2007/7/24/lighttpd-1.4.x_duplicated_headers_with_folding_crash.patch + +@DPATCH@ +diff -urNad lighttpd-1.4.13~/src/request.c lighttpd-1.4.13/src/request.c +--- lighttpd-1.4.13~/src/request.c 2006-10-04 15:29:17.000000000 +0200 ++++ lighttpd-1.4.13/src/request.c 2007-08-08 11:49:39.195051857 +0200 +@@ -281,8 +281,6 @@ + + int done = 0; + +- data_string *ds = NULL; +- + /* + * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$" + * Option : "^([-a-zA-Z]+): (.+)$" +@@ -712,12 +710,24 @@ + switch(*cur) { + case '\r': + if (con->parse_request->ptr[i+1] == '\n') { ++ data_string *ds = NULL; ++ + /* End of Headerline */ + con->parse_request->ptr[i] = '\0'; + con->parse_request->ptr[i+1] = '\0'; + + if (in_folding) { +- if (!ds) { ++ buffer *key_b; ++ /** ++ * we use a evil hack to handle the line-folding ++ * ++ * As array_insert_unique() deletes 'ds' in the case of a duplicate ++ * ds points somewhere and we get a evil crash. As a solution we keep the old ++ * "key" and get the current value from the hash and append us ++ * ++ * */ ++ ++ if (!key || !key_len) { + /* 400 */ + + if (srv->srvconf.log_request_header_on_error) { +@@ -734,7 +744,15 @@ + con->response.keep_alive = 0; + return 0; + } +- buffer_append_string(ds->value, value); ++ ++ key_b = buffer_init(); ++ buffer_copy_string_len(key_b, key, key_len); ++ ++ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, key_b->ptr))) { ++ buffer_append_string(ds->value, value); ++ } ++ ++ buffer_free(key_b); + } else { + int s_len; + key = con->parse_request->ptr + first; +@@ -959,7 +977,12 @@ + first = i+1; + is_key = 1; + value = 0; +- key_len = 0; ++#if 0 ++ /** ++ * for Bug 1230 keep the key_len a live ++ */ ++ key_len = 0; ++#endif + in_folding = 0; + } else { + if (srv->srvconf.log_request_header_on_error) { +diff -urNad lighttpd-1.4.13~/tests/core-request.t lighttpd-1.4.13/tests/core-request.t +--- lighttpd-1.4.13~/tests/core-request.t 2006-10-05 11:10:49.000000000 +0200 ++++ lighttpd-1.4.13/tests/core-request.t 2007-08-08 11:49:39.195051857 +0200 +@@ -8,7 +8,7 @@ + + use strict; + use IO::Socket; +-use Test::More tests => 33; ++use Test::More tests => 36; + use LightyTest; + + my $tf = LightyTest->new(); +@@ -273,6 +273,38 @@ + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ]; + ok($tf->handle_http($t) == 0, 'uppercase filenames'); + ++$t->{REQUEST} = ( <{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ]; ++ok($tf->handle_http($t) == 0, '#1232 - duplicate headers with line-wrapping'); ++ ++$t->{REQUEST} = ( <{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ]; ++ok($tf->handle_http($t) == 0, '#1232 - duplicate headers with line-wrapping - test 2'); ++ ++$t->{REQUEST} = ( <{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ]; ++ok($tf->handle_http($t) == 0, '#1232 - duplicate headers with line-wrapping - test 3'); ++ ++ ++ + + ok($tf->stop_proc == 0, "Stopping lighttpd"); + only in patch2: unchanged: --- lighttpd-1.4.13~r1370.orig/debian/patches/07_security_lighttpd-1.4.x_mod_auth_sec.dpatch +++ lighttpd-1.4.13~r1370/debian/patches/07_security_lighttpd-1.4.x_mod_auth_sec.dpatch @@ -0,0 +1,117 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 07_lighttpd-1.4.x_mod_auth_sec.dpatch by Aron Sisak +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: Fixes various mod_auth bugs (Lighttpd SA 2007:04-07) +## DP: * http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_04.txt, +## DP: http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_05.txt, +## DP: http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_06.txt, +## DP: http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_07.txt +## DP: * http://www.lighttpd.net/assets/2007/7/24/lighttpd-1.4.x_mod_auth_sec.patch + +@DPATCH@ +diff -urNad lighttpd-1.4.13~/src/http_auth.c lighttpd-1.4.13/src/http_auth.c +--- lighttpd-1.4.13~/src/http_auth.c 2006-10-04 15:29:17.000000000 +0200 ++++ lighttpd-1.4.13/src/http_auth.c 2007-08-08 11:53:21.211381534 +0200 +@@ -830,7 +830,13 @@ + username = buffer_init(); + password = buffer_init(); + +- base64_decode(username, realm_str); ++ if (!base64_decode(username, realm_str)) { ++ buffer_free(username); ++ ++ log_error_write(srv, __FILE__, __LINE__, "sb", "decodeing base64-string failed", username); ++ ++ return 0; ++ } + + /* r2 == user:password */ + if (NULL == (pw = strchr(username->ptr, ':'))) { +@@ -966,7 +972,7 @@ + for (c = b->ptr; *c; c++) { + /* skip whitespaces */ + while (*c == ' ' || *c == '\t') c++; +- if (!c) break; ++ if (!*c) break; + + for (i = 0; dkv[i].key; i++) { + if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) { +@@ -1015,6 +1021,21 @@ + + log_error_write(srv, __FILE__, __LINE__, "s", + "digest: missing field"); ++ ++ buffer_free(b); ++ return -1; ++ } ++ ++ /** ++ * protect the md5-sess against missing cnonce and nonce ++ */ ++ if (algorithm && ++ 0 == strcasecmp(algorithm, "md5-sess") && ++ (!nonce || !cnonce)) { ++ log_error_write(srv, __FILE__, __LINE__, "s", ++ "digest: (md5-sess: missing field"); ++ ++ buffer_free(b); + return -1; + } + +diff -urNad lighttpd-1.4.13~/tests/mod-auth.t lighttpd-1.4.13/tests/mod-auth.t +--- lighttpd-1.4.13~/tests/mod-auth.t 2006-10-05 11:10:49.000000000 +0200 ++++ lighttpd-1.4.13/tests/mod-auth.t 2007-08-08 11:53:21.211381534 +0200 +@@ -8,7 +8,7 @@ + + use strict; + use IO::Socket; +-use Test::More tests => 10; ++use Test::More tests => 13; + use LightyTest; + + my $tf = LightyTest->new(); +@@ -93,6 +93,43 @@ + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ]; + ok($tf->handle_http($t) == 0, 'Digest-Auth: missing nc (noncecount instead), no crash'); + ++$t->{REQUEST} = ( <{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ]; ++ok($tf->handle_http($t) == 0, 'Basic-Auth: Invalid Base64'); ++ ++ ++$t->{REQUEST} = ( <{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ]; ++ok($tf->handle_http($t) == 0, 'Digest-Auth: md5-sess + missing cnonce'); ++ ++$t->{REQUEST} = ( <{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ]; ++ok($tf->handle_http($t) == 0, 'Digest-Auth: trailing WS'); ++ + + + ok($tf->stop_proc == 0, "Stopping lighttpd"); only in patch2: unchanged: --- lighttpd-1.4.13~r1370.orig/debian/patches/08_security_lighttpd-1.4.x_mod_access_bypass.dpatch +++ lighttpd-1.4.13~r1370/debian/patches/08_security_lighttpd-1.4.x_mod_access_bypass.dpatch @@ -0,0 +1,137 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 08_lighttpd-1.4.x_mod_access_bypass.dpatch by Aron Sisak +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: Fixes mod_access bug (Lighttpd SA 2007:08) +## DP: * http://www.lighttpd.net/assets/2007/7/24/lighttpd_sa2007_08.txt +## DP: * http://www.lighttpd.net/assets/2007/7/24/lighttpd-1.4.x_mod_access_bypass.patch + +@DPATCH@ +diff -urNad lighttpd-1.4.13~/src/mod_access.c lighttpd-1.4.13/src/mod_access.c +--- lighttpd-1.4.13~/src/mod_access.c 2006-10-04 15:29:17.000000000 +0200 ++++ lighttpd-1.4.13/src/mod_access.c 2007-08-08 11:57:53.231697846 +0200 +@@ -111,6 +111,15 @@ + } + #undef PATCH + ++/** ++ * URI handler ++ * ++ * we will get called twice: ++ * - after the clean up of the URL and ++ * - after the pathinfo checks are done ++ * ++ * this handles the issue of trailing slashes ++ */ + URIHANDLER_FUNC(mod_access_uri_handler) { + plugin_data *p = p_d; + int s_len; +@@ -122,28 +131,41 @@ + + s_len = con->uri.path->used - 1; + ++ if (con->conf.log_request_handling) { ++ log_error_write(srv, __FILE__, __LINE__, "s", ++ "-- mod_access_uri_handler called"); ++ } ++ + for (k = 0; k < p->conf.access_deny->used; k++) { + data_string *ds = (data_string *)p->conf.access_deny->data[k]; + int ct_len = ds->value->used - 1; ++ int denied = 0; + +- if (ct_len > s_len) continue; + ++ if (ct_len > s_len) continue; + if (ds->value->used == 0) continue; + + /* if we have a case-insensitive FS we have to lower-case the URI here too */ + + if (con->conf.force_lowercase_filenames) { + if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) { +- con->http_status = 403; +- +- return HANDLER_FINISHED; ++ denied = 1; + } + } else { + if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) { +- con->http_status = 403; ++ denied = 1; ++ } ++ } + +- return HANDLER_FINISHED; ++ if (denied) { ++ con->http_status = 403; ++ ++ if (con->conf.log_request_handling) { ++ log_error_write(srv, __FILE__, __LINE__, "sb", ++ "url denied as we match:", ds->value); + } ++ ++ return HANDLER_FINISHED; + } + } + +@@ -158,7 +180,8 @@ + + p->init = mod_access_init; + p->set_defaults = mod_access_set_defaults; +- p->handle_uri_clean = mod_access_uri_handler; ++ p->handle_uri_clean = mod_access_uri_handler; ++ p->handle_subrequest_start = mod_access_uri_handler; + p->cleanup = mod_access_free; + + p->data = NULL; +diff -urNad lighttpd-1.4.13~/tests/docroot/www/Makefile.am lighttpd-1.4.13/tests/docroot/www/Makefile.am +--- lighttpd-1.4.13~/tests/docroot/www/Makefile.am 2006-10-05 11:10:48.000000000 +0200 ++++ lighttpd-1.4.13/tests/docroot/www/Makefile.am 2007-08-08 11:57:53.231697846 +0200 +@@ -1,5 +1,5 @@ + EXTRA_DIST=cgi.php cgi.pl dummydir index.html index.txt phpinfo.php \ + redirect.php cgi-pathinfo.pl get-env.php get-server-env.php \ + nph-status.pl prefix.fcgi get-header.pl ssi.shtml get-post-len.pl \ +- exec-date.shtml ++ exec-date.shtml index.html~ + SUBDIRS=go indexfile expire +diff -urNad lighttpd-1.4.13~/tests/docroot/www/index.html~ lighttpd-1.4.13/tests/docroot/www/index.html~ +--- lighttpd-1.4.13~/tests/docroot/www/index.html~ 1970-01-01 01:00:00.000000000 +0100 ++++ lighttpd-1.4.13/tests/docroot/www/index.html~ 2007-08-08 11:57:53.231697846 +0200 +@@ -0,0 +1 @@ ++ +diff -urNad lighttpd-1.4.13~/tests/mod-access.t lighttpd-1.4.13/tests/mod-access.t +--- lighttpd-1.4.13~/tests/mod-access.t 2006-10-05 11:10:49.000000000 +0200 ++++ lighttpd-1.4.13/tests/mod-access.t 2007-08-08 11:57:53.231697846 +0200 +@@ -8,7 +8,7 @@ + + use strict; + use IO::Socket; +-use Test::More tests => 3; ++use Test::More tests => 4; + use LightyTest; + + my $tf = LightyTest->new(); +@@ -23,5 +23,12 @@ + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ]; + ok($tf->handle_http($t) == 0, 'forbid access to ...~'); + ++$t->{REQUEST} = ( <{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ]; ++ok($tf->handle_http($t) == 0, '#1230 - forbid access to ...~ - trailing slash'); ++ + ok($tf->stop_proc == 0, "Stopping lighttpd"); + +diff -urNad lighttpd-1.4.13~/tests/prepare.sh lighttpd-1.4.13/tests/prepare.sh +--- lighttpd-1.4.13~/tests/prepare.sh 2006-10-05 11:10:49.000000000 +0200 ++++ lighttpd-1.4.13/tests/prepare.sh 2007-08-08 11:57:53.231697846 +0200 +@@ -25,6 +25,7 @@ + # copy everything into the right places + cp $srcdir/docroot/www/*.html \ + $srcdir/docroot/www/*.php \ ++ $srcdir/docroot/www/*.html~ \ + $srcdir/docroot/www/*.pl \ + $srcdir/docroot/www/*.fcgi \ + $srcdir/docroot/www/*.shtml \