CERT-FI Vulnerability Advisory on GnuTLS Version Information Advisory Reference FICORA #130447 Release Date 19 May 2008 12:00 UTC Last Revision 19 May 2008 Version Number 1.0 Acknowledgement Vulnerabilities were discovered by Ossi Herrala and Jukka Taimisto from the CROSS project at Codenomicon Ltd., and reported directly to the vendor through CERT-FI. What is Affected? The vulnerabilities described in this advisory affect GnuTLS prior to version 2.2.4. Impact The impact from vulnerabilities can expose Denial-of-Service (DoS) and buffer overflow conditions. It may even be possible for an attacker to execute code on the affected system. Summary Three programming errors leading to segmentation fault were found in the gnutls-serv program, triggered by the following TLS messages: 1. Sending TLS record containing multiple Client Hello handshake messages. 2. Sending TLS 1.0 Client Hello message which contains specifically crafted server name extension. 3. Doing complete TLS 1.0 handshake followed by a encrypted Client-Hello message with a Record Length of 8. Details 1. The problem occurs when gnutls-serv receives TLS message which contains multiple Client Hello messages. The program reads the first Client Hello and then proceeds to send Server Hello, Certificate, Certificate Request and Server Hello Done messages. After sending these, it apperently reads next Client Hello from the message sent earlier and crashes to segmentation fault caused by a NULL pointer. The error occurs when _gnutls_recv_client_kx_message() (in lib/gnutls_kx.c) is called. This function calls _gnutls_recv_handshake() which in turn reads the next Client Hello packet and ends up returning 0 and sets the data pointer to NULL. _gnutls_recv_client_kx_message() does not check the variable data for NULL before calling the key exchange handling function, in this case _gnutls_proc_rsa_client_kx() (in lib/auth_rsa.c). _gnutls_proc_rsa_client_kx() function does not check the data pointer for NULL and proceeds to call _gnutls_read_uint16() with a NULL pointer, causing a segmentation fault. 2. The problem occurs when gnutls-serv receives Client Hello message which contains Server name extension where the length of the server name list is set to 18 and the data of the Server Same list consists of 18 zero octets. After receiving this Client Hello message gnutls-serv continues to function normally, but crashes after Finished messages when it tries to pack the session data in the function pack_security_parameters() (in lib/gnutls_session_pack.c). However the bug causing the crash is in the extension handling, in _gnutls_server_name_recv_params() (lib/ext_server_name.c). The function tries to calculate the number of Server Names in the packet (lines 70-80), but does not check if the length of Server Name is 0. This causes the function to interpret the 18 zero octets as containing 6 Server Names. The more serious bug follows when, on line 83, the number of server names is saved to session->security_parameters.extensions.server_names_size. Then the number of Server Sames is checked against the maximum number of Server Names supported (3) but the value saved to the struct is never corrected. Hence after the extensions are interpreted, the session->security_parameters.extensions.server_names_size contains the illegal value 6. This causes the crash later on when in pack_security_parameters() the session->security_parameters.extensions.server_names_size is used in the loop where the Server Names are copied (gnutls_session_pack.c, lines 1074 - 1090). Since there is only space for 3 Server Names, the loop iterates well over the boundary and results in a segmentation fault. 3. The problem occurs in function _gnutls_ciphertext2compressed() (in lib/gnutls_cipher.c). The parameter ciphertext contains the start of the received message in ciphertext.data and the ciphertext.size contains value 8 (taken from the Record Length field of the received TLS record). Now, since block cipher is being used, after the 8 bytes of data has been decrypted the _gnutls_ciphertext2compressed() proceeds to read the length of the padding bytes in line 505: pad = ciphertext.data[ciphertext.size - 1] + 1; /* pad */ Since the ciphertext.size is 8, the pad byte is read from the Random field in the Client Hello message (as stated in the introduction, the flaw was found by sending encrypted Client Hello message in a TLS Record containig invalid Record Length field) and contains value 0xf0 (240 in decimal) and the pad variable is set to 241. In line 507, the length of the data is calculated: length = ciphertext.size - hash_size - pad; Since, pad is 241, hash_size 20 (SHA1 is used) and ciphertext.size is 8, the length is set to a negative value. This is not checked immediately. In line 509, a check is made to make sure padding length is not invalid: if (pad > ciphertext.size - hash_size) Due the data types used in the comparison (pad is uin8_t, ciphertext.size is unsigned int and hash_size is int) the invalid pad length is not catched by this check, instead the comparison is false leaving the pad_failed to value 0 and the execution proceeds to the next statement in line 520. The check in line 520 passes and the program proceeds to do the padding check. The for loop: for (i = 2; i < pad; i++) { if (ciphertext.data[ciphertext.size - i] != ciphertext.data[ciphertext.size - 1]) pad_failed = GNUTLS_E_DECRYPTION_FAILED; } loops the i from 2 to 241, resulting in a segmentation fault. Solution Patch the affected software with the patches supplied by the vendor. Vendor Statements GnuTLS The issue is covered in the advisory SA-2008-01. Credits CERT-FI would like to thank Codenomicon for providing the vulnerability information and Simon Josefsson of GnuTLS for his co-operation. Contact Information CERT-FI Vulnerability Coordination can be contacted as follows: Email: vulncoord@ficora.fi Please quote the advisory reference in the subject line Telephone: +358 9 6966 510 Monday - Friday 08:00 - 16:15 (EET: UTC+2) Fax : +358 9 6966 515 Post: Vulnerability Coordination FICORA/CERT-FI P.O. Box 313 FI-00181 Helsinki FINLAND CERT-FI encourages those who wish to communicate via email to make use of our PGP key. The key is available at https://www.cert.fi/en/activities/contact/pgp-keys.html