xorl %eax, %eax

CVE-2009-1379: OpenSSL DTLS fragment read after free()

leave a comment »

This bug was discovered by Daniel Mentz and affects OpenSSL from 0.9.8 to 0.9.8k. Here is the vulnerable code from 0.9.8k release of the popular library:

501 static int
502 dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
503         {
504         /* (0) check whether the desired fragment is available
505          * if so:
506          * (1) copy over the fragment to s->init_buf->data[]
507          * (2) update s->init_num
508          */
509         pitem *item;
510         hm_fragment *frag;
511         int al;
 ...
520         if ( s->d1->handshake_read_seq == frag->msg_header.seq)
 ...
524                 al=dtls1_preprocess_fragment(s,&frag->msg_header,max);
525
 ...
532
533                 dtls1_hm_fragment_free(frag);
534                 pitem_free(item);
535
536                 if (al==0)
537                         {
538                         *ok = 1;
539                         return frag->msg_header.frag_len;
540                         }
 ...
549         }


At line 525, al is initilized to the fragment to preprocess. At line 533 dtls1_hm_fragment_free() is used to free the allocated space for the fragment, but if al is 0 (which is really likely), it will attempt to access a location (line 539) which was freed at line 533. This was characterized as a DoS vulnerability by Mark J. Cox. Personally, I believe that if an attacker is able to manipulate the information contained in this memory area so that this will not be an invalid read operation after this was freed, then you can set frag->msg_header.frag_len to arbitrary values which eventually, might lead to something more than a DoS. Of course, this is easier locally but anyway…
To fix this, a new variable was added to keep the value of the fragment’s length:

 if ( s->d1->handshake_read_seq == frag->msg_header.seq)
 {
+		unsigned long frag_len = frag->msg_header.frag_len;
+
 pqueue_pop(s->d1->buffered_messages);


And of course, the return operation at line 539 was changed like this:

 *ok = 1;
-			return frag->msg_header.frag_len;
+			return frag_len;
 }


To trigger the bug you can use the information that Daniel Mentz disclosed in openssl-dev mailing list.

Written by xorl

May 18, 2009 at 22:22

Posted in bugs

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s