Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 712481 Details for
Bug 804920
CVE-2012-1569 libtasn1: DER decoding buffer overflow (GNUTLS-SA-2012-3, MU-201202-02)
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
Local copy of the Mu Dynamics advisory text
mu-dynamics-gnutls-advisories-201202.txt.asc (text/plain), 15.53 KB, created by
Tomas Hoger
on 2013-03-19 09:30:23 UTC
(
hide
)
Description:
Local copy of the Mu Dynamics advisory text
Filename:
MIME Type:
Creator:
Tomas Hoger
Created:
2013-03-19 09:30:23 UTC
Size:
15.53 KB
patch
obsolete
>-----BEGIN PGP SIGNED MESSAGE----- >Hash: SHA1 > >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(¶ms->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 (¶ms->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 (¶ms->read.cipher_state, preamble, preamble_size); > 584 if (ret < 0) > 585 return gnutls_assert_val(ret); > 586 > 587 ret = _gnutls_auth_cipher_add_auth (¶ms->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@mudynamics.com>, >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. >-----BEGIN PGP SIGNATURE----- >Version: GnuPG/MacGPG2 v2.0.18 (Darwin) >Comment: GPGTools - http://gpgtools.org > >iQIcBAEBAgAGBQJPaRSqAAoJEEzdDa9po1UUuhkP/RnvCMvQwF+9UyZArKkEDVgu >Z6NvZPcquXZhQ4MNLuIbfkikQnGg+9e7EnbKUzbxxNp7tsVN/ioVGWFHRZw3diSp >Tknw8SZlMghz4Li/nw4ruPQcbT4r6EcDtlkJhTAtI+A2ZAlMkurMUAGIcPhX2CvU >cpNHwGdTPqYcT4+07zzhbhf2M2MD5y1268PNEx9EN9VrZEriyDpFRBKlkkOTeti5 >LuSkhIUbiH0wChWGheM54rvsoi4LRSO8QEeeUED1kqBzNI5OJD7AB3g1RJ/K8vEB >DjSkGmKg2siDHifNQUgwOcnED0qcUnN9LAp/1qV0Wn+DJvG3RC5hleJSHYPAW6sk >/fmoOegRN+9TlXVI2ZBzF3ltCaDr8ktbwMUiOU/BZc0MAG2geUvGUyYGkZW0JLZN >MZaJRMzqAS2DrKMapwDWUeNXf5rvQHU49eRweBjyE8lUA2cMtMsvgbFtTOtxAFhl >JYytEI1e7Sh8Xo12GWUxsc6aMjIngFzs2VgfwQc283fnBjZWHZNsdX8gKcKoUY3f >oN6IcQijxfOgCEiWkERsPtcX9GN2+9y2QLs79Z5uDeBJXCOLSzeZg93gWqjEGfcm >64iJwKAWpGcHEr5Po3mxwA+9yREmrth+e6cax9LujiXAn1LrW2SkUXofCafYg8yd >ym77p8ibkKLczxASVN2I >=aqOg >-----END PGP SIGNATURE-----
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 804920
: 712481