Wireshark-dev: Re: [Wireshark-dev] Mu Dynamics, Inc. Security Advisories MU-201202-01 and MU-20
From: Gerald Combs <gerald@xxxxxxxxxxxxx>
Date: Wed, 21 Mar 2012 15:16:02 -0700
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

The GNUTLS libraries that we ship with the Windows installers come
from the OpenSUSE build system:

https://build.opensuse.org/package/show?package=mingw32-gnutls&project=windows%3Amingw%3Awin32

I submitted a request to update GNUTLS and Libtasn1 to the most recent
releases that we can ship...

https://bugzilla.novell.com/show_bug.cgi?id=753440

...and by "that we can ship" I mean that GNUTLS 3.0 changed its
license from LGPLv2.1+ / GPLv3+ to LGPLv3+ / GPLv3+. The compatibility
matrix at

http://www.gnu.org/licenses/gpl-faq.html#AllCompatibility

suggests that this would require changing Wireshark's license. A while
back someone suggested adding support for Mozilla's Network Security
Services library:

https://bugzilla.redhat.com/show_bug.cgi?id=348461

It might be a good time to revisit that.



On 3/20/12 7:14 PM, Security wrote:
> Hello Open Source Distributors,
> 
> Any libgnutls and libtasn1 packages you may have in your
> environments should be updated to the latest versions in order to
> correct the below vulnerabilities we released today. Various
> popular packages such as Wireshark / tshark use these packages and
> could also be affected.
> 
> http://www.gnu.org/software/gnutls/security.html 
> http://blog.mudynamics.com/2012/03/20/gnutls-and-libtasn1-vulns/
> 
> Regards, Matthew Hall Mu Dynamics Research Team Mu Dynamics, Inc.
> 
> Mu Dynamics, Inc. Security Advisories MU-201202-01 and MU-201202-02
> for GnuTLS and Libtasn1
> 
> TLS record handling vulnerability in GnuTLS [MU-201202-01] ASN.1
> length decoding vulnerability in Libtasn1 [MU-201202-02]
> 
> 20 March 2012
> 
> http://blog.mudynamics.com/2012/03/20/gnutls-and-libtasn1-vulns/ 
> http://labs.mudynamics.com/advisories.html
> 
> Affected Products/Versions:
> 
> * libgnutls up to 3.0.16. * libtasn1 up to 2.11.
> 
> Product Overview:
> 
> GnuTLS is an open source implementation of SSL, TLS and DTLS, with
> APIs for encrypted network communications, along with X.509, PKCS
> #12, OpenPGP, and other security data types.
> 
> Analysis:
> 
> Details for TLS record handling vulnerability in GnuTLS
> [MU-201202-01]:
> 
> The block cipher decryption logic in GnuTLS assumed that a record
> containing any data which was a multiple of the block size was
> valid for further decryption processing, leading to a heap
> corruption vulnerability.
> 
> The bug can be reproduced in GnuTLS 3.0.14 by creating a corrupt 
> GenericBlockCipher struct with a valid IV, while everything else is
> stripped off the end, while the handshake message length retains
> its original value:
> 
> struct { opaque IV[SecurityParameters.record_iv_length]; //
> corrupt: below items not sent /* block-ciphered struct { opaque
> content[TLSCompressed.length]; opaque
> MAC[SecurityParameters.mac_length]; uint8
> padding[GenericBlockCipher.padding_length]; uint8 padding_length; 
> }; */ } GenericBlockCipher;
> 
> This will cause a segmentation fault, when the
> ciphertext_to_compressed function tries to give decrypted data to
> _gnutls_auth_cipher_add_auth for HMAC verification, even though the
> data length is invalid, and it should have returned
> GNUTLS_E_DECRYPTION_FAILED or GNUTLS_E_UNEXPECTED_PACKET_LENGTH 
> instead, before _gnutls_auth_cipher_add_auth was called.
> 
> Since the error was not returned soon enough, all of the various
> operations ciphertext_to_compressed performs: i.e. setting the IV,
> removing the padding, setting the "true" data length with the
> padding stripped, checking the padding size and padding payload and
> verifying HMAC could all reference undefined, unallocated, or
> uninitialized memory.
> 
> There could be similar ways to reproduce this for AEAD ciphers due
> to the various flows through this code, but we did not attempt to
> do this, and see it as a topic for further investigation.
> 
> Below we trace the execution of the ciphertext_to_compressed
> function from lib/gnutls_cipher.c. The unsafe operations and missed
> opportunities to return before the heap corruption happens are
> marked with "***** ... *****" :
> 
> 433    static int 434    ciphertext_to_compressed (gnutls_session_t
> session, 435                              gnutls_datum_t
> *ciphertext, 436                              uint8_t *
> compress_data, 437                              int compress_size, 
> 438                              uint8_t type, record_parameters_st
> * params, 439                              uint64* sequence) 440
> { ... 511        case CIPHER_BLOCK: 512          if
> (ciphertext->size < MAX(blocksize, tag_size) || (ciphertext->size %
> blocksize != 0)) ***** UNSAFE ***** 513            return
> gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); 514 515
> /* ignore the IV in TLS 1.1+ 516           */ 517          if
> (explicit_iv) 518            { 519
> _gnutls_auth_cipher_setiv(&params->read.cipher_state, 520
> ciphertext->data, blocksize); 521 522              ciphertext->size
> -= blocksize; 523              ciphertext->data += blocksize; 524 
> 525              if (ciphertext->size == 0) ***** UNSAFE ***** 526
> { 527                  gnutls_assert (); 528
> return GNUTLS_E_DECRYPTION_FAILED; 529                } 530
> } ... 537          if ((ret = 538
> _gnutls_cipher_decrypt (&params->read.cipher_state.cipher, 539
> ciphertext->data, ciphertext->size)) < 0) 540            return
> gnutls_assert_val(ret); 541 542          pad =
> ciphertext->data[ciphertext->size - 1] + 1;   /* pad */ 543 544
> if ((int) pad > (int) ciphertext->size - tag_size) 545
> { 546              gnutls_assert (); 547
> _gnutls_record_log 548                ("REC[%p]: Short record
> length %d > %d - %d (under attack?)\n", 549
> session, pad, ciphertext->size, tag_size); ***** Message Appears
> During The Attack ***** 550              /* We do not fail here. We
> check below for the 551               * the pad_failed. If zero
> means success. 552               */ 553              pad_failed =
> GNUTLS_E_DECRYPTION_FAILED; ***** Execution Continues Anyway ***** 
> 554              pad %= blocksize; 555            } 556 557
> length = ciphertext->size - tag_size - pad; 558 559          /*
> Check the padding bytes (TLS 1.x) */ ... 577          /* Pass the
> type, version, length and compressed through 578           * MAC. 
> 579           */ 580          preamble_size = 581
> make_preamble (UINT64DATA(*sequence), type, 582
> length, ver, preamble); 583          ret =
> _gnutls_auth_cipher_add_auth (&params->read.cipher_state, preamble,
> preamble_size); 584          if (ret < 0) 585            return
> gnutls_assert_val(ret); 586 587          ret =
> _gnutls_auth_cipher_add_auth (&params->read.cipher_state,
> ciphertext->data, length); ***** UNSAFE, crashes here ***** 588
> if (ret < 0) 589            return gnutls_assert_val(ret); *****
> Crashes Before Error Is Returned ***** ...
> 
> The segmentation fault appears as follows in GDB:
> 
> Program received signal SIGSEGV, Segmentation fault. 0x003b9946 in
> _nettle_sha256_compress (state=0x807f128, input=0x808f000 <Address
> 0x808f000 out of bounds>, k=0x3cdb60) at sha256-compress.c:111 111
> sha256-compress.c: No such file or directory. in sha256-compress.c 
> (gdb) bt #0  0x003b9946 in _nettle_sha256_compress
> (state=0x807f128, input=0x808f000 <Address 0x808f000 out of
> bounds>, k=0x3cdb60) at sha256-compress.c:111 #1  0x003b961b in
> nettle_sha256_update (ctx=0x807f128, length=4294916861, 
> data=0x808effc "") at sha256.c:92 #2  0x003b336d in
> nettle_hmac_sha256_update (ctx=0x807f050, length=4294967280, 
> data=0x8082b09 '\017' <repeats 16 times>) at hmac-sha256.c:43 #3
> 0x0021a749 in wrap_nettle_hmac_update (_ctx=0x807f050,
> text=0x8082b09, textsize=4294967280) at mac.c:231 #4  0x00158233 in
> _gnutls_hmac (handle=0x807ef9c, text=0x8082b09, textlen=4294967280)
> at ./gnutls_hash_int.h:73 #5  0x00158b35 in
> _gnutls_auth_cipher_add_auth (handle=0x807ef78, text=0x8082b09,
> textlen=-16) at gnutls_cipher_int.c:190 #6  0x001473de in
> ciphertext_to_compressed (session=0x807d810, ciphertext=0xbfffe8a4,
> compress_data=0x8083da4 "", compress_size=16384, type=22 '\026',
> params=0x807ed48, sequence=0x807efcc) at gnutls_cipher.c:587 #7
> 0x00145cdc in _gnutls_decrypt (session=0x807d810, 
> ciphertext=0x8082af9 "\252\257C/7\301\362\352h|d\275#\312\027\312",
> '\017' <repeats 16 times>, ciphertext_size=32, data=0x8083da4 "",
> max_data_size=16384, type=GNUTLS_HANDSHAKE, params=0x807ed48,
> sequence=0x807efcc) at gnutls_cipher.c:159 ... (gdb)
> 
> The segmentation fault appears as follows in Valgrind Memcheck:
> 
> ==29586== Invalid read of size 1 ==29586==    at 0x40274B9: memcpy
> (mc_replace_strmem.c:497) ==29586==    by 0x42BC5A6:
> nettle_sha256_update (sha256.c:92) ==29586==    by 0x42B636C:
> nettle_hmac_sha256_update (hmac-sha256.c:43) ==29586==    by
> 0x411C748: wrap_nettle_hmac_update (mac.c:231) ==29586==    by
> 0x405A232: _gnutls_hmac (gnutls_hash_int.h:73) ==29586==    by
> 0x405AB34: _gnutls_auth_cipher_add_auth (gnutls_cipher_int.c:190) 
> ==29586==    by 0x40493DD: ciphertext_to_compressed
> (gnutls_cipher.c:587) ==29586==    by 0x4047CDB: _gnutls_decrypt
> (gnutls_cipher.c:159) ... ==29586==  Address 0x4464411 is 0 bytes
> after a block of size 89 alloc'd ==29586==    at 0x4024F12: calloc
> (vg_replace_malloc.c:467) ==29586==    by 0x4049AE4: _mbuffer_alloc
> (gnutls_mbuffers.c:288) ==29586==    by 0x4049C49:
> _mbuffer_linearize (gnutls_mbuffers.c:349) ==29586==    by
> 0x40462FB: _gnutls_recv_in_buffers (gnutls_record.c:996) ==29586==
> by 0x404D01C: _gnutls_handshake_io_recv_int
> (gnutls_buffers.c:1174) ==29586==    by 0x4050383:
> _gnutls_recv_handshake (gnutls_handshake.c:1260) ... ==29586==
> Invalid read of size 1 ... ==29586==  Address 0x4464412 is 1 bytes
> after a block of size 89 alloc'd ... ==29586== Process terminating
> with default action of signal 11 (SIGSEGV) ==29586==  Access not
> within mapped region at address 0x4779000 ==29586==    at
> 0x42BC946: _nettle_sha256_compress (sha256-compress.c:111) 
> ==29586==    by 0x42BC61A: nettle_sha256_update (sha256.c:92) 
> ==29586==    by 0x42B636C: nettle_hmac_sha256_update
> (hmac-sha256.c:43) ==29586==    by 0x411C748:
> wrap_nettle_hmac_update (mac.c:231) ==29586==    by 0x405A232:
> _gnutls_hmac (gnutls_hash_int.h:73) ==29586==    by 0x405AB34:
> _gnutls_auth_cipher_add_auth (gnutls_cipher_int.c:190) ==29586==
> by 0x40493DD: ciphertext_to_compressed (gnutls_cipher.c:587) ... 
> Segmentation fault
> 
> Details for ASN.1 length decoding vulnerability in Libtasn1
> [MU-201202-02]:
> 
> Various functions using the ASN.1 length decoding logic in Libtasn1
> were incorrectly assuming that the return value from
> asn1_get_length_der is always less than the length of the enclosing
> ASN.1 structure, which is only true for valid structures and not
> for intentionally corrupt or otherwise buggy structures.
> 
> Here is an example of unsafe asn1_get_length_der usage from 
> lib/minitasn1/decoding.c, in the asn1_der_decoding function:
> 
> 0812    asn1_retCode 0813    asn1_der_decoding (ASN1_TYPE *
> element, const void *ider, int len, 0814                       char
> *errorDescription) 0815    { ... 1033                case
> TYPE_ENUMERATED: 1034                  len2 = 1035
> asn1_get_length_der (der + counter, len - counter, &len3); 1036
> if (len2 < 0) 1037                    return ASN1_DER_ERROR; 1038
> if (len2 + len3 > len - counter) 1039                    return
> ASN1_DER_ERROR; 1040                  _asn1_set_value (p, der +
> counter, len3 + len2); 1041                  counter += len3 +
> len2; 1042                  move = RIGHT; 1043
> break;
> 
> The above call to asn1_get_length_der was returning an impossibly
> large value of 2GB when the Mu analyzer generated corrupt lengths
> fields for versions, serial numbers, public key info, and signature
> structures in X.509 client certificates, but this could happen in
> any use of Libtasn1 that is relying upon asn1_get_length_der, not
> just SSL, TLS, or GnuTLS.
> 
> The asn1_der_decoding function failed to check for cases when 
> asn1_get_length_der returned a length larger than the enclosing
> structure's (void* ider) own length (int len).
> 
> When _asn1_set_value was called anyway, it contained a memcpy
> operation which assumed the arguments are valid, which tried copy
> 2GB of memory, leading to a heap corruption vulnerability.
> 
> Simon Josefsson, Libtasn1 maintainer, described the patch as
> follows: "the real bug was not in asn1_get_length_der() even if
> that is the function we patch[ed]. The callers of that function
> that did not check that the return values are sane were buggy.
> However, instead of fixing all callers, ... we went for the simpler
> solution to let the function return an error for a situation that
> is unlikely to occur without malicious interaction or data 
> corruption."
> 
> The asn1_der_decoding function shown above is now safe, because 
> asn1_get_length_der was updated to "[return] -4 when the decoded
> length value plus @len would exceed @der_len," so asn1_der_decoding
> returns ASN1_DER_ERROR before it can call _asn1_set_value to
> trigger the segmentation fault.
> 
> Abbreviated GDB Backtrace after the segmentation fault:
> 
> (gdb) bt #0  __memcpy_ia32 () at
> ../sysdeps/i386/i686/multiarch/../memcpy.S:75 #1  0x00000001 in ??
> () #2  0x0020eadc in _asn1_set_value (node=0x807ff50,
> value=0x807ed5c, len=2147483652) at parser_aux.c:228 #3  0x0020a646
> in asn1_der_decoding (element=0x8078000, ider=0x807ed4e, len=687,
> errorDescription=0x0) at decoding.c:1036 #4  0x001bc7da in
> gnutls_x509_crt_import (cert=0x8078000, data=0xbfffeae8, 
> format=GNUTLS_X509_FMT_DER) at x509.c:226 #5  0x00176d16 in
> gnutls_pcert_import_x509_raw (pcert=0x807d610, cert=0xbfffeae8,
> format=GNUTLS_X509_FMT_DER, flags=0) at gnutls_pcert.c:201 ... 
> (gdb)
> 
> Response / Solution:
> 
> TLS record handling vulnerability in GnuTLS [MU-201202-01] is fixed
> in GnuTLS 3.0.15. For more details, see 
> http://article.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/5912
> .
> 
> ASN.1 length decoding vulnerability in Libtasn1 [MU-201202-02] is
> fixed in Libtasn1 2.12 and GnuTLS 3.0.16. For more details, see 
> http://lists.gnu.org/archive/html/help-libtasn1/2012-03/msg00000.html
> and 
> http://article.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/5932
> .
> 
> History:
> 
> Mon, 27 Feb 2012 14:13:45 -0800: TLS Record handling issue
> reported. Tue, 28 Feb 2012 10:29:46 +0100: TLS Record handling
> patch created. Fri, 02 Mar 2012 18:42:05 +0000: GnuTLS 3.0.15
> release announced. Fri, 02 Mar 2012 14:04:31 -0800: ASN.1 length
> decoding issue reported. Wed, 14 Mar 2012 01:04:36 +0100: ASN.1
> length decoding patch created. Mon, 19 Mar 2012 10:57:42 +0100:
> Libtasn1 2.12 release announced. Tue, 20 Mar 2012 23:40:00 +0000:
> Advisory released to the public.
> 
> See also:
> 
> http://article.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/5912
>
> 
http://article.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/5932
> http://lists.gnu.org/archive/html/help-libtasn1/2012-03/msg00000.html
>
> 
http://git.savannah.gnu.org/gitweb/?p=gnutls.git;a=commitdiff;h=b495740f2ff66550ca9395b3fda3ea32c3acb185
> http://git.savannah.gnu.org/gitweb/?p=libtasn1.git;a=commitdiff;h=6e534bf4fb3144be51c928ed3efcf9c36055c9c7
>
>  Credit:
> 
> These vulnerabilities were discovered by Matthew Hall
> <mhall@xxxxxxxxxxxxxx>, Senior Network Protocol Software Engineer
> at Mu Dynamics, via code inspection and protocol fuzzing using a Mu
> 4000 security analyzer.
> 
> http://blog.mudynamics.com/wp-content/uploads/2012/03/pgpkey.txt
> 
> Mu Dynamics is the leading provider of solutions ensuring the
> performance and security of both applications and network
> infrastructure. The company's innovative solutions enable customers
> to confidently meet the challenges posed by today's rapidly
> changing networks. This includes the ever-growing number of 
> applications and devices on the network, and the swift transition
> to mobile, virtual and cloud environments. Hundreds of service
> providers, enterprises, application developers and network
> equipment manufacturers count on its purpose-built solutions, like
> Mu Studio and Blitz, to ensure their applications and networks are
> scalable and secure. Mu Dynamics is headquartered in Sunnyvale,
> California. 
> ___________________________________________________________________________
>
> 
Sent via:    Wireshark-dev mailing list <wireshark-dev@xxxxxxxxxxxxx>
> Archives:    http://www.wireshark.org/lists/wireshark-dev 
> Unsubscribe: https://wireshark.org/mailman/options/wireshark-dev 
> mailto:wireshark-dev-request@xxxxxxxxxxxxx?subject=unsubscribe

- -- 
Join us for Sharkfest ’12! · Wireshark® Developer and User Conference
Berkeley, CA, June 24-27 · sharkfest.wireshark.org
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk9qUyIACgkQpw8IXSHylJrJSwCgqZWz1v7gP7s/b/+j9nZaJ6nW
0psAmgPx/RJxdrYbNwJti4gN6YGmUf33
=ZtFw
-----END PGP SIGNATURE-----