[helix-maintainers] Bug#340270: helix-player: CVE-2005-2629, CVE-2005-2630: Do these vulnerabilities affect Helix as well?

Moritz Muehlenhoff jmm at inutil.org
Tue Nov 22 22:04:50 UTC 2005


Noah Meyerhans wrote:
> > According to http://service.real.com/help/faq/security/051110_player/EN/
> > helix-player is not vulnerable to the "malicious skin" problems, but
> > only to the stack overrun via malicious RealMedia file".  This bug is
> > allegedly fixed in 1.0.6.
> > 
> > I can examine the diff between 1.0.5 and 1.0.6 and try to isolate the
> > changes relative to the security problem.  Or, if the maintainer (or
> > anybody else) could do it sooner, that would be appreciated.  I'm not
> > sure if I'll have time today or not...
> 
> OK, I've had some time to look at 1.0.6, and I'm confused.  The code
> seems to be fixing a problem relating to http chunked encoding support.

I've read the interdiff between 1.0.5 and 1.0.6 and three different
issues seem to have been addressed:
1. A server can send more data than indicated and overflow pChunkedEncoding->buf
2. A format string vulnerability in the GTK interface (hxgerror.cpp)
3. A potential buffer overflow in hxbitset.cpp, needs to be checked further
   with the surrounding code

I'm attaching it for reference.

> None of the reports at
> http://service.real.com/help/faq/security/051110_player/EN/ or
> cve.mitre.org or http://www.frsirt.com/english/advisories/2005/2385
> mention http chunked encoding at all...
> 
> More details would be helpful.  It may be that I'm looking at the right
> bug, and am just confused by the terminology being used.

I'm quite convinced that be above "chunked encoding" change relates to
the realmedia buffer overflow:

Real's description:
> * Exploit 2: To fashion a malicious RealMedia file which could have
> caused stack overflow to allow an attacker to execute arbitrary code
> on a customer's machine.

FrSIRT's description:
> The first issue is due to a stack overflow error when processing a malformed
> data packet contained in a Real Media file, which could be exploited
> by remote attackers to compromise a vulnerable system by convincing a user
> to visit a malicious Web page hosting a specially crafted ".rm" file.

This matches the code comments and http://www.multimedia.cx/rmff.htm gives
a description of .rm-streaming, which confirms this as well.

Cheers,
        Moritz
-------------- next part --------------
diff -Naur helix-player-1.0.5/filesystem/http/httpfsys.cpp helix-player-1.0.6/filesystem/http/httpfsys.cpp
--- helix-player-1.0.5/filesystem/http/httpfsys.cpp	2004-07-13 23:00:44.000000000 +0200
+++ helix-player-1.0.6/filesystem/http/httpfsys.cpp	2005-09-14 02:08:15.000000000 +0200
@@ -1,5 +1,5 @@
 /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: httpfsys.cpp,v 1.28.2.5 2004/07/13 21:00:44 bobclark Exp $
+ * Source last modified: $Id: httpfsys.cpp,v 1.28.2.5.4.1 2005/09/14 00:08:15 darrick Exp $
  * 
  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  * 
