Mu Dynamics, Inc. Security Advisories MU-201202-01 and MU-201202

看板Bugtraq作者時間14年前 (2012/03/22 03:32), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/1
-----BEGIN PGP SIGNED MESSAGE-----=0A= Hash: SHA1=0A= =0A= Mu Dynamics, Inc. Security Advisories MU-201202-01 and MU-201202-02 for Gnu= TLS and Libtasn1=0A= =0A= TLS record handling vulnerability in GnuTLS [MU-201202-01]=0A= ASN.1 length decoding vulnerability in Libtasn1 [MU-201202-02]=0A= =0A= 20 March 2012=0A= =0A= http://blog.mudynamics.com/2012/03/20/gnutls-and-libtasn1-vulns/=0A= http://labs.mudynamics.com/advisories.html=0A= =0A= Affected Products/Versions:=0A= =0A= * libgnutls up to 3.0.16.=0A= * libtasn1 up to 2.11.=0A= =0A= Product Overview:=0A= =0A= GnuTLS is an open source implementation of SSL, TLS and DTLS, with APIs for= =0A= encrypted network communications, along with X.509, PKCS #12, OpenPGP, and = =0A= other security data types.=0A= =0A= Analysis:=0A= =0A= Details for TLS record handling vulnerability in GnuTLS [MU-201202-01]:=0A= =0A= The block cipher decryption logic in GnuTLS assumed that a record containin= g =0A= any data which was a multiple of the block size was valid for further =0A= decryption processing, leading to a heap corruption vulnerability.=0A= =0A= The bug can be reproduced in GnuTLS 3.0.14 by creating a corrupt =0A= GenericBlockCipher struct with a valid IV, while everything else is strippe= d =0A= off the end, while the handshake message length retains its original value:= =0A= =0A= struct {=0A= opaque IV[SecurityParameters.record_iv_length];=0A= // corrupt: below items not sent=0A= /*=0A= block-ciphered struct {=0A= opaque content[TLSCompressed.length];=0A= opaque MAC[SecurityParameters.mac_length];=0A= uint8 padding[GenericBlockCipher.padding_length];=0A= uint8 padding_length;=0A= };=0A= */=0A= } GenericBlockCipher;=0A= =0A= This will cause a segmentation fault, when the ciphertext_to_compressed =0A= function tries to give decrypted data to _gnutls_auth_cipher_add_auth for H= MAC =0A= verification, even though the data length is invalid, and it should have = =0A= returned GNUTLS_E_DECRYPTION_FAILED or GNUTLS_E_UNEXPECTED_PACKET_LENGTH = =0A= instead, before _gnutls_auth_cipher_add_auth was called.=0A= =0A= Since the error was not returned soon enough, all of the various operations= =0A= ciphertext_to_compressed performs: i.e. setting the IV, removing the paddin= g, =0A= setting the "true" data length with the padding stripped, checking the padd= ing =0A= size and padding payload and verifying HMAC could all reference undefined, = =0A= unallocated, or uninitialized memory.=0A= =0A= There could be similar ways to reproduce this for AEAD ciphers due to the = =0A= various flows through this code, but we did not attempt to do this, and see= it =0A= as a topic for further investigation.=0A= =0A= Below we trace the execution of the ciphertext_to_compressed function from = =0A= lib/gnutls_cipher.c. The unsafe operations and missed opportunities to retu= rn =0A= before the heap corruption happens are marked with "***** ... *****" :=0A= =0A= 433 static int=0A= 434 ciphertext_to_compressed (gnutls_session_t session,=0A= 435 gnutls_datum_t *ciphertext, =0A= 436 uint8_t * compress_data,=0A= 437 int compress_size,=0A= 438 uint8_t type, record_parameters_st * para= ms, =0A= 439 uint64* sequence)=0A= 440 {=0A= ....=0A= 511 case CIPHER_BLOCK:=0A= 512 if (ciphertext->size < MAX(blocksize, tag_size) || (ciphertex= t->size % blocksize !=3D 0)) ***** UNSAFE *****=0A= 513 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH)= ;=0A= 514 =0A= 515 /* ignore the IV in TLS 1.1+=0A= 516 */=0A= 517 if (explicit_iv)=0A= 518 {=0A= 519 _gnutls_auth_cipher_setiv(&params->read.cipher_state,=0A= 520 ciphertext->data, blocksize);=0A= 521 =0A= 522 ciphertext->size -=3D blocksize;=0A= 523 ciphertext->data +=3D blocksize;=0A= 524 =0A= 525 if (ciphertext->size =3D=3D 0) ***** UNSAFE *****=0A= 526 {=0A= 527 gnutls_assert ();=0A= 528 return GNUTLS_E_DECRYPTION_FAILED;=0A= 529 }=0A= 530 }=0A= ....=0A= 537 if ((ret =3D=0A= 538 _gnutls_cipher_decrypt (&params->read.cipher_state.ciphe= r,=0A= 539 ciphertext->data, ciphertext->size)) < 0)=0A= 540 return gnutls_assert_val(ret);=0A= 541 =0A= 542 pad =3D ciphertext->data[ciphertext->size - 1] + 1; /* pad = */=0A= 543 =0A= 544 if ((int) pad > (int) ciphertext->size - tag_size)=0A= 545 {=0A= 546 gnutls_assert ();=0A= 547 _gnutls_record_log=0A= 548 ("REC[%p]: Short record length %d > %d - %d (under atta= ck?)\n",=0A= 549 session, pad, ciphertext->size, tag_size); ***** Messa= ge Appears During The Attack *****=0A= 550 /* We do not fail here. We check below for the=0A= 551 * the pad_failed. If zero means success.=0A= 552 */=0A= 553 pad_failed =3D GNUTLS_E_DECRYPTION_FAILED; ***** Executio= n Continues Anyway *****=0A= 554 pad %=3D blocksize;=0A= 555 }=0A= 556 =0A= 557 length =3D ciphertext->size - tag_size - pad;=0A= 558 =0A= 559 /* Check the padding bytes (TLS 1.x) */=0A= ....=0A= 577 /* Pass the type, version, length and compressed through=0A= 578 * MAC.=0A= 579 */=0A= 580 preamble_size =3D=0A= 581 make_preamble (UINT64DATA(*sequence), type,=0A= 582 length, ver, preamble);=0A= 583 ret =3D _gnutls_auth_cipher_add_auth (&params->read.cipher_st= ate, preamble, preamble_size);=0A= 584 if (ret < 0)=0A= 585 return gnutls_assert_val(ret);=0A= 586 =0A= 587 ret =3D _gnutls_auth_cipher_add_auth (&params->read.cipher_st= ate, ciphertext->data, length); ***** UNSAFE, crashes here *****=0A= 588 if (ret < 0)=0A= 589 return gnutls_assert_val(ret); ***** Crashes Before Error I= s Returned *****=0A= .... =0A= =0A= The segmentation fault appears as follows in GDB:=0A= =0A= Program received signal SIGSEGV, Segmentation fault.=0A= 0x003b9946 in _nettle_sha256_compress (state=3D0x807f128, =0A= input=3D0x808f000 <Address 0x808f000 out of bounds>, k=3D0x3cdb60)=0A= at sha256-compress.c:111=0A= 111 sha256-compress.c: No such file or directory.=0A= in sha256-compress.c=0A= (gdb) bt=0A= #0 0x003b9946 in _nettle_sha256_compress (state=3D0x807f128, =0A= input=3D0x808f000 <Address 0x808f000 out of bounds>, k=3D0x3cdb60)=0A= at sha256-compress.c:111=0A= #1 0x003b961b in nettle_sha256_update (ctx=3D0x807f128, length=3D429491686= 1, =0A= data=3D0x808effc "") at sha256.c:92=0A= #2 0x003b336d in nettle_hmac_sha256_update (ctx=3D0x807f050, length=3D4294= 967280, =0A= data=3D0x8082b09 '\017' <repeats 16 times>) at hmac-sha256.c:43=0A= #3 0x0021a749 in wrap_nettle_hmac_update (_ctx=3D0x807f050, text=3D0x8082b= 09, =0A= textsize=3D4294967280) at mac.c:231=0A= #4 0x00158233 in _gnutls_hmac (handle=3D0x807ef9c, text=3D0x8082b09, =0A= textlen=3D4294967280) at ./gnutls_hash_int.h:73=0A= #5 0x00158b35 in _gnutls_auth_cipher_add_auth (handle=3D0x807ef78, =0A= text=3D0x8082b09, textlen=3D-16) at gnutls_cipher_int.c:190=0A= #6 0x001473de in ciphertext_to_compressed (session=3D0x807d810, =0A= ciphertext=3D0xbfffe8a4, compress_data=3D0x8083da4 "", compress_size=3D= 16384, =0A= type=3D22 '\026', params=3D0x807ed48, sequence=3D0x807efcc)=0A= at gnutls_cipher.c:587=0A= #7 0x00145cdc in _gnutls_decrypt (session=3D0x807d810, =0A= ciphertext=3D0x8082af9 "\252\257C/7\301\362\352h|d\275#\312\027\312", '= \017' <repeats 16 times>, ciphertext_size=3D32, data=3D0x8083da4 "", max_da= ta_size=3D16384, =0A= type=3DGNUTLS_HANDSHAKE, params=3D0x807ed48, sequence=3D0x807efcc)=0A= at gnutls_cipher.c:159=0A= ....=0A= (gdb) =0A= =0A= The segmentation fault appears as follows in Valgrind Memcheck:=0A= =0A= =3D=3D29586=3D=3D Invalid read of size 1=0A= =3D=3D29586=3D=3D at 0x40274B9: memcpy (mc_replace_strmem.c:497)=0A= =3D=3D29586=3D=3D by 0x42BC5A6: nettle_sha256_update (sha256.c:92)=0A= =3D=3D29586=3D=3D by 0x42B636C: nettle_hmac_sha256_update (hmac-sha256.c= :43)=0A= =3D=3D29586=3D=3D by 0x411C748: wrap_nettle_hmac_update (mac.c:231)=0A= =3D=3D29586=3D=3D by 0x405A232: _gnutls_hmac (gnutls_hash_int.h:73)=0A= =3D=3D29586=3D=3D by 0x405AB34: _gnutls_auth_cipher_add_auth (gnutls_cip= her_int.c:190)=0A= =3D=3D29586=3D=3D by 0x40493DD: ciphertext_to_compressed (gnutls_cipher.= c:587)=0A= =3D=3D29586=3D=3D by 0x4047CDB: _gnutls_decrypt (gnutls_cipher.c:159)=0A= ....=0A= =3D=3D29586=3D=3D Address 0x4464411 is 0 bytes after a block of size 89 al= loc'd=0A= =3D=3D29586=3D=3D at 0x4024F12: calloc (vg_replace_malloc.c:467)=0A= =3D=3D29586=3D=3D by 0x4049AE4: _mbuffer_alloc (gnutls_mbuffers.c:288)= =0A= =3D=3D29586=3D=3D by 0x4049C49: _mbuffer_linearize (gnutls_mbuffers.c:34= 9)=0A= =3D=3D29586=3D=3D by 0x40462FB: _gnutls_recv_in_buffers (gnutls_record.c= :996)=0A= =3D=3D29586=3D=3D by 0x404D01C: _gnutls_handshake_io_recv_int (gnutls_bu= ffers.c:1174)=0A= =3D=3D29586=3D=3D by 0x4050383: _gnutls_recv_handshake (gnutls_handshake= ..c:1260)=0A= ....=0A= =3D=3D29586=3D=3D Invalid read of size 1=0A= ....=0A= =3D=3D29586=3D=3D Address 0x4464412 is 1 bytes after a block of size 89 al= loc'd=0A= ....=0A= =3D=3D29586=3D=3D Process terminating with default action of signal 11 (SIG= SEGV)=0A= =3D=3D29586=3D=3D Access not within mapped region at address 0x4779000=0A= =3D=3D29586=3D=3D at 0x42BC946: _nettle_sha256_compress (sha256-compress= ..c:111)=0A= =3D=3D29586=3D=3D by 0x42BC61A: nettle_sha256_update (sha256.c:92)=0A= =3D=3D29586=3D=3D by 0x42B636C: nettle_hmac_sha256_update (hmac-sha256.c= :43)=0A= =3D=3D29586=3D=3D by 0x411C748: wrap_nettle_hmac_update (mac.c:231)=0A= =3D=3D29586=3D=3D by 0x405A232: _gnutls_hmac (gnutls_hash_int.h:73)=0A= =3D=3D29586=3D=3D by 0x405AB34: _gnutls_auth_cipher_add_auth (gnutls_cip= her_int.c:190)=0A= =3D=3D29586=3D=3D by 0x40493DD: ciphertext_to_compressed (gnutls_cipher.= c:587)=0A= ....=0A= Segmentation fault=0A= =0A= Details for ASN.1 length decoding vulnerability in Libtasn1 [MU-201202-02]:= =0A= =0A= Various functions using the ASN.1 length decoding logic in Libtasn1 were = =0A= incorrectly assuming that the return value from asn1_get_length_der is alwa= ys =0A= less than the length of the enclosing ASN.1 structure, which is only true f= or =0A= valid structures and not for intentionally corrupt or otherwise buggy =0A= structures.=0A= =0A= Here is an example of unsafe asn1_get_length_der usage from =0A= lib/minitasn1/decoding.c, in the asn1_der_decoding function:=0A= =0A= 0812 asn1_retCode=0A= 0813 asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len,= =0A= 0814 char *errorDescription)=0A= 0815 {=0A= ....=0A= 1033 case TYPE_ENUMERATED:=0A= 1034 len2 =3D=0A= 1035 asn1_get_length_der (der + counter, len - counter, = &len3);=0A= 1036 if (len2 < 0)=0A= 1037 return ASN1_DER_ERROR;=0A= 1038 if (len2 + len3 > len - counter)=0A= 1039 return ASN1_DER_ERROR;=0A= 1040 _asn1_set_value (p, der + counter, len3 + len2);=0A= 1041 counter +=3D len3 + len2;=0A= 1042 move =3D RIGHT;=0A= 1043 break;=0A= =0A= The above call to asn1_get_length_der was returning an impossibly large val= ue =0A= of 2GB when the Mu analyzer generated corrupt lengths fields for versions, = =0A= serial numbers, public key info, and signature structures in X.509 client = =0A= certificates, but this could happen in any use of Libtasn1 that is relying = =0A= upon asn1_get_length_der, not just SSL, TLS, or GnuTLS.=0A= =0A= The asn1_der_decoding function failed to check for cases when =0A= asn1_get_length_der returned a length larger than the enclosing structure's= =0A= (void* ider) own length (int len).=0A= =0A= When _asn1_set_value was called anyway, it contained a memcpy operation whi= ch =0A= assumed the arguments are valid, which tried copy 2GB of memory, leading to= a =0A= heap corruption vulnerability.=0A= =0A= Simon Josefsson, Libtasn1 maintainer, described the patch as follows: "the = =0A= real bug was not in asn1_get_length_der() even if that is the function we = =0A= patch[ed]. The callers of that function that did not check that the return = =0A= values are sane were buggy. However, instead of fixing all callers, ... we = =0A= went for the simpler solution to let the function return an error for a =0A= situation that is unlikely to occur without malicious interaction or data = =0A= corruption."=0A= =0A= The asn1_der_decoding function shown above is now safe, because =0A= asn1_get_length_der was updated to "[return] -4 when the decoded length val= ue =0A= plus @len would exceed @der_len," so asn1_der_decoding returns ASN1_DER_ERR= OR =0A= before it can call _asn1_set_value to trigger the segmentation fault.=0A= =0A= Abbreviated GDB Backtrace after the segmentation fault:=0A= =0A= (gdb) bt=0A= #0 __memcpy_ia32 () at ../sysdeps/i386/i686/multiarch/../memcpy.S:75=0A= #1 0x00000001 in ?? ()=0A= #2 0x0020eadc in _asn1_set_value (node=3D0x807ff50, value=3D0x807ed5c, =0A= len=3D2147483652) at parser_aux.c:228=0A= #3 0x0020a646 in asn1_der_decoding (element=3D0x8078000, ider=3D0x807ed4e,= =0A= len=3D687, errorDescription=3D0x0) at decoding.c:1036=0A= #4 0x001bc7da in gnutls_x509_crt_import (cert=3D0x8078000, data=3D0xbfffea= e8, =0A= format=3DGNUTLS_X509_FMT_DER) at x509.c:226=0A= #5 0x00176d16 in gnutls_pcert_import_x509_raw (pcert=3D0x807d610, =0A= cert=3D0xbfffeae8, format=3DGNUTLS_X509_FMT_DER, flags=3D0) at gnutls_p= cert.c:201=0A= ....=0A= (gdb) =0A= =0A= Response / Solution:=0A= =0A= TLS record handling vulnerability in GnuTLS [MU-201202-01] is fixed in GnuT= LS =0A= 3.0.15. For more details, see =0A= http://article.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/5912 .=0A= =0A= ASN.1 length decoding vulnerability in Libtasn1 [MU-201202-02] is fixed in = =0A= Libtasn1 2.12 and GnuTLS 3.0.16. For more details, see =0A= http://lists.gnu.org/archive/html/help-libtasn1/2012-03/msg00000.html and = =0A= http://article.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/5932 .=0A= =0A= History:=0A= =0A= Mon, 27 Feb 2012 14:13:45 -0800: TLS Record handling issue reported.=0A= Tue, 28 Feb 2012 10:29:46 +0100: TLS Record handling patch created.=0A= Fri, 02 Mar 2012 18:42:05 +0000: GnuTLS 3.0.15 release announced.=0A= Fri, 02 Mar 2012 14:04:31 -0800: ASN.1 length decoding issue reported.=0A= Wed, 14 Mar 2012 01:04:36 +0100: ASN.1 length decoding patch created.=0A= Mon, 19 Mar 2012 10:57:42 +0100: Libtasn1 2.12 release announced.=0A= Tue, 20 Mar 2012 23:40:00 +0000: Advisory released to the public.=0A= =0A= See also:=0A= =0A= http://article.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/5912=0A= http://article.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/5932=0A= http://lists.gnu.org/archive/html/help-libtasn1/2012-03/msg00000.html=0A= http://git.savannah.gnu.org/gitweb/?p=3Dgnutls.git;a=3Dcommitdiff;h=3Db4957= 40f2ff66550ca9395b3fda3ea32c3acb185=0A= http://git.savannah.gnu.org/gitweb/?p=3Dlibtasn1.git;a=3Dcommitdiff;h=3D6e5= 34bf4fb3144be51c928ed3efcf9c36055c9c7=0A= =0A= Credit:=0A= =0A= These vulnerabilities were discovered by Matthew Hall <mhall@mudynamics.com= >, =0A= Senior Network Protocol Software Engineer at Mu Dynamics, via code inspecti= on =0A= and protocol fuzzing using a Mu 4000 security analyzer.=0A= =0A= http://blog.mudynamics.com/wp-content/uploads/2012/03/pgpkey.txt=0A= =0A= Mu Dynamics is the leading provider of solutions ensuring the performance a= nd =0A= security of both applications and network infrastructure. The company's =0A= innovative solutions enable customers to confidently meet the challenges po= sed =0A= by today's rapidly changing networks. This includes the ever-growing number= of =0A= applications and devices on the network, and the swift transition to mobile= , =0A= virtual and cloud environments. Hundreds of service providers, enterprises,= =0A= application developers and network equipment manufacturers count on its =0A= purpose-built solutions, like Mu Studio and Blitz, to ensure their =0A= applications and networks are scalable and secure. Mu Dynamics is =0A= headquartered in Sunnyvale, California.=0A= -----BEGIN PGP SIGNATURE-----=0A= Version: GnuPG/MacGPG2 v2.0.18 (Darwin)=0A= Comment: GPGTools - http://gpgtools.org=0A= =0A= iQIcBAEBAgAGBQJPaRSqAAoJEEzdDa9po1UUuhkP/RnvCMvQwF+9UyZArKkEDVgu=0A= Z6NvZPcquXZhQ4MNLuIbfkikQnGg+9e7EnbKUzbxxNp7tsVN/ioVGWFHRZw3diSp=0A= Tknw8SZlMghz4Li/nw4ruPQcbT4r6EcDtlkJhTAtI+A2ZAlMkurMUAGIcPhX2CvU=0A= cpNHwGdTPqYcT4+07zzhbhf2M2MD5y1268PNEx9EN9VrZEriyDpFRBKlkkOTeti5=0A= LuSkhIUbiH0wChWGheM54rvsoi4LRSO8QEeeUED1kqBzNI5OJD7AB3g1RJ/K8vEB=0A= DjSkGmKg2siDHifNQUgwOcnED0qcUnN9LAp/1qV0Wn+DJvG3RC5hleJSHYPAW6sk=0A= /fmoOegRN+9TlXVI2ZBzF3ltCaDr8ktbwMUiOU/BZc0MAG2geUvGUyYGkZW0JLZN=0A= MZaJRMzqAS2DrKMapwDWUeNXf5rvQHU49eRweBjyE8lUA2cMtMsvgbFtTOtxAFhl=0A= JYytEI1e7Sh8Xo12GWUxsc6aMjIngFzs2VgfwQc283fnBjZWHZNsdX8gKcKoUY3f=0A= oN6IcQijxfOgCEiWkERsPtcX9GN2+9y2QLs79Z5uDeBJXCOLSzeZg93gWqjEGfcm=0A= 64iJwKAWpGcHEr5Po3mxwA+9yREmrth+e6cax9LujiXAn1LrW2SkUXofCafYg8yd=0A= ym77p8ibkKLczxASVN2I=0A= =3DaqOg=0A= -----END PGP SIGNATURE-----=0A=
文章代碼(AID): #1FQYoqQy (Bugtraq)