]> Pileus Git - ~andy/fetchmail/blob - fetchmail-SA-2010-02.txt
Fix history date in fetchmail-SA-2010-02.txt.
[~andy/fetchmail] / fetchmail-SA-2010-02.txt
1 fetchmail-SA-2010-02: Denial of service in debug mode w/ multichar locales
2
3 Topics:         Denial of service in debug output
4
5 Author:         Matthias Andree
6 Version:        1.0
7 Announced:      2010-05-06
8 Type:           Unbounded allocation of memory until exhaustion
9 Impact:         Denial of service
10 Danger:         low
11
12 CVE Name:       CVE-2010-1167
13 CVSSv2:         (AV:N/AC:M/Au:N/C:N/I:N/A:P/E:U/RL:O/RC:C)
14 CVSS scores:    3.2, Base 4.3 (Impact 2.9, Exploitability 8.6), Temporal 3.2
15                 This is calculated without Environmental Score.
16 URL:            http://www.fetchmail.info/fetchmail-SA-2010-02.txt
17 Project URL:    http://www.fetchmail.info/
18
19 Affects:        fetchmail releases 4.6.3 up to and including 6.3.16
20
21 Not affected:   fetchmail release 6.3.17 and newer
22
23 Corrected:      2010-04-24 Git, required commits:
24                 167fa2093e82f891eb2fcb6eaa0b1eb3685f44e3
25                 ec06293134b85876f9201d8a52b844c41581b2b3
26
27                 2010-04-30 fetchmail 6.3.17-pre1 tarball
28
29                 2010-05-06 fetchmail 6.3.17 release tarball
30
31
32 0. Release history
33 ==================
34
35 2010-04-18 0.1  first draft (visible in SVN and through oss-security)
36 2010-04-19 0.2  add note announcements may appear before releases
37 2010-04-20 0.3  add CVE name, fix Type:
38 2010-04-24 0.4  revise patch
39 2010-04-29 0.5  add info on contributing/mitigating factors
40 2010-05-06 1.0  complete
41
42
43 1. Background
44 =============
45
46 fetchmail is a software package to retrieve mail from remote POP2, POP3,
47 IMAP, ETRN or ODMR servers and forward it to local SMTP, LMTP servers or
48 message delivery agents. It supports SSL and TLS security layers through
49 the OpenSSL library, if enabled at compile time and if also enabled at
50 run time.
51
52
53 2. Problem description and Impact
54 =================================
55
56 In debug mode (-v -v), fetchmail prints information that was obtained from the
57 upstream server (POP3 UIDL lists) or from message headers retrieved from it.
58   If printing such information fails, for instance because there are invalid
59 multibyte character sequences in this information (message headers), fetchmail
60 will misinterpret this condition, and believe that the buffer was too small,
61 and reallocate a bigger one (with linearly increasing buffer size), and repeat,
62 until the allocation fails. At that point, fetchmail will abort.
63
64 The exact combination of contributing and mitigating factors is not
65 fully understood; GNU glibc 2.7 and 2.10.1 on i586 report EILSEQ when
66 printing invalid sequences through a %.*s format string in multibyte
67 locales such as de_DE.UTF-8; NetBSD 5, FreeBSD 8 and Solaris 10 do not.
68 However, the issue is a genuine fetchmail bug that deserves a fix.
69
70 Note that the "Affects:" line above may be inaccurate, and it may be that
71 versions before 5.6.6 are actually unaffected.  The author was unable to
72 compile such old fetchmail versions to verify the existence of the bug.
73   Given that other security issues are present in such versions, those should
74 not be used, and the wider version range was listed as vulnerable to err
75 towards the safe.
76
77
78 3. Solution
79 ===========
80
81 There are two alternatives, either of them by itself is sufficient:
82
83 a. Apply the patch found in section B of this announcement to
84    fetchmail 6.3.14 or newer, recompile and reinstall it.
85
86 b. Install fetchmail 6.3.17 or newer after it will have become available.
87    (Note that the announcements may be publicly visible quite some time
88    before the release is made, particularly for minor bugs.)
89    The fetchmail source code is always available from
90    <http://developer.berlios.de/project/showfiles.php?group_id=1824>.
91
92
93 4. Workaround
94 =============
95
96 Run fetchmail with at most one -v (--verbose) option.
97
98
99 A. Copyright, License and Warranty
100 ==================================
101
102 (C) Copyright 2010 by Matthias Andree, <matthias.andree@gmx.de>.
103 Some rights reserved.
104
105 This work is licensed under the Creative Commons
106 Attribution-Noncommercial-No Derivative Works 3.0 Germany License.
107 To view a copy of this license, visit
108 http://creativecommons.org/licenses/by-nc-nd/3.0/de/ or send a letter to
109
110 Creative Commons
111 171 Second Street
112 Suite 300
113 SAN FRANCISCO, CALIFORNIA 94105
114 USA
115
116
117 THIS WORK IS PROVIDED FREE OF CHARGE AND WITHOUT ANY WARRANTIES.
118 Use the information herein at your own risk.
119
120
121 B. Patch to remedy the problem
122 ==============================
123
124 Note that when taking this from a GnuPG clearsigned file, the lines
125 starting with a "-" character are prefixed by another "- " (dash +
126 blank) combination. Either feed this file through GnuPG to strip them,
127 or strip them manually. You may want to use the "-p1" flag to patch.
128
129 Whitespace differences can usually be ignored by invoking "patch -l",
130 so try this if the patch does not apply.
131
132 diff --git a/rfc822.c b/rfc822.c
133 index 6f2dbf3..dbcda32 100644
134 --- a/rfc822.c
135 +++ b/rfc822.c
136 @@ -25,6 +25,7 @@ MIT license.  Compile with -DMAIN to build the demonstrator.
137  #include  <stdlib.h>
138  
139  #include "fetchmail.h"
140 +#include "sdump.h"
141  
142  #ifndef MAIN
143  #include "i18n.h"
144 @@ -74,9 +75,10 @@ char *reply_hack(
145      }
146  
147  #ifndef MAIN
148 -    if (outlevel >= O_DEBUG)
149 -       report_build(stdout, GT_("About to rewrite %.*s...\n"),
150 -                       (int)BEFORE_EOL(buf), buf);
151 +    if (outlevel >= O_DEBUG) {
152 +       report_build(stdout, GT_("About to rewrite %s...\n"), (cp = sdump(buf, BEFORE_EOL(buf))));
153 +       xfree(cp);
154 +    }
155  
156      /* make room to hack the address; buf must be malloced */
157      for (cp = buf; *cp; cp++)
158 @@ -211,9 +213,12 @@ char *reply_hack(
159      }
160  
161  #ifndef MAIN
162 -    if (outlevel >= O_DEBUG)
163 -       report_complete(stdout, GT_("...rewritten version is %.*s.\n"),
164 -                       (int)BEFORE_EOL(buf), buf);
165 +    if (outlevel >= O_DEBUG) {
166 +       report_complete(stdout, GT_("...rewritten version is %s.\n"),
167 +                       (cp = sdump(buf, BEFORE_EOL(buf))));
168 +       xfree(cp)
169 +    }
170 +
171  #endif /* MAIN */
172      *length = strlen(buf);
173      return(buf);
174 diff --git a/uid.c b/uid.c
175 index fdc6f5d..9a62ee2 100644
176 --- a/uid.c
177 +++ b/uid.c
178 @@ -20,6 +20,7 @@
179  
180  #include "fetchmail.h"
181  #include "i18n.h"
182 +#include "sdump.h"
183  
184  /*
185   * Machinery for handling UID lists live here.  This is mainly to support
186 @@ -249,8 +250,11 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
187             {
188                 report_build(stdout, GT_("Old UID list from %s:"), 
189                              ctl->server.pollname);
190 -               for (idp = ctl->oldsaved; idp; idp = idp->next)
191 -                   report_build(stdout, " %s", idp->id);
192 +               for (idp = ctl->oldsaved; idp; idp = idp->next) {
193 +                   char *t = sdump(idp->id, strlen(idp->id));
194 +                   report_build(stdout, " %s", t);
195 +                   free(t);
196 +               }
197                 if (!idp)
198                     report_build(stdout, GT_(" <empty>"));
199                 report_complete(stdout, "\n");
200 @@ -260,8 +264,11 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
201         if (uidlcount)
202         {
203             report_build(stdout, GT_("Scratch list of UIDs:"));
204 -           for (idp = scratchlist; idp; idp = idp->next)
205 -               report_build(stdout, " %s", idp->id);
206 +           for (idp = scratchlist; idp; idp = idp->next) {
207 +               char *t = sdump(idp->id, strlen(idp->id));
208 +               report_build(stdout, " %s", t);
209 +               free(t);
210 +           }
211             if (!idp)
212                 report_build(stdout, GT_(" <empty>"));
213             report_complete(stdout, "\n");
214 @@ -517,8 +524,11 @@ void uid_swap_lists(struct query *ctl)
215             report_build(stdout, GT_("Merged UID list from %s:"), ctl->server.pollname);
216         else
217             report_build(stdout, GT_("New UID list from %s:"), ctl->server.pollname);
218 -       for (idp = dofastuidl ? ctl->oldsaved : ctl->newsaved; idp; idp = idp->next)
219 -           report_build(stdout, " %s = %d", idp->id, idp->val.status.mark);
220 +       for (idp = dofastuidl ? ctl->oldsaved : ctl->newsaved; idp; idp = idp->next) {
221 +           char *t = sdump(idp->id, strlen(idp->id));
222 +           report_build(stdout, " %s = %d", t, idp->val.status.mark);
223 +           free(t);
224 +        }
225         if (!idp)
226             report_build(stdout, GT_(" <empty>"));
227         report_complete(stdout, "\n");
228 @@ -567,8 +577,11 @@ void uid_discard_new_list(struct query *ctl)
229         /* this is now a merged list! the mails which were seen in this
230          * poll are marked here. */
231         report_build(stdout, GT_("Merged UID list from %s:"), ctl->server.pollname);
232 -       for (idp = ctl->oldsaved; idp; idp = idp->next)
233 -           report_build(stdout, " %s = %d", idp->id, idp->val.status.mark);
234 +       for (idp = ctl->oldsaved; idp; idp = idp->next) {
235 +           char *t = sdump(idp->id, strlen(idp->id));
236 +           report_build(stdout, " %s = %d", t, idp->val.status.mark);
237 +           free(t);
238 +       }
239         if (!idp)
240             report_build(stdout, GT_(" <empty>"));
241         report_complete(stdout, "\n");