Bug 129077

Summary: [patch] [vuxml] net/wireshark: fix DoS in SMTP dissector
Product: Ports & Packages Reporter: Eygene Ryabinkin <rea-fbsd>
Component: Individual Port(s)Assignee: Joe Marcus Clarke <marcus>
Status: Closed FIXED    
Severity: Affects Only Me CC: security
Priority: Normal    
Version: Latest   
Hardware: Any   
OS: Any   

Description Eygene Ryabinkin 2008-11-22 23:20:01 UTC
Today the DoS possibility for Wireshark was disclosed via BugTraq
list: http://www.securityfocus.com/archive/1/498562/30/0/threaded
Vendor acknowledged the existence of this issue and had already
patched it in Subversion repository:
----- http://wiki.wireshark.org/Development/Roadmap
Complete:

* Rev 24989 & Rev 24994 - Support for RFC 2920 SMTP Command Pipelining,
which also happens to fix a DoS found by researchers at Bkis
-----

Fix: The following patch will apply the vendor fix from the trunk to the
1.0.4:


I had briefly tested it and it works for me.

The following VuXML entry should be evaluated and added:
  <vuln vid="">
    <topic>wireshark -- DoS in the SMTP dissector module</topic>
    <affects>
      <package>
	<name>wireshark</name>
	<name>wireshark-lite</name>
	<range><lt>1.0.4_1</lt></range>
      </package>
    </affects>
    <description>
      <body xmlns="http://www.w3.org/1999/xhtml">
	<p>Bach Khoa from Internetwork Security Center reports:</p>
	<blockquote cite="http://www.securityfocus.com/archive/1/498562/30/0/threaded">
	<p>On Nov 2008, Security Vulnerability Research Team of
	Bkis (SVRT-Bkis) has detected a vulnerability underlying
	WireShark 1.0.4 (lastest version).</p>
	<p>The flaw is in the function processing SMTP protocol and
	enables hacker to perform a DoS attack by sending a SMTP
	request with large content to port 25. The application then
	enter a large loop and cannot do anything else.</p>
	</blockquote>
      </body>
    </description>
    <references>
      <url>http://www.securityfocus.com/archive/1/498562/30/0/threaded</url>
      <url>http://wiki.wireshark.org/Development/Roadmap</url>
    </references>
    <dates>
      <discovery>2008-11-22</discovery>
    </dates>
  </vuln>
--- vuln.xml ends here -----iFNl7PIINNzTbMUeDPeFwIgF6hbx0yUm2kSIfPfPH55Q6OiC
Content-Type: text/plain; name="fix-DoS-in-SMTP-dissector.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="fix-DoS-in-SMTP-dissector.diff"

From 676903bce0030930fa99ce4a9692057c2020c319 Mon Sep 17 00:00:00 2001
From: Eygene Ryabinkin <rea-fbsd@codelabs.ru>
Date: Sun, 23 Nov 2008 02:04:51 +0300

See http://www.securityfocus.com/archive/1/498562/30/0/threaded for the
description of the vulnerability.  The patch was taken from the
Subversion repository of wireshark.

Signed-off-by: Eygene Ryabinkin <rea-fbsd@codelabs.ru>
---
 net/wireshark/Makefile                       |    2 +-
 net/wireshark/files/patch-fix-SMTP-DoS-1.0.4 |  356 ++++++++++++++++++++++++++
 2 files changed, 357 insertions(+), 1 deletions(-)
 create mode 100644 net/wireshark/files/patch-fix-SMTP-DoS-1.0.4

diff --git a/net/wireshark/Makefile b/net/wireshark/Makefile
index 49de12c..2e21104 100644
--- a/net/wireshark/Makefile
+++ b/net/wireshark/Makefile
@@ -7,7 +7,7 @@
 
 PORTNAME?=	wireshark
 PORTVERSION=	1.0.4
