fetchmail-SA-2010-02.txt 8.36 KB
Newer Older
Matthias Andree's avatar
Matthias Andree committed
1 2 3
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

4 5
fetchmail-SA-2010-02: Denial of service in debug mode w/ multichar locales

6
Topics:		Denial of service in debug output
7 8

Author:		Matthias Andree
9 10 11 12
Version:	1.0
Announced:	2010-05-06
Type:		Unbounded allocation of memory until exhaustion
Impact:		Denial of service
13 14
Danger:		low

15
CVE Name:	CVE-2010-1167
16 17 18
CVSSv2:		(AV:N/AC:M/Au:N/C:N/I:N/A:P/E:U/RL:O/RC:C)
CVSS scores:	3.2, Base 4.3 (Impact 2.9, Exploitability 8.6), Temporal 3.2
		This is calculated without Environmental Score.
19 20 21 22 23 24 25
URL:		http://www.fetchmail.info/fetchmail-SA-2010-02.txt
Project URL:	http://www.fetchmail.info/

Affects:	fetchmail releases 4.6.3 up to and including 6.3.16

Not affected:	fetchmail release 6.3.17 and newer

26 27 28 29 30 31 32
Corrected:	2010-04-24 Git, required commits:
		167fa2093e82f891eb2fcb6eaa0b1eb3685f44e3
		ec06293134b85876f9201d8a52b844c41581b2b3

		2010-04-30 fetchmail 6.3.17-pre1 tarball

		2010-05-06 fetchmail 6.3.17 release tarball
33 34 35 36 37 38


0. Release history
==================

2010-04-18 0.1	first draft (visible in SVN and through oss-security)
39
2010-04-19 0.2	add note announcements may appear before releases
40 41 42
2010-04-20 0.3	add CVE name, fix Type:
2010-04-24 0.4	revise patch
2010-04-29 0.5	add info on contributing/mitigating factors
43
2010-05-06 1.0	complete
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66


1. Background
=============

fetchmail is a software package to retrieve mail from remote POP2, POP3,
IMAP, ETRN or ODMR servers and forward it to local SMTP, LMTP servers or
message delivery agents. It supports SSL and TLS security layers through
the OpenSSL library, if enabled at compile time and if also enabled at
run time.


2. Problem description and Impact
=================================

In debug mode (-v -v), fetchmail prints information that was obtained from the
upstream server (POP3 UIDL lists) or from message headers retrieved from it.
  If printing such information fails, for instance because there are invalid
multibyte character sequences in this information (message headers), fetchmail
will misinterpret this condition, and believe that the buffer was too small,
and reallocate a bigger one (with linearly increasing buffer size), and repeat,
until the allocation fails. At that point, fetchmail will abort.

67 68 69 70 71 72
The exact combination of contributing and mitigating factors is not
fully understood; GNU glibc 2.7 and 2.10.1 on i586 report EILSEQ when
printing invalid sequences through a %.*s format string in multibyte
locales such as de_DE.UTF-8; NetBSD 5, FreeBSD 8 and Solaris 10 do not.
However, the issue is a genuine fetchmail bug that deserves a fix.

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
Note that the "Affects:" line above may be inaccurate, and it may be that
versions before 5.6.6 are actually unaffected.  The author was unable to
compile such old fetchmail versions to verify the existence of the bug.
  Given that other security issues are present in such versions, those should
not be used, and the wider version range was listed as vulnerable to err
towards the safe.


3. Solution
===========

There are two alternatives, either of them by itself is sufficient:

a. Apply the patch found in section B of this announcement to
   fetchmail 6.3.14 or newer, recompile and reinstall it.

b. Install fetchmail 6.3.17 or newer after it will have become available.
90 91
   (Note that the announcements may be publicly visible quite some time
   before the release is made, particularly for minor bugs.)
92
   The fetchmail source code is always available from
93
   <http://sourceforge.net/projects/fetchmail/files/>.