@@ -7236,29 +7236,71 @@
 	} 
 	else if (*pChunk == CR && *(pChunk+1) == LF) 
 	{
-	    // first CRLF marks the chunk header
-	    if (CE_HEADER_PENDING == pChunkedEncoding->state)
-	    {
-		pChunkedEncoding->state = CE_HEADER_READY;
-	    }
-	    // ignore the CRLF within the chunk body while we are 
-	    // still reading it
-	    else if (pChunkedEncoding->read < pChunkedEncoding->size)
-	    {
-		pChunkedEncoding->buf[pChunkedEncoding->read++] = *pChunk;
-	    }
-	    // last CRLF marks the end of chunk
-	    else if (CE_BODY_PENDING == pChunkedEncoding->state)
-	    {
-		HX_ASSERT(pChunkedEncoding->read == pChunkedEncoding->size);
-		pChunkedEncoding->state = CE_BODY_READY;
-	    }
-	} 
-	else
-	{
-	    pChunkedEncoding->buf[pChunkedEncoding->read++] = *pChunk;
-	}
-	pChunk++, l--;
+            // first CRLF marks the chunk header
+            if (CE_HEADER_PENDING == pChunkedEncoding->state)
+            {
+                pChunkedEncoding->state = CE_HEADER_READY;
+            }
+            // ignore the CRLF within the chunk body while we are
+            // still reading it
+            else if (pChunkedEncoding->read < pChunkedEncoding->size)
+            {
+                pChunkedEncoding->buf[pChunkedEncoding->read++] = *pChunk;
+            }
+            // last CRLF marks the end of chunk
+            else if (CE_BODY_PENDING == pChunkedEncoding->state)
+            {
+                HX_ASSERT(pChunkedEncoding->read == pChunkedEncoding->size);
+
+                // Remote HTTP server is sending more data than specified by 
+                // chunk-size. This may be an attack on the server, so don't 
+                // accept data sent in this fashion.
+
+                // This should NEVER happen. This condition should be caught
+                // earlier, but just in case fail gracefully anyway.
+                if (pChunkedEncoding->read > pChunkedEncoding->size)
+                {
+                    rc = HXR_UNEXPECTED;
+                    break;
+                }
+
+                pChunkedEncoding->state = CE_BODY_READY;
+            }
+        }
+        else
+        {
+            // chunk-size exceeded MAX_CHUNK_SIZE in length.
+            // A hex-number >=1024 digits is very suspicious.
+
+            if ((CE_HEADER_PENDING == pChunkedEncoding->state)
+            &&  (pChunkedEncoding->read >= MAX_CHUNK_SIZE))
+            {
+                rc = HXR_UNEXPECTED;
+                break;
+            }
+
+            // Remote HTTP server is sending more data than specified by 
+            // chunk-size. This may be an attack on the server, so don't 
+            // accept data sent in this fashion.
+
+            else if ((CE_BODY_PENDING == pChunkedEncoding->state)
+                 &&  (pChunkedEncoding->read >= pChunkedEncoding->size))
+            {
+                HX_ASSERT(pChunkedEncoding->size > 0);
+
+                // If read is ever > size, we're in trouble--
+                // the buffer has already been overrun.
+                HX_ASSERT(pChunkedEncoding->read == pChunkedEncoding->size);
+
+                rc = HXR_UNEXPECTED;
+                break;
+            }
+
+            HX_ASSERT((CE_HEADER_PENDING == pChunkedEncoding->state) || (CE_BODY_PENDING == pChunkedEncoding->state));
+
+            pChunkedEncoding->buf[pChunkedEncoding->read++] = *pChunk;
+        }
+        pChunk++, l--;
     }
 
     return rc;
diff -Naur helix-player-1.0.5/player/common/gtk/hxgerror.cpp helix-player-1.0.6/player/common/gtk/hxgerror.cpp
--- helix-player-1.0.5/player/common/gtk/hxgerror.cpp	2004-10-18 20:55:17.000000000 +0200
+++ helix-player-1.0.6/player/common/gtk/hxgerror.cpp	2005-09-09 03:32:19.000000000 +0200
@@ -1,5 +1,5 @@
 /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: hxgerror.cpp,v 1.3.6.4 2004/10/18 18:55:17 rggammon Exp $
+ * Source last modified: $Id: hxgerror.cpp,v 1.3.6.4.4.1 2005/09/09 01:32:19 rggammon Exp $
  * 
  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  * 
@@ -135,7 +135,7 @@
         g_string_append_printf(message, " (%s)", pUserString);
     }
    
-    err = g_error_new (HX_ERROR, code, message->str);
+    err = g_error_new (HX_ERROR, code, "%s", message->str);
 
     g_string_free(message, TRUE);
     
diff -Naur helix-player-1.0.5/protocol/common/util/hxbitset.cpp helix-player-1.0.6/protocol/common/util/hxbitset.cpp
--- helix-player-1.0.5/protocol/common/util/hxbitset.cpp	2004-07-09 04:05:26.000000000 +0200
+++ helix-player-1.0.6/protocol/common/util/hxbitset.cpp	2005-09-07 15:31:45.000000000 +0200
@@ -1,5 +1,5 @@
 /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: hxbitset.cpp,v 1.5.32.1 2004/07/09 02:05:26 hubbe Exp $
+ * Source last modified: $Id: hxbitset.cpp,v 1.5.32.1.4.1 2005/09/07 13:31:45 ehyche Exp $
  * 
  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  * 
@@ -251,7 +251,7 @@
         if (nBitsetSize > _BS_SHORT_LEN)
         {
             _BS_word* pTempBitset = new _BS_word[nBitsetSize];
-            memcpy(pTempBitset, m_pBitset, m_nBitsetSize); /* Flawfinder: ignore */
+            memcpy(pTempBitset, m_pBitset, m_nBitsetSize * sizeof(_BS_word)); /* Flawfinder: ignore */
             memset(&(pTempBitset[m_nBitsetSize]), 0,
                    HX_SAFESIZE_T(sizeof(_BS_word) * (nBitsetSize - m_nBitsetSize)));
             if (m_pBitset != m_pShortBitset)


More information about the helix-maintainers mailing list