-PORTREVISION?=	0
+PORTREVISION?=	1
 CATEGORIES=	net ipv6
 MASTER_SITES=	http://www.wireshark.org/download/src/ \
     		http://wireshark.osmirror.nl/download/src/ \
diff --git a/net/wireshark/files/patch-fix-SMTP-DoS-1.0.4 b/net/wireshark/files/patch-fix-SMTP-DoS-1.0.4
new file mode 100644
index 0000000..e5d2e9e
--- /dev/null
+++ b/net/wireshark/files/patch-fix-SMTP-DoS-1.0.4
@@ -0,0 +1,356 @@
+Fix for the SMTP dissector DoS
+
+See: http://www.securityfocus.com/archive/1/498562/30/0/threaded
+Obtained from: http://anonsvn.wireshark.org/viewvc/trunk/epan/dissectors/packet-smtp.c?r1=24989&r2=24988&pathrev=24989&view=patch
+Obtained from: http://anonsvn.wireshark.org/viewvc/trunk/epan/dissectors/packet-smtp.c?r1=24994&r2=24993&pathrev=24994&view=patch
+
+--- epan/dissectors/packet-smtp.c	2008/04/13 16:21:22	24988
++++ epan/dissectors/packet-smtp.c	2008/04/13 16:33:44	24989
+@@ -97,10 +97,6 @@
+ 	"DATA fragments"
+ };
+ 
+-/* Define media_type/Content type table */
+-static dissector_table_t media_type_dissector_table;
+-
+-
+ static  dissector_handle_t imf_handle = NULL;
+ 
+ /*
+@@ -175,6 +171,7 @@
+     gint                    length_remaining;
+     gboolean                eom_seen = FALSE;
+     gint                    next_offset;
++    gint                    loffset;
+     gboolean                is_continuation_line;
+     int                     cmdlen;
+     fragment_data           *frag_msg = NULL;
+@@ -217,21 +214,6 @@
+      * longer than what's in the buffer, so the "tvb_get_ptr()" call
+      * won't throw an exception.
+      */
+-    linelen = tvb_find_line_end(tvb, offset, -1, &next_offset,
+-      smtp_desegment && pinfo->can_desegment);
+-    if (linelen == -1) {
+-      /*
+-       * We didn't find a line ending, and we're doing desegmentation;
+-       * tell the TCP dissector where the data for this message starts
+-       * in the data it handed us, and tell it we need one more byte
+-       * (we may need more, but we'll try again if what we get next
+-       * isn't enough), and return.
+-       */
+-      pinfo->desegment_offset = offset;
+-      pinfo->desegment_len = 1;
+-      return;
+-    }
+-    line = tvb_get_ptr(tvb, offset, linelen);
+ 
+     frame_data = p_get_proto_data(pinfo->fd, proto_smtp);
+ 
+@@ -267,6 +249,42 @@
+ 
+       }
+ 
++      if(request) {
++	frame_data = se_alloc(sizeof(struct smtp_proto_data));
++
++	frame_data->conversation_id = conversation->index;
++	frame_data->more_frags = TRUE;
++
++	p_add_proto_data(pinfo->fd, proto_smtp, frame_data);	
++
++      }
++
++    loffset = offset;
++    while (tvb_offset_exists(tvb, loffset)) {
++
++    linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset,
++      smtp_desegment && pinfo->can_desegment);
++    if (linelen == -1) {
++
++      if(offset == loffset) {
++      /*
++       * We didn't find a line ending, and we're doing desegmentation;
++       * tell the TCP dissector where the data for this message starts
++       * in the data it handed us, and tell it we need one more byte
++       * (we may need more, but we'll try again if what we get next
++       * isn't enough), and return.
++       */
++      pinfo->desegment_offset = loffset;
++      pinfo->desegment_len = 1;
++      return;
++      }
++      else {
++	linelen = tvb_length_remaining(tvb, loffset);
++	next_offset = loffset + linelen;
++      }
++    }
++    line = tvb_get_ptr(tvb, loffset, linelen);
++
+       /*
+        * Check whether or not this packet is an end of message packet
+        * We should look for CRLF.CRLF and they may be split.
+@@ -282,16 +300,16 @@
+ 	 * .CRLF at the begining of the same packet.
+ 	 */
+ 
+-	if ((request_val->crlf_seen && tvb_strneql(tvb, offset, ".\r\n", 3) == 0) ||
+-	    tvb_strneql(tvb, offset, "\r\n.\r\n", 5) == 0) {
++	if ((request_val->crlf_seen && tvb_strneql(tvb, loffset, ".\r\n", 3) == 0) ||
++	    tvb_strneql(tvb, loffset, "\r\n.\r\n", 5) == 0) {
+ 
+ 	  eom_seen = TRUE;
+ 
+-	}
++	} 
+ 
+-	length_remaining = tvb_length_remaining(tvb, offset);
+-	if (length_remaining == tvb_reported_length_remaining(tvb, offset) &&
+-	    tvb_strneql(tvb, offset + length_remaining - 2, "\r\n", 2) == 0) {
++	length_remaining = tvb_length_remaining(tvb, loffset);
++	if (length_remaining == tvb_reported_length_remaining(tvb, loffset) &&
++	    tvb_strneql(tvb, loffset + length_remaining - 2, "\r\n", 2) == 0) {
+ 
+ 	  request_val->crlf_seen = TRUE;
+ 
+@@ -310,11 +328,6 @@
+ 
+       if (request) {
+ 
+-	frame_data = se_alloc(sizeof(struct smtp_proto_data));
+-
+-	frame_data->conversation_id = conversation->index;
+-	frame_data->more_frags = TRUE;
+-
+ 	if (request_val->reading_data) {
+ 	  /*
+ 	   * This is message data.
+@@ -329,6 +342,9 @@
+ 	     */
+ 	    frame_data->pdu_type = SMTP_PDU_EOM;
+ 	    request_val->reading_data = FALSE;
++	    
++	    break;
++	    
+ 	  } else {
+ 	    /*
+ 	     * Message data with no EOM.
+@@ -340,7 +356,7 @@
+ 	       * We are handling a BDAT message.
+ 	       * Check if we have reached end of the data chunk.
+ 	       */
+-	      request_val->msg_read_len += tvb_length_remaining(tvb, offset);
++	      request_val->msg_read_len += tvb_length_remaining(tvb, loffset);
+ 
+               if (request_val->msg_read_len == request_val->msg_tot_len) {
+ 		/* 
+@@ -356,6 +372,8 @@
+ 		   */
+ 		  frame_data->more_frags = FALSE;
+ 		}
++		
++		break; /* no need to go through the remaining lines */
+ 	      }
+ 	    }
+ 	  }
+@@ -446,12 +464,15 @@
+ 	    frame_data->pdu_type = request_val->data_seen ? SMTP_PDU_MESSAGE : SMTP_PDU_CMD;
+ 
+ 	  }
+-
+ 	}
++      }
+ 
+-	p_add_proto_data(pinfo->fd, proto_smtp, frame_data);
++      /*
++       * Step past this line.
++       */
++      loffset = next_offset;
+ 
+-      }
++    }
+     }
+ 
+     /*
+@@ -463,6 +484,7 @@
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMTP");
+ 
+     if (check_col(pinfo->cinfo, COL_INFO)) {  /* Add the appropriate type here */
++      col_clear(pinfo->cinfo, COL_INFO);
+ 
+       /*
+        * If it is a request, we have to look things up, otherwise, just
+@@ -477,21 +499,38 @@
+ 	case SMTP_PDU_MESSAGE:
+ 
+ 	  length_remaining = tvb_length_remaining(tvb, offset);
+-	  col_set_str(pinfo->cinfo, COL_INFO, smtp_data_desegment ? "DATA fragment" : "Message Body");
++	  col_set_str(pinfo->cinfo, COL_INFO, smtp_data_desegment ? "C: DATA fragment" : "C: Message Body");
+ 	  col_append_fstr(pinfo->cinfo, COL_INFO, ", %d byte%s", length_remaining,
+ 			  plurality (length_remaining, "", "s"));
+ 	  break;
+ 
+ 	case SMTP_PDU_EOM:
+ 
+-	  col_add_fstr(pinfo->cinfo, COL_INFO, "EOM: %s",
+-	      format_text(line, linelen));
++	  col_set_str(pinfo->cinfo, COL_INFO, "C: .");
++
+ 	  break;
+ 
+ 	case SMTP_PDU_CMD:
+ 
+-	  col_add_fstr(pinfo->cinfo, COL_INFO, "Command: %s",
+-	      format_text(line, linelen));
++	  loffset = offset;
++	  while (tvb_offset_exists(tvb, loffset)) {
++	    /*
++	     * Find the end of the line.
++	     */
++	    linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);
++	    line = tvb_get_ptr(tvb, loffset, linelen);
++
++	    if(loffset == offset) 
++	      col_append_fstr(pinfo->cinfo, COL_INFO, "C: %s",
++			   format_text(line, linelen));
++	    else {
++	      col_append_fstr(pinfo->cinfo, COL_INFO, " | %s",
++			   format_text(line, linelen));
++	    }
++
++	    loffset = next_offset;
++
++	  }
+ 	  break;
+ 
+ 	}
+@@ -499,9 +538,24 @@
+       }
+       else {
+ 
+-	col_add_fstr(pinfo->cinfo, COL_INFO, "Response: %s",
+-	    format_text(line, linelen));
++	  loffset = offset;
++	  while (tvb_offset_exists(tvb, loffset)) {
++	    /*
++	     * Find the end of the line.
++	     */
++	    linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);
++	    line = tvb_get_ptr(tvb, loffset, linelen);
++
++	    if(loffset == offset) 
++	      col_append_fstr(pinfo->cinfo, COL_INFO, "S: %s",
++			   format_text(line, linelen));
++	    else {
++	      col_append_fstr(pinfo->cinfo, COL_INFO, " | %s",
++			   format_text(line, linelen));
++	    }
+ 
++	    loffset = next_offset;
++	  }
+       }
+     }
+ 
+@@ -556,8 +610,7 @@
+ 	   * DATA command this terminates before sending another
+ 	   * request, but we should probably handle it.
+ 	   */
+-	  proto_tree_add_text(smtp_tree, tvb, offset, linelen,
+-	      "EOM: %s", format_text(line, linelen));
++	  proto_tree_add_text(smtp_tree, tvb, offset, linelen, "C: .");
+ 
+ 	  if(smtp_data_desegment) {
+ 
+@@ -578,6 +631,15 @@
+ 	   * previous command before sending another request, but we
+ 	   * should probably handle it.
+ 	   */
++
++	  loffset = offset;
++	while (tvb_offset_exists(tvb, loffset)) {
++
++	  /*
++	   * Find the end of the line.
++	   */
++	  linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);
++
+ 	  if (linelen >= 4)
+ 	    cmdlen = 4;
+ 	  else
+@@ -587,16 +649,16 @@
+ 	  /*
+ 	   * Put the command line into the protocol tree.
+ 	   */
+-	  ti = proto_tree_add_text(smtp_tree, tvb, offset, next_offset - offset,
++	  ti = proto_tree_add_text(smtp_tree, tvb, loffset, next_offset - loffset,
+ 	        "Command: %s",
+-		tvb_format_text(tvb, offset, next_offset - offset));
++		tvb_format_text(tvb, loffset, next_offset - loffset));
+ 	  cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp);
+ 
+ 	  proto_tree_add_item(cmdresp_tree, hf_smtp_req_command, tvb,
+-			      offset, cmdlen, FALSE);
++			      loffset, cmdlen, FALSE);
+ 	  if (linelen > 5) {
+ 	    proto_tree_add_item(cmdresp_tree, hf_smtp_req_parameter, tvb,
+-				offset + 5, linelen - 5, FALSE);
++				loffset + 5, linelen - 5, FALSE);
+ 	  }
+ 
+ 	  if (smtp_data_desegment && !frame_data->more_frags) {
+@@ -605,6 +667,13 @@
+ 	    frag_msg = fragment_end_seq_next (pinfo, frame_data->conversation_id, smtp_data_segment_table,
+ 					      smtp_data_reassembled_table);
+ 	  }
++
++	  /*
++	   * Step past this line.
++	   */
++	  loffset = next_offset;
++	  
++	}
+ 	}
+ 
+ 	if (smtp_data_desegment) {
+@@ -689,8 +758,8 @@
+ 	  /*
+ 	   * If it's not a continuation line, quit.
+ 	   */
+-	  if (!is_continuation_line)
+-	    break;
++	  /* if (!is_continuation_line)
++	     break; */
+ 
+ 	}
+ 
+@@ -771,7 +840,6 @@
+   };
+   module_t *smtp_module;
+ 
+-
+   proto_smtp = proto_register_protocol("Simple Mail Transfer Protocol",
+ 				       "SMTP", "smtp");
+ 
+@@ -808,11 +876,6 @@
+   dissector_add("tcp.port", TCP_PORT_SMTP, smtp_handle);
+   dissector_add("tcp.port", TCP_PORT_SUBMISSION, smtp_handle);
+ 
+-  /*
+-   * Get the content type and Internet media type table
+-   */
+-  media_type_dissector_table = find_dissector_table("media_type");
+-
+   /* find the IMF dissector */
+   imf_handle = find_dissector("imf");
+ 
+--- epan/dissectors/packet-smtp.c	2008/04/13 16:55:56	24993
++++ epan/dissectors/packet-smtp.c	2008/04/13 16:58:57	24994
+@@ -167,7 +167,7 @@
+     struct smtp_request_val *request_val;
+     const guchar            *line;
+     guint32                 code;
+-    int                     linelen;
++    int                     linelen = 0;
+     gint                    length_remaining;
+     gboolean                eom_seen = FALSE;
+     gint                    next_offset;
-- 
1.6.0.4
How-To-Repeat: 
Look at http://www.securityfocus.com/archive/1/498562/30/0/threaded
and http://wiki.wireshark.org/Development/Roadmap
Comment 1 Edwin Groothuis freebsd_committer freebsd_triage 2008-11-22 23:20:15 UTC
Responsible Changed
From-To: freebsd-ports-bugs->marcus

Over to maintainer (via the GNATS Auto Assign Tool)
Comment 2 dfilter service freebsd_committer freebsd_triage 2008-12-07 19:44:17 UTC
miwi        2008-12-07 19:44:04 UTC

  FreeBSD ports repository

  Modified files:
    net/wireshark        Makefile 
  Added files:
    net/wireshark/files  patch-fix-SMTP-DoS-1.0.4 
  Log:
  - Fix DoS in SMTP dissector
  - Bump PORTREVISION
  
  PR:             129077 (based on)
  Submitted by:   Eygene Ryabinkin <rea-fbsd@codelabs.ru>
  Approved by:    marcus@ (maintainer)
  Obtained from:  wireshake svn
  Security:       http://www.vuxml.org/freebsd/baece347-c489-11dd-a721-0030843d3802.html
  
  Revision  Changes    Path
  1.137     +1 -1      ports/net/wireshark/Makefile
  1.1       +356 -0    ports/net/wireshark/files/patch-fix-SMTP-DoS-1.0.4 (new)
_______________________________________________
cvs-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/cvs-all
To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
Comment 3 Martin Wilke freebsd_committer freebsd_triage 2008-12-07 19:44:23 UTC
State Changed
From-To: open->closed

Committed. Thanks!