94 95 96 97 98 99 100 101 102 103 104 105 106 107


4. Workaround
=============

Run fetchmail with at most one -v (--verbose) option.


A. Copyright, License and Warranty
==================================

(C) Copyright 2010 by Matthias Andree, <[email protected]>.
Some rights reserved.

108 109 110
This work is licensed under the
Creative Commons Attribution-NoDerivs 3.0 Germany License (CC BY-ND 3.0).

111
To view a copy of this license, visit
112 113
http://creativecommons.org/licenses/by-nd/3.0/de/deed.en
or send a letter to:
114 115

Creative Commons
116 117 118
444 Castro Street
Suite 900
MOUNTAIN VIEW, CALIFORNIA 94041
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
USA


THIS WORK IS PROVIDED FREE OF CHARGE AND WITHOUT ANY WARRANTIES.
Use the information herein at your own risk.


B. Patch to remedy the problem
==============================

Note that when taking this from a GnuPG clearsigned file, the lines
starting with a "-" character are prefixed by another "- " (dash +
blank) combination. Either feed this file through GnuPG to strip them,
or strip them manually. You may want to use the "-p1" flag to patch.

Whitespace differences can usually be ignored by invoking "patch -l",
so try this if the patch does not apply.

diff --git a/rfc822.c b/rfc822.c
index 6f2dbf3..dbcda32 100644
Matthias Andree's avatar
Matthias Andree committed
139
- --- a/rfc822.c
140 141 142
+++ b/rfc822.c
@@ -25,6 +25,7 @@ MIT license.  Compile with -DMAIN to build the demonstrator.
 #include  <stdlib.h>
143

144 145
 #include "fetchmail.h"
+#include "sdump.h"
146

147 148 149 150
 #ifndef MAIN
 #include "i18n.h"
@@ -74,9 +75,10 @@ char *reply_hack(
     }
151

152
 #ifndef MAIN
Matthias Andree's avatar
Matthias Andree committed
153 154 155
- -    if (outlevel >= O_DEBUG)
- -	report_build(stdout, GT_("About to rewrite %.*s...\n"),
- -			(int)BEFORE_EOL(buf), buf);
156 157 158 159
+    if (outlevel >= O_DEBUG) {
+	report_build(stdout, GT_("About to rewrite %s...\n"), (cp = sdump(buf, BEFORE_EOL(buf))));
+	xfree(cp);
+    }
160

161 162 163 164
     /* make room to hack the address; buf must be malloced */
     for (cp = buf; *cp; cp++)
@@ -211,9 +213,12 @@ char *reply_hack(
     }
165

166
 #ifndef MAIN
Matthias Andree's avatar
Matthias Andree committed
167 168 169
- -    if (outlevel >= O_DEBUG)
- -	report_complete(stdout, GT_("...rewritten version is %.*s.\n"),
- -			(int)BEFORE_EOL(buf), buf);
170 171 172 173 174 175 176 177 178 179
+    if (outlevel >= O_DEBUG) {
+	report_complete(stdout, GT_("...rewritten version is %s.\n"),
+			(cp = sdump(buf, BEFORE_EOL(buf))));
+	xfree(cp)
+    }
+
 #endif /* MAIN */
     *length = strlen(buf);
     return(buf);
diff --git a/uid.c b/uid.c
180
index fdc6f5d..9a62ee2 100644
Matthias Andree's avatar
Matthias Andree committed
181
- --- a/uid.c
182 183
+++ b/uid.c
@@ -20,6 +20,7 @@
184

185 186 187
 #include "fetchmail.h"
 #include "i18n.h"
+#include "sdump.h"
188

