Vulnerability Development mailing list archives

Re: mpg123 DoS ... It receives a SIGSEGV.


From: Daniel Kobras <kobras () debian org>
Date: Fri, 28 Apr 2006 22:47:51 +0200

On Sun, Apr 02, 2006 at 05:11:55PM -0600, "A. Alejandro Hernández" wrote:
I was listening a song ( http://www.genexx.org/nitrous/Belanova-Y.mp3 ) 
and mpg123 died.
(...)
nitrous@lsd:~/vulndev/mpg123fuck$ gdb -q ./mpg123
(gdb) r Belanova-Y.mp3
Starting program: /home/nitrous/vulndev/mpg123fuck/mpg123 Belanova-Y.mp3
High Performance MPEG 1.0/2.0/2.5 Audio Player for Layer 1, 2 and 3.
Version 0.59r (1999/Jun/15). Written and copyrights by Michael Hipp.
Uses code from various people. See 'README' for more!
THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! USE AT YOUR OWN RISK!
Title  : Y                               Artist: Belanova
Album  : Cocktail                        Year  : 2003
Comment:                                 Genre : Blues

Playing MPEG stream from Belanova-Y.mp3 ...
Junk at the beginning 49443303
MPEG 2.0 layer III, 128 kbit/s, 24000 Hz joint-stereo
big_values too large!
mpg123: Can't rewind stream by 3341 bits!
Illegal Audio-MPEG-Header 0x00000000 at offset 0x32f.
Skipped 3513063 bytes in input.

Program received signal SIGSEGV, Segmentation fault.
do_layer3 (fr=0x8077e39, outmode=-1129440371, ai=0xffffffff) at 
layer3.c:1179
1179             register real bu = *--xr2,bd = *xr1;

It's an overflow of an array on the stack of do_layer3(), and possibly
allows to inject code into the player process. I'm not aware of an
analysis of this hole so far, so here's mine, copied from
http://bugs.debian.org/361863:

The root cause of this bug lies in layer3.c::III_i_stereo(). A specially
crafted MPEG 2.0-type stereo frame with block type feature set to 2 in
the frame header can trigger a stack overflow in this function if it
flags all subbands to belong to the left channel. I'm not sure whether
such settings make sense for real data. In any case, the code didn't
take it into account, and as a result copied a fixed amount of data past
the end of the xr array. It is allocated on the stack in the calling
function, do_layer3(). There are plenty of other variables on the stack
before the xr array (actually called hybridIn in do_layer3()), so the
overflow cannot be exploited directly. However, it's possible to
overwrite several variable in do_layer3() from user-supplied data.
gr_info->maxb in particular is used later on as a loop boundary.
Modifying this value it is possible to overflow the same xr/hybridIn
array once more in III_antialias(), but this time the size of the
overflowing region can be arbitrarily large. To a limited extent, data
written to the overflow region can be user-controlled. Therefore, it
might be possible to exploit this bug to execute arbitrary code with
privileges of a user opening a malicious MPEG 2.0 layer3 file. The
attached patch prevents the hole by skipping the unnecessary copy of
subband data in the corner case mentioned above.

Regards,

Daniel.

Index: layer3.c
===================================================================
RCS file: /home/kobras/cvsroot/debian/mpg123/layer3.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- layer3.c    7 Sep 2004 13:48:58 -0000       1.5
+++ layer3.c    28 Apr 2006 15:02:34 -0000      1.6
@@ -1125,7 +1125,10 @@
       } 
       else { /* ((gr_info->block_type != 2)) */
         int sfb = gr_info->maxbandl;
-        int is_p,idx = bi->longIdx[sfb];
+        int is_p,idx;
+       if (sfb > 21)
+         return;
+       idx = bi->longIdx[sfb];
         for ( ; sfb<21; sfb++) {
           int sb = bi->longDiff[sfb];
           is_p = scalefac[sfb]; /* scale: 0-15 */

Current thread: