[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#991119: unblock: postsrsd/1.10-2



Hi

On 2021-07-17 19:49:05 +0200, Sebastian Ramacher wrote:
> Control: tags -1 confirmed moreinfo
> 
> On 2021-07-14 21:48:50, Oxan van Leeuwen wrote:
> > Package: release.debian.org
> > Severity: normal
> > User: release.debian.org@packages.debian.org
> > Usertags: unblock
> > 
> > Please unblock package postsrsd
> > 
> > [ Reason ]
> > Security fix for CVE-2021-35525.
> > 
> > [ Impact ]
> > Package is vulnerable to a potential DoS attack.
> > 
> > [ Tests ]
> > Tests from upstream backported, testsuite from upstream passes, manually tested 
> > functionality.
> > 
> > [ Risks ]
> > Fix is a one-to-one backport from upstream, modulus formatting changes.
> > 
> > [ Checklist ]
> >   [x] all changes are documented in the d/changelog
> >   [x] I reviewed all changes and I approve them
> >   [x] attach debdiff against the package in testing
> > 
> > [ Other info ]
> > N/A
> > 
> > unblock postsrsd/1.10-2
> 
> If this is a pre-approval request, please go ahead and remove the
> moreinfo tag once the new version is available in unstable.

Ping. The window for getting this upload into the initial release of
bullseye is closing.

Cheers

> 
> Cheers
> 
> 
> > diff -Nru postsrsd-1.10/debian/changelog postsrsd-1.10/debian/changelog
> > --- postsrsd-1.10/debian/changelog	2020-12-02 22:36:36.000000000 +0100
> > +++ postsrsd-1.10/debian/changelog	2021-07-14 21:21:11.000000000 +0200
> > @@ -1,4 +1,12 @@
> > -postsrsd (1.10-1) UNRELEASED; urgency=medium
> > +postsrsd (1.10-2) UNRELEASED; urgency=medium
> > +
> > +  * Fix CVE-2021-35525: potential DoS when Postfix sends certain long data
> > +    fields such as multiple concatenated email addresses. Fix backported from
> > +    upstream commit 077be98d8c8. (Closes: #990439)
> > +
> > + -- Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>  Wed, 14 Jul 2021 21:21:11 +0200
> > +
> > +postsrsd (1.10-1) unstable; urgency=medium
> >  
> >    * New upstream release (Closes: #975633)
> >    * Drop patches integrated upstream
> > diff -Nru postsrsd-1.10/debian/patches/0002-SECURITY-Fix-DoS-on-overly-long-input-from-Postfix.patch postsrsd-1.10/debian/patches/0002-SECURITY-Fix-DoS-on-overly-long-input-from-Postfix.patch
> > --- postsrsd-1.10/debian/patches/0002-SECURITY-Fix-DoS-on-overly-long-input-from-Postfix.patch	1970-01-01 01:00:00.000000000 +0100
> > +++ postsrsd-1.10/debian/patches/0002-SECURITY-Fix-DoS-on-overly-long-input-from-Postfix.patch	2021-07-14 21:21:11.000000000 +0200
> > @@ -0,0 +1,211 @@
> > +From: =?utf-8?q?Timo_R=C3=B6hling?= <timo@gaussglocke.de>
> > +Date: Sun, 21 Mar 2021 15:27:55 +0100
> > +Subject: SECURITY: Fix DoS on overly long input from Postfix
> > +MIME-Version: 1.0
> > +Content-Type: text/plain; charset="utf-8"
> > +Content-Transfer-Encoding: 8bit
> > +
> > +Thanks to Mateusz Jończyk who reported this issue and gave valuable
> > +feedback for its resolution.
> > +
> > +PostSRSd would hang on an overly long GET request, because the
> > +fread()/fwrite() logic in the subprocess would get confused by the
> > +remaining input line in its buffer.
> > +
> > +Theoretically, this error should never occur, as Postfix is supposed to
> > +send valid email addresses only, which are shorter than the buffer, even
> > +assuming every single character is percent-encoded. However, Postfix
> > +sometimes does seem to send malformed request with multiple concatenated
> > +email addresses. I'm not sure if there's a reliable way to trigger this
> > +condition by an external attacker, but it is a security bug in PostSRSd
> > +nevertheless.
> > +
> > +Fixes CVE-2021-35525.
> > +
> > +Origin: https://github.com/roehling/postsrsd/commit/077be98d8c8a9847e4ae0c7dc09e7474cbe27db2
> > +Forwarded: not-needed
> > +Last-Update: 2021-07-14
> > +---
> > + postsrsd.c              | 52 ++++++++++++++++++++++++++++++-------------------
> > + run_postsrsd_tests.bats | 40 +++++++++++++++++++++++++++++++++----
> > + 2 files changed, 68 insertions(+), 24 deletions(-)
> > +
> > +diff --git a/postsrsd.c b/postsrsd.c
> > +index c009d8f..5ebf7f6 100644
> > +--- a/postsrsd.c
> > ++++ b/postsrsd.c
> > +@@ -518,9 +518,9 @@ int main (int argc, char **argv)
> > +     fds[sc].events = POLLIN;
> > +   }
> > +   while(TRUE) {
> > +     int conn;
> > +-    FILE *fp;
> > ++    FILE *fp_read, *fp_write;
> > +     char linebuf[1024], *line;
> > +     char keybuf[1024], *key;
> > + 
> > +     if (poll(fds, socket_count, 1000) < 0) {
> > +@@ -540,41 +540,53 @@ int main (int argc, char **argv)
> > +           int i;
> > +           // close listen sockets so that we don't stop the main daemon process from restarting
> > +           for (i = 0; i < socket_count; ++i) close (sockets[i]);
> > + 
> > +-          fp = fdopen(conn, "r+");
> > +-          if (fp == NULL) exit(EXIT_FAILURE);
> > +-          fds[0].fd = conn;
> > +-          fds[0].events = POLLIN;
> > +-          if (poll(fds, 1, timeout * 1000) <= 0) return EXIT_FAILURE;
> > +-          line = fgets(linebuf, sizeof(linebuf), fp);
> > +-          while (line) {
> > +-            fseek (fp, 0, SEEK_CUR); /* Workaround for Solaris */
> > ++          /* create separate input/output streams */
> > ++          fp_read = fdopen(conn, "r");
> > ++          if (fp_read == NULL)
> > ++            return EXIT_FAILURE;
> > ++          fp_write = fdopen(dup(conn), "w");
> > ++          if (fp_write == NULL) return EXIT_FAILURE;
> > ++          errno = 0;
> > ++          alarm(timeout);
> > ++          if (errno != 0)
> > ++              return EXIT_FAILURE;
> > ++          while ((line = fgets(linebuf, sizeof(linebuf), fp_read))) {
> > +             char* token;
> > ++            alarm(0);
> > ++            if (strlen(line) >= sizeof(linebuf) - 1) {
> > ++              fprintf(fp_write, "500 Invalid request\n");
> > ++              fflush(fp_write);
> > ++              return EXIT_FAILURE;
> > ++            }
> > +             token = strtok(line, " \r\n");
> > +             if (token == NULL || strcmp(token, "get") != 0) {
> > +-              fprintf (fp, "500 Invalid request\n");
> > +-              fflush (fp);
> > ++              fprintf (fp_write, "500 Invalid request\n");
> > ++              fflush (fp_write);
> > +               return EXIT_FAILURE;
> > +             }
> > +             token = strtok(NULL, "\r\n");
> > +             if (!token) {
> > +-              fprintf (fp, "500 Invalid request\n");
> > +-              fflush (fp);
> > ++              fprintf (fp_write, "500 Invalid request\n");
> > ++              fflush (fp_write);
> > +               return EXIT_FAILURE;
> > +             }
> > +             key = url_decode(keybuf, sizeof(keybuf), token);
> > +             if (!key) {
> > +-              fprintf (fp, "500 Invalid request\n");
> > +-              fflush(fp);
> > ++              fprintf (fp_write, "500 Invalid request\n");
> > ++              fflush(fp_write);
> > +               return EXIT_FAILURE;
> > +             }
> > +-            handler[sc](srs, fp, key, domain, excludes);
> > +-            fflush (fp);
> > +-            if (poll(fds, 1, timeout * 1000) <= 0) break;
> > +-            line = fgets(linebuf, sizeof(linebuf), fp);
> > ++            handler[sc](srs, fp_write, key, domain, excludes);
> > ++            fflush (fp_write);
> > ++            errno = 0;
> > ++            alarm(timeout);
> > ++            if (errno != 0)
> > ++              return EXIT_FAILURE;
> > +           }
> > +-          fclose (fp);
> > ++          fclose (fp_write);
> > ++          fclose (fp_read);
> > +           return EXIT_SUCCESS;
> > +         }
> > +         close (conn);
> > +       }
> > +diff --git a/run_postsrsd_tests.bats b/run_postsrsd_tests.bats
> > +index f4b04bb..3d52a50 100755
> > +--- a/run_postsrsd_tests.bats
> > ++++ b/run_postsrsd_tests.bats
> > +@@ -2,9 +2,9 @@
> > + # vim: filetype=bash:
> > + 
> > + if [ ! -x "$POSTSRSD" ]
> > + then
> > +-	for builddir in . build* obj*
> > ++	for builddir in . build* obj* _build*
> > + 	do
> > + 		if [ -x "${builddir}/postsrsd" ]
> > + 		then
> > + 			POSTSRSD="${builddir}/postsrsd"
> > +@@ -14,9 +14,9 @@ then
> > + fi
> > + if [ ! -x "$POSTSRSD" ]
> > + then
> > + 	cat>&2 <<- EOF
> > +-	cannot find postsrsd executable (looked in ., build*, obj*)
> > ++	cannot find postsrsd executable (looked in ., build*, obj*, _build*)
> > + 	please build the executable first, or set the POSTSRSD
> > + 	environment variable if it is in a different location.
> > + 
> > + 	EOF
> > +@@ -25,14 +25,21 @@ fi
> > + 
> > + LANG=C.UTF-8
> > + 
> > + 
> > ++fillchar()
> > ++{
> > ++        local count="$1"
> > ++        local char="$2"
> > ++        eval 'printf "'"$char"'%.0s" {1..'"$count"'}'
> > ++}
> > ++
> > + start_postsrsd_at()
> > + {
> > + 	echo 'tops3cr3t' > "$BATS_TMPDIR/postsrsd.secret"
> > + 	local faketime="$1"
> > + 	shift
> > +-	faketime "${faketime}" ${POSTSRSD} -D -f 10001 -r 10002 -p "$BATS_TMPDIR/postsrsd.pid" -s "$BATS_TMPDIR/postsrsd.secret" -d example.com "$@"
> > ++	faketime "${faketime}" ${POSTSRSD} -D -t1 -f 10001 -r 10002 -p "$BATS_TMPDIR/postsrsd.pid" -s "$BATS_TMPDIR/postsrsd.secret" -d example.com "$@"
> > + }
> > + 
> > + stop_postsrsd()
> > + {
> > +@@ -158,9 +165,9 @@ teardown()
> > + 	read<&9 line
> > + 	[[ "$line" =~ ^"500 Domain excluded" ]]
> > + }
> > + 
> > +-@test "SRS invalid requests" {
> > ++@test "Malformed or invalid requests" {
> > + 	start_postsrsd_at "2020-01-01 00:01:00 UTC"
> > + 	exec 9<>/dev/tcp/127.0.0.1/10001
> > + 	echo>&9 "get"
> > + 	read<&9 line
> > +@@ -172,5 +179,30 @@ teardown()
> > + 	exec 9<>/dev/tcp/127.0.0.1/10001
> > + 	echo>&9 "get encoding%error@otherdomain.com"
> > + 	read<&9 line
> > + 	[[ "$line" =~ ^500 ]]
> > ++	exec 9<>/dev/tcp/127.0.0.1/10001
> > ++	# Try to overflow the input buffer
> > ++	echo>&9 "get too_long@`fillchar 1024 a`.com"
> > ++	read<&9 line
> > ++	[[ "$line" =~ ^500 ]]
> > ++}
> > ++
> > ++@test "Pipelining multiple requests" {
> > ++	start_postsrsd_at "2020-01-01 00:01:00 UTC"
> > ++	exec 9<>/dev/tcp/127.0.0.1/10001
> > ++	# Send two requests at once and see if PostSRSd answers both
> > ++	echo>&9 -e "get test@domain1.com\nget test@domain2.com"
> > ++	read<&9 line
> > ++	[[ "$line" =~ ^200 ]]
> > ++	read<&9 line
> > ++	[[ "$line" =~ ^200 ]]
> > ++}
> > ++
> > ++@test "Session timeout" {
> > ++	start_postsrsd_at "2020-01-01 00:01:00 UTC"
> > ++	exec 9<>/dev/tcp/127.0.0.1/10001
> > ++	# Wait until PostSRSd disconnects due to inactivity
> > ++	sleep 2
> > ++	echo >&9 "get test@example.com"
> > ++	! read <&9 line
> > + }
> > diff -Nru postsrsd-1.10/debian/patches/series postsrsd-1.10/debian/patches/series
> > --- postsrsd-1.10/debian/patches/series	2020-12-02 22:36:36.000000000 +0100
> > +++ postsrsd-1.10/debian/patches/series	2021-07-14 21:21:11.000000000 +0200
> > @@ -1 +1,2 @@
> >  0001-Run-as-postsrsd-user-by-default.patch
> > +0002-SECURITY-Fix-DoS-on-overly-long-input-from-Postfix.patch
> 
> 
> -- 
> Sebastian Ramacher
> 

-- 
Sebastian Ramacher

Attachment: signature.asc
Description: PGP signature


Reply to: