From b82c3ccb65e3279996a690ebf577263d7730e0b3 Mon Sep 17 00:00:00 2001 From: Matthias Andree Date: Thu, 26 Aug 2021 23:53:14 +0200 Subject: SECURITY: IMAP: PREAUTH->abort if STARTTLS needed On --sslproto auto (or other nonempty values), when receiving IMAP PREAUTH state, abort the connection, rather than continuing with cleartext. --ssl is unaffected because it always negotiates TLS. See fetchmail-SA-2021-02.txt for details. --- NEWS | 17 ++++++ driver.c | 8 +++ fetchmail-SA-2021-02.txt | 117 +++++++++++++++++++++++++++++++++++++++++ imap.c | 20 ++++--- po/de.po | 132 ++++++++++++++++++++++++++--------------------- 5 files changed, 230 insertions(+), 64 deletions(-) create mode 100644 fetchmail-SA-2021-02.txt diff --git a/NEWS b/NEWS index 2add2b6a..2d51b6e7 100644 --- a/NEWS +++ b/NEWS @@ -81,6 +81,23 @@ removed from a 6.5.0 or newer release.) messages. This will not be fixed, because the maintainer has no Kerberos 5 server to test against. Use GSSAPI. +-------------------------------------------------------------------------------- +fetchmail-6.4.22 (not yet released): + +# SECURITY FIX: +* On IMAP connections, without --ssl and with nonempty --sslproto, meaning that + fetchmail is to enforce TLS, and when the server or an attacker sends + a PREAUTH greeting, fetchmail used to continue an unencrypted connection. + Now, log the error and abort the connection. + + Recommendation for servers that support SSL/TLS-wrapped or "implicit" mode on + a dedicated port (default 993): use --ssl. + + Reported by: Andrew C. Aitchison, based on the USENIX Security 21 paper "Why + TLS is better without STARTTLS - A Security Analysis of STARTTLS in the Email + Context" by Damian Poddebniak, Fabian Ising, Hanno Böck, and Sebastian + Schinzel. The paper did not mention fetchmail. + -------------------------------------------------------------------------------- fetchmail-6.4.21 (released 2021-08-09, 30042 LoC): diff --git a/driver.c b/driver.c index 3e382d3a..5421c766 100644 --- a/driver.c +++ b/driver.c @@ -1243,10 +1243,18 @@ is restored.")); ctl->remotename, ctl->server.truename); } + else if (err == PS_SOCKET) + { + report(stderr, GT_("Socket or TLS error on %s@%s\n"), + ctl->remotename, + ctl->server.truename); + } else + { report(stderr, GT_("Unknown login or authentication error on %s@%s\n"), ctl->remotename, ctl->server.truename); + } goto cleanUp; } diff --git a/fetchmail-SA-2021-02.txt b/fetchmail-SA-2021-02.txt new file mode 100644 index 00000000..7c324ed4 --- /dev/null +++ b/fetchmail-SA-2021-02.txt @@ -0,0 +1,117 @@ +fetchmail-SA-2021-02: failure to enforce STARTTLS session encryption with IMAP PREAUTH + +Topics: fetchmail fails to enforce an encrypted connection + +Author: Matthias Andree +Version: 0.1 +Announced: TBC +Type: failure to enforce configured security policy +Impact: fetchmail continues an unencrypted connection, + thus reading unauthenticated input and sending + information unencrypted over its transport, + including passwords +Danger: medium +Acknowledgment: Andrew C. Aitchison for reporting this against fetchmail + Damian Poddebniak, Fabian Ising, Hanno Böck, and Sebastian + Schinzel for their Usenix Security 21 paper NO STARTTLS + +CVE Name: TBC (if any) +URL: https://www.fetchmail.info/fetchmail-SA-2021-02.txt +Project URL: https://www.fetchmail.info/ + +Affects: - fetchmail releases up to and including 6.4.21 + +Not affected: - fetchmail releases 6.4.22 and newer + +Corrected in: TBC Git commit hash (both needed) + TBC fetchmail 6.4.21 release tarball + +0. Release history +================== + +2021-08-10 initial report to maintainer +2021-08-10 0.1 first draft + + +1. Background +============= + +fetchmail is a software package to retrieve mail from remote POP3, IMAP, +ETRN or ODMR servers and forward it to local SMTP, LMTP servers or +message delivery agents. fetchmail supports SSL and TLS security layers +through the OpenSSL library, if enabled at compile time and if also +enabled at run time, in both SSL/TLS-wrapped mode on dedicated ports as +well as in-band-negotiated "STARTTLS" and "STLS" modes through the +regular protocol ports. + + +2. Problem description and Impact +================================= + +fetchmail permits requiring that an IMAP or POP3 protocol exchange uses +a TLS-encrypted transport, in 6.4 by way of an --sslproto auto or similar configuration. + +This TLS encryption can be establised either as implicit or fully-wrapped +connections on dedicated TCP ports for the "secure" variants, or by initiating +a cleartext protocol exchange and then requesting a TLS negotiation in-band. + +IMAP also supports sessions that start in "authenticated state" (PREAUTH). +In this latter case, IMAP (RFC-3501) does not permit sending STARTTLS +negotations, which are only permissible in not-authenticated state. + +In such a combination of circumstances (1. IMAP protocol in use, 2. the server +greets with PREAUTH, announcing authenticated state, 3. the user configured TLS +mandatory, 4. the user did not configure "ssl" mode that uses separate ports +for implicit SSL/TLS), fetchmail 6.4.21 and older continues with the +unencrypted connection, rather than flagging the situation and aborting. + +This can cause e-mail and potentially passwords to be exposed to eavesdropping. + + +3. Solutions +============ + +3a. Install fetchmail 6.4.22 or newer. + +The fetchmail source code is available from +. + +The Git-based source code repository is currently published via +https://gitlab.com/fetchmail/fetchmail/-/tree/legacy_64 (primary) +https://sourceforge.net/p/fetchmail/git/ci/legacy_64/tree/ (copy) + + +3b. Alternatively, where the IMAP server supports this form of access, +fetchmail can be configured to "ssl" mode, meaning it will connect to +a dedicated port (default: 993 for IMAP) and negotiate TLS without +prior clear-text protocol exchange. + Also, --ssl can be given on the command line, which switches all +configured server statements to this ssl mode. + + +Distributors are encouraged to review the NEWS file and move forward to +6.4.22, rather than backport individual security fixes, because doing so +routinely misses other fixes crucial to fetchmail's proper operation, +for which no security announcements are issued, or documentation, +or translation updates. + +Fetchmail 6.4.X releases have been made with a focus on unchanged user and +program interfaces so as to avoid disruptions when upgrading from 6.3.Z or +6.4.X to 6.4.Y with Y > X. Care was taken to not change the interface +incompatibly. + + +A. Copyright, License and Non-Warranty +====================================== + +(C) Copyright 2021 by Matthias Andree, . +Some rights reserved. + +© Copyright 2021 by Matthias Andree. This file is licensed under CC +BY-ND 4.0. To view a copy of this license, visit +http://creativecommons.org/licenses/by-nd/4.0/ + +THIS WORK IS PROVIDED FREE OF CHARGE AND WITHOUT ANY WARRANTIES. +Use the information herein at your own risk. + +END of fetchmail-SA-2021-02 diff --git a/imap.c b/imap.c index 5f65ee47..3b74f6f6 100644 --- a/imap.c +++ b/imap.c @@ -428,6 +428,20 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting) if ((ok = capa_probe(sock, ctl))) return ok; + commonname = ctl->server.pollname; + if (ctl->server.via) + commonname = ctl->server.via; + if (ctl->sslcommonname) + commonname = ctl->sslcommonname; + + /* Defend against a PREAUTH-prevents-STARTTLS attack */ + if (preauth && must_starttls(ctl)) { + report(stderr, GT_("%s: configuration requires TLS, but STARTTLS is not permitted " + "because of authenticated state (PREAUTH). Aborting connection. Server permitting, try --ssl instead (see manual).\n"), commonname); + preauth = FALSE; /* reset for the next session */ + return PS_SOCKET; + } + /* * If either (a) we saw a PREAUTH token in the greeting, or * (b) the user specified ssh preauthentication, then we're done. @@ -438,12 +452,6 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting) return(PS_SUCCESS); } - commonname = ctl->server.pollname; - if (ctl->server.via) - commonname = ctl->server.via; - if (ctl->sslcommonname) - commonname = ctl->sslcommonname; - #ifdef SSL_ENABLE if (maybe_starttls(ctl)) { if ((strstr(capabilities, "STARTTLS") && maybe_starttls(ctl)) diff --git a/po/de.po b/po/de.po index 0f905593..8d698ffc 100644 --- a/po/de.po +++ b/po/de.po @@ -6,10 +6,10 @@ # Matthias Andree , 2004 - 2020. msgid "" msgstr "" -"Project-Id-Version: fetchmail 6.4.16-rc1\n" +"Project-Id-Version: fetchmail 6.4.22\n" "Report-Msgid-Bugs-To: fetchmail-devel@lists.sourceforge.net\n" -"POT-Creation-Date: 2021-07-28 18:09+0200\n" -"PO-Revision-Date: 2021-01-30 15:17+0100\n" +"POT-Creation-Date: 2021-08-10 18:07+0200\n" +"PO-Revision-Date: 2021-08-10 18:08+0200\n" "Last-Translator: Matthias Andree \n" "Language-Team: German \n" "Language: de\n" @@ -360,175 +360,180 @@ msgstr "" msgid "Repoll immediately on %s@%s\n" msgstr "Sofortige erneute Abfrage von %s@%s\n" -#: driver.c:1247 +#: driver.c:1248 +#, c-format +msgid "Socket or TLS error on %s@%s\n" +msgstr "Socket- oder TLS-Fehler bei %s@%s\n" + +#: driver.c:1254 #, c-format msgid "Unknown login or authentication error on %s@%s\n" msgstr "Unbekannter Einlogg- oder Authentifikationsfehler bei %s@%s\n" -#: driver.c:1271 +#: driver.c:1279 #, c-format msgid "Authorization OK on %s@%s\n" msgstr "Authentifikation bei %s@%s erfolgreich\n" -#: driver.c:1277 +#: driver.c:1285 #, c-format msgid "fetchmail authentication OK on %s@%s" msgstr "Fetchmail: Authentifikation bei %s@%s erfolgreich" -#: driver.c:1281 +#: driver.c:1289 #, c-format msgid "Fetchmail was able to log into %s@%s.\n" msgstr "Fetchmail war in der Lage, sich bei %s@%s einzuloggen.\n" # -#: driver.c:1285 +#: driver.c:1293 msgid "Service has been restored.\n" msgstr "Der Dienst ist wieder hergestellt.\n" -#: driver.c:1318 +#: driver.c:1326 #, c-format msgid "selecting or re-polling folder %s\n" msgstr "Ordner %s wird gewählt oder erneut abgefragt\n" -#: driver.c:1320 +#: driver.c:1328 msgid "selecting or re-polling default folder\n" msgstr "Vorgabe-Ordner wird gewählt oder erneut abgefragt\n" -#: driver.c:1332 +#: driver.c:1340 #, c-format msgid "%s at %s (folder %s)" msgstr "%s bei %s (Ordner %s)" -#: driver.c:1335 rcfile_y.y:390 +#: driver.c:1343 rcfile_y.y:390 #, c-format msgid "%s at %s" msgstr "%s bei %s" -#: driver.c:1340 +#: driver.c:1348 #, c-format msgid "Polling %s\n" msgstr "Frage %s ab\n" -#: driver.c:1344 +#: driver.c:1352 #, c-format msgid "%d message (%d %s) for %s" msgid_plural "%d messages (%d %s) for %s" msgstr[0] "%d Nachricht (%d %s) für %s" msgstr[1] "%d Nachrichten (%d %s) für %s" -#: driver.c:1347 +#: driver.c:1355 msgid "seen" msgid_plural "seen" msgstr[0] "gesehene" msgstr[1] "gesehene" -#: driver.c:1350 +#: driver.c:1358 #, c-format msgid "%d message for %s" msgid_plural "%d messages for %s" msgstr[0] "%d Nachricht für %s" msgstr[1] "%d Nachrichten für %s" -#: driver.c:1357 +#: driver.c:1365 #, c-format msgid " (%d octets).\n" msgstr " (%d Bytes).\n" -#: driver.c:1363 +#: driver.c:1371 #, c-format msgid "No mail for %s\n" msgstr "Keine Post für %s\n" -#: driver.c:1396 +#: driver.c:1404 msgid "bogus message count!" msgstr "ungültige Nachrichtenanzahl!" -#: driver.c:1448 +#: driver.c:1456 #, c-format msgid "Too many mails skipped (%d > %d) due to transient errors for %s\n" msgstr "" "Zu viele Nachrichten (%d > %d) wegen vorübergehender Fehler auf %s " "übersprungen.\n" -#: driver.c:1549 +#: driver.c:1557 msgid "socket" msgstr "Socket" -#: driver.c:1552 +#: driver.c:1560 msgid "missing or bad RFC822 header" msgstr "fehlende oder fehlerhafte RFC822-Kopfzeile" -#: driver.c:1555 +#: driver.c:1563 msgid "MDA" msgstr "MDA" -#: driver.c:1558 +#: driver.c:1566 msgid "client/server synchronization" msgstr "Klient/Server-Synchronisation" -#: driver.c:1561 +#: driver.c:1569 msgid "client/server protocol" msgstr "Klient/Server-Protokoll" -#: driver.c:1564 +#: driver.c:1572 msgid "lock busy on server" msgstr "Lock auf Server beschäftigt" -#: driver.c:1567 +#: driver.c:1575 msgid "SMTP transaction" msgstr "SMTP-Transaktion" -#: driver.c:1570 +#: driver.c:1578 msgid "DNS lookup" msgstr "DNS-Nachschlagen" -#: driver.c:1573 +#: driver.c:1581 msgid "undefined" msgstr "undefinierter" -#: driver.c:1579 +#: driver.c:1587 #, c-format msgid "%s error while fetching from %s@%s and delivering to SMTP host %s\n" msgstr "%s-Fehler beim Abholen von %s@%s und Auslieferung zum SMTP-Host %s\n" -#: driver.c:1581 +#: driver.c:1589 msgid "unknown" msgstr "unbekannt" -#: driver.c:1583 +#: driver.c:1591 #, c-format msgid "%s error while fetching from %s@%s\n" msgstr "%s-Fehler beim Abholen von %s@%s\n" -#: driver.c:1595 +#: driver.c:1603 #, c-format msgid "post-connection command terminated with signal %d\n" msgstr "Nach-Verbindungs-Befehl wurde mit Signal %d beendet\n" -#: driver.c:1597 +#: driver.c:1605 #, c-format msgid "post-connection command failed with status %d\n" msgstr "Nach-Verbindungs-Befehl scheiterte mit Status %d\n" -#: driver.c:1616 +#: driver.c:1624 msgid "Kerberos V4 support not linked.\n" msgstr "Kerberos-V4-Unterstützung nicht vorhanden.\n" -#: driver.c:1624 +#: driver.c:1632 msgid "Kerberos V5 support not linked.\n" msgstr "Kerberos-V5-Unterstützung nicht vorhanden.\n" -#: driver.c:1635 +#: driver.c:1643 #, c-format msgid "Option --flush is not supported with %s\n" msgstr "Option --flush wird mit %s nicht unterstützt\n" -#: driver.c:1641 +#: driver.c:1649 #, c-format msgid "Option --all is not supported with %s\n" msgstr "Option --all wird mit %s nicht unterstützt\n" -#: driver.c:1650 +#: driver.c:1658 #, c-format msgid "Option --limit is not supported with %s\n" msgstr "Option --limit wird mit %s nicht unterstützt\n" @@ -1911,100 +1916,111 @@ msgstr "Protokoll identifiziert als IMAP2 oder IMAP2BIS\n" msgid "will idle after poll\n" msgstr "werde nach Abfrage untätig sein\n" -#: imap.c:476 pop3.c:474 +#: imap.c:439 +#, c-format +msgid "" +"%s: configuration requires TLS, but STARTTLS is not permitted because of " +"authenticated state (PREAUTH). Aborting connection. Server permitting, try " +"--ssl instead (see manual).\n" +msgstr "" +"%s: die Konfiguration verlangt TLS, aber STARTTLS ist aufgrund eingeloggtem " +"Zustnad (PREAUTH) unzulässig. Breche Verbindung ab. Wenn der Server es " +"erlaubt, versuchen Sie --ssl (siehe Handbuch).\n" + +#: imap.c:484 pop3.c:474 #, c-format msgid "%s: upgrade to TLS succeeded.\n" msgstr "%s: Upgrade auf TLS erfolgreich.\n" -#: imap.c:482 pop3.c:480 +#: imap.c:490 pop3.c:480 #, c-format msgid "%s: upgrade to TLS failed.\n" msgstr "%s: Upgrade auf TLS fehlgeschlagen.\n" -#: imap.c:487 +#: imap.c:495 #, c-format msgid "%s: opportunistic upgrade to TLS failed, trying to continue\n" msgstr "" "%s: opportunistisches Upgrade auf TLS fehlgeschlagen, versuche " "weiterzumachen\n" -#: imap.c:502 +#: imap.c:510 #, c-format msgid "%s: WARNING: server offered STARTTLS but sslproto '' given.\n" msgstr "" "%s: WARNUNG: Server hat STARTTLS angeboten, aber sslproto '' ist angegeben.\n" -#: imap.c:607 +#: imap.c:615 msgid "Required OTP capability not compiled into fetchmail\n" msgstr "Benötigte OTP-Fähigkeit nicht in fetchmail einkompiliert\n" -#: imap.c:627 pop3.c:560 +#: imap.c:635 pop3.c:560 msgid "Required NTLM capability not compiled into fetchmail\n" msgstr "Benötigte NTLM-Fähigkeit nicht in fetchmail einkompiliert\n" -#: imap.c:693 +#: imap.c:701 #, c-format msgid "mail expunge mismatch (%d actual != %d expected)\n" msgstr "unerwartete Expunge-Bestätigung (%d tatsächlich != %d erwartet)\n" -#: imap.c:820 +#: imap.c:828 #, c-format msgid "%lu is unseen\n" msgstr "%lu ist ungelesen\n" -#: imap.c:870 pop3.c:831 pop3.c:843 pop3.c:1088 pop3.c:1095 +#: imap.c:878 pop3.c:831 pop3.c:843 pop3.c:1088 pop3.c:1095 #, c-format msgid "%u is unseen\n" msgstr "%u ist ungelesen\n" -#: imap.c:905 imap.c:964 +#: imap.c:913 imap.c:972 msgid "re-poll failed\n" msgstr "erneute Abfrage fehlgeschlagen\n" -#: imap.c:913 imap.c:969 +#: imap.c:921 imap.c:977 #, c-format msgid "%d message waiting after re-poll\n" msgid_plural "%d messages waiting after re-poll\n" msgstr[0] "%d Nachricht wartet nach erneuter Abfrage\n" msgstr[1] "%d Nachrichten warten nach erneuter Abfrage\n" -#: imap.c:930 +#: imap.c:938 msgid "mailbox selection failed\n" msgstr "Postfach-Auswahl fehlgeschlagen\n" -#: imap.c:934 +#: imap.c:942 #, c-format msgid "%d message waiting after first poll\n" msgid_plural "%d messages waiting after first poll\n" msgstr[0] "%d Nachricht wartet nach der ersten Abfrage\n" msgstr[1] "%d Nachrichten warten nach der ersten Abfrage\n" -#: imap.c:948 +#: imap.c:956 msgid "expunge failed\n" msgstr "Säubern (EXPUNGE) fehlgeschlagen\n" -#: imap.c:952 +#: imap.c:960 #, c-format msgid "%d message waiting after expunge\n" msgid_plural "%d messages waiting after expunge\n" msgstr[0] "%d Nachricht wartet nach dem Säubern (EXPUNGE)\n" msgstr[1] "%d Nachrichten warten nach dem Säubern (EXPUNGE)\n" -#: imap.c:991 +#: imap.c:999 msgid "search for unseen messages failed\n" msgstr "Suche nach ungelesenen Nachrichten fehlgeschlagen\n" -#: imap.c:996 pop3.c:852 +#: imap.c:1004 pop3.c:852 #, c-format msgid "%u is first unseen\n" msgstr "%u ist erste ungelesene\n" -#: imap.c:1080 +#: imap.c:1088 msgid "" "Warning: ignoring bogus data for message sizes returned by the server.\n" msgstr "Warnung: ignoriere falsche Größendaten vom Server.\n" -#: imap.c:1179 imap.c:1186 +#: imap.c:1187 imap.c:1194 #, c-format msgid "Incorrect FETCH response: %s.\n" msgstr "Unpassende Antwort auf FETCH: %s.\n" -- cgit v1.2.3