]> Pileus Git - ~andy/fetchmail/commitdiff
Validate NTLM challenge fields.
authorMatthias Andree <matthias.andree@gmx.de>
Tue, 14 Aug 2012 18:47:22 +0000 (20:47 +0200)
committerMatthias Andree <matthias.andree@gmx.de>
Tue, 14 Aug 2012 18:56:47 +0000 (20:56 +0200)
This is to avoid reading from bad locations, and possibly conveying
confidential data. Credit to Nico Golde.

NEWS
fetchmail-SA-2012-02.txt
ntlm.h
ntlmsubr.c

diff --git a/NEWS b/NEWS
index afc329a00971ea6980958d0d5b45eecb22e7279e..748a5e8954f897b808d9c0072c33a46c97e90654 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -59,15 +59,19 @@ removed from a 6.4.0 or newer release.)
 fetchmail-6.3.22 (not yet released):
 
 # SECURITY FIXES
-* CVE-2012-(not yet assigned):
+* for CVE-2012-3482:
   NTLM: fetchmail mistook an error message that the server sent in response to
   an NTLM request for protocol exchange, tried to decode it, and crashed while
   reading from a bad memory location.
-  Fix: Detect base64 decoding errors and abort NTLM authentication.
+  Also, with a carefully crafted NTLM challenge packet sent from the server, it
+  would be possible that fetchmail conveyed confidential data not meant for the
+  server through the NTLM response packet.
+  Fix: Detect base64 decoding errors, validate the NTLM challenge, and abort
+  NTLM authentication in case of error.
   See fetchmail-SA-2012-02.txt for further details.
   Reported by J. Porter Clark.
 
-* CVE-2011-3389:
+* for CVE-2011-3389:
   SSL/TLS (wrapped and STARTTLS): fetchmail used to disable a countermeasure 
   against a certain kind of attack against cipher block chaining initialization 
   vectors (SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS).
index 584706dad432e9460dfd11cfd0d71855081229f6..fc713d225d3fe8a999d8c36c49b4da7a3ca1004d 100644 (file)
@@ -1,15 +1,17 @@
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
-fetchmail-SA-2012-02: DoS possible with NTLM authentication in debug mode
+fetchmail-SA-2012-02: DoS/data theft possible in NTLM authentication
 
-Topics:                fetchmail denial of service in NTLM protocol phase
+Topics:                fetchmail denial of service/data theft in NTLM protocol phase
 
 Author:                Matthias Andree
 Version:       draft
 Announced:     2012-08-13
-Type:          crash while reading from bad memory location
-Impact:                fetchmail segfaults and aborts, stalling inbound mail
+Type:          reading from bad memory locations
+Impact:                fetchmail segfaults and aborts, stalling inbound mail,
+               or: fetchmail conveys data from bad locations, possibly
+               betraying confidential data
 Danger:                low
 Acknowledgment:        J. Porter Clark
 
@@ -34,6 +36,7 @@ Corrected in: 2012-08-13 Git, among others, see commit
 
 2012-08-13 0.1 draft
 2012-08-14 0.2 added CVE ID
+2012-08-14 0.3 mention data theft
 
 
 1. Background
@@ -53,12 +56,16 @@ regular protocol ports.
 
 Fetchmail version 5.0.8 added NTLM support. This code sent the NTLM
 authentication request, but never checked if the received response was
-NTLM protocol exchange, or a server-side error message.  Instead,
-fetchmail tried to decode the error message as though it were
-base64-encoded protocol exchange, and could then segfault, subject to
-verbosity and other circumstances, while reading data from bad memory
-locations.
+an NTLM challenge, or a server-side error message.  Instead, fetchmail
+tried to decode the error message as though it were base64-encoded
+protocol exchange, and could then segfault, subject to verbosity and
+other circumstances, while reading data from bad memory locations.
 
+Also, when the "Target Name" structure in the NTLM Type 2 message (the
+challenge) was carefully crafted, fetchmail might read from the wrong
+memory location, and send confidential data to the server that it should
+not have.  It is deemed hard, although not impossible, to steal
+other accounts' data.
 
 3. Solution
 ===========
@@ -106,7 +113,7 @@ END of fetchmail-SA-2012-02
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
-iEYEARECAAYFAlAp5g0ACgkQvmGDOQUufZXtLwCg54tPXJZAXauGxJ77oRGox49g
-WUIAnizjQ4AvBSzk3Oraqv+WCS+8wiMb
-=NEZ4
+iEYEARECAAYFAlAqnJ0ACgkQvmGDOQUufZURKQCgtarBW3fr0uR/ANpNma7QiAd0
+dFMAoPMNVYwTitZG/gkvwhr7QBGB59pj
+=HBRo
 -----END PGP SIGNATURE-----
diff --git a/ntlm.h b/ntlm.h
index 1469633508701a8dcfdadbc9d5647563545d7f7d..ad835201ce1515deef88bef04d88c4309fd4d843 100644 (file)
--- a/ntlm.h
+++ b/ntlm.h
@@ -32,8 +32,8 @@ uint32        msgType;
 tSmbStrHeader    uDomain;
 uint32        flags;
 uint8         challengeData[8];
-uint8         reserved[8];
-tSmbStrHeader    emptyString;
+uint32        context[2];
+tSmbStrHeader    targetInfo;
 uint8         buffer[1024];
 uint32        bufIndex;
 }tSmbNtlmAuthChallenge;
index 9321d26e7c99af92af44c7e677d5dc6f730b8a7c..63cbed8f34a91fae338e3f1c0f6f6044de554895 100644 (file)
@@ -55,7 +55,8 @@ int ntlm_helper(int sock, struct query *ctl, const char *proto)
     if ((result = gen_recv(sock, msgbuf, sizeof msgbuf)))
        goto cancelfail;
 
-    if ((result = from64tobits (&challenge, msgbuf, sizeof(challenge))) < 0)
+    if ((result = from64tobits (&challenge, msgbuf, sizeof(challenge))) < 0
+           || result < ((void *)&challenge.context - (void *)&challenge))
     {
        report (stderr, GT_("could not decode BASE64 challenge\n"));
        /* We do not goto cancelfail; the server has already sent the
@@ -64,6 +65,23 @@ int ntlm_helper(int sock, struct query *ctl, const char *proto)
        return PS_AUTHFAIL;
     }
 
+    /* validate challenge:
+     * - ident
+     * - message type
+     * - that offset points into buffer
+     * - that offset + length does not wrap
+     * - that offset + length is not bigger than buffer */
+    if (0 != memcmp("NTLMSSP", challenge.ident, 8)
+           || challenge.msgType != 2
+           || challenge.uDomain.offset > result
+           || challenge.uDomain.offset + challenge.uDomain.len < challenge.uDomain.offset
+           || challenge.uDomain.offset + challenge.uDomain.len > result)
+    {
+       report (stderr, GT_("NTLM challenge contains invalid data.\n"));
+       result = PS_AUTHFAIL;
+       goto cancelfail;
+    }
+
     if (outlevel >= O_DEBUG)
        dumpSmbNtlmAuthChallenge(stdout, &challenge);