189 190
 /*
  * Machinery for handling UID lists live here.  This is mainly to support
191 192
@@ -249,8 +250,11 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
 	    {
193
 		report_build(stdout, GT_("Old UID list from %s:"),
194
 			     ctl->server.pollname);
Matthias Andree's avatar
Matthias Andree committed
195 196
- -		for (idp = ctl->oldsaved; idp; idp = idp->next)
- -		    report_build(stdout, " %s", idp->id);
197 198 199 200 201 202 203 204 205
+		for (idp = ctl->oldsaved; idp; idp = idp->next) {
+		    char *t = sdump(idp->id, strlen(idp->id));
+		    report_build(stdout, " %s", t);
+		    free(t);
+		}
 		if (!idp)
 		    report_build(stdout, GT_(" <empty>"));
 		report_complete(stdout, "\n");
@@ -260,8 +264,11 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
206 207 208
 	if (uidlcount)
 	{
 	    report_build(stdout, GT_("Scratch list of UIDs:"));
Matthias Andree's avatar
Matthias Andree committed
209 210
- -	    for (idp = scratchlist; idp; idp = idp->next)
- -		report_build(stdout, " %s", idp->id);
211 212 213 214 215 216 217 218
+	    for (idp = scratchlist; idp; idp = idp->next) {
+		char *t = sdump(idp->id, strlen(idp->id));
+		report_build(stdout, " %s", t);
+		free(t);
+	    }
 	    if (!idp)
 		report_build(stdout, GT_(" <empty>"));
 	    report_complete(stdout, "\n");
219
@@ -517,8 +524,11 @@ void uid_swap_lists(struct query *ctl)
220 221 222
 	    report_build(stdout, GT_("Merged UID list from %s:"), ctl->server.pollname);
 	else
 	    report_build(stdout, GT_("New UID list from %s:"), ctl->server.pollname);
Matthias Andree's avatar
Matthias Andree committed
223 224
- -	for (idp = dofastuidl ? ctl->oldsaved : ctl->newsaved; idp; idp = idp->next)
- -	    report_build(stdout, " %s = %d", idp->id, idp->val.status.mark);
225 226 227 228 229 230 231 232
+	for (idp = dofastuidl ? ctl->oldsaved : ctl->newsaved; idp; idp = idp->next) {
+	    char *t = sdump(idp->id, strlen(idp->id));
+	    report_build(stdout, " %s = %d", t, idp->val.status.mark);
+	    free(t);
+        }
 	if (!idp)
 	    report_build(stdout, GT_(" <empty>"));
 	report_complete(stdout, "\n");
233
@@ -567,8 +577,11 @@ void uid_discard_new_list(struct query *ctl)
234 235 236
 	/* this is now a merged list! the mails which were seen in this
 	 * poll are marked here. */
 	report_build(stdout, GT_("Merged UID list from %s:"), ctl->server.pollname);
Matthias Andree's avatar
Matthias Andree committed
237 238
- -	for (idp = ctl->oldsaved; idp; idp = idp->next)
- -	    report_build(stdout, " %s = %d", idp->id, idp->val.status.mark);
239 240 241 242 243 244 245 246
+	for (idp = ctl->oldsaved; idp; idp = idp->next) {
+	    char *t = sdump(idp->id, strlen(idp->id));
+	    report_build(stdout, " %s = %d", t, idp->val.status.mark);
+	    free(t);
+	}
 	if (!idp)
 	    report_build(stdout, GT_(" <empty>"));
 	report_complete(stdout, "\n");
Matthias Andree's avatar
Matthias Andree committed
247
-----BEGIN PGP SIGNATURE-----
248
Version: GnuPG v1.4.11 (GNU/Linux)
Matthias Andree's avatar
Matthias Andree committed
249

250 251 252
iEYEARECAAYFAlN9DK4ACgkQvmGDOQUufZUKUACeOl0QLdcl48bttiIEOF5XKRCF
wxQAnigEIYE6BlJQ17CSjZ4KfigM3oK6
=culN
Matthias Andree's avatar
Matthias Andree committed
253
-----END PGP SIGNATURE-----