VLC versions 1.0.0 and below suffer from an integer underflow.
650aca25cb84d71eb4fa0785a245cabb44834ea872441694d0a5359c9abff262
Advisory:
The Movie Player and VLC Media Player Real Data Transport
parsing integer underflow.
Affected products:
The Movie player svn r29438 [1]
VLC media player <= 1.0.0 [2]
Possible others applications that use the xine lib code [3].
Discovred by:
tixxDZ <tixxdz at gmail dot com>
DZCORE Labs, Algeria
Date reported:
2009/07/25
Release Date:
2009/07/27
Solutions:
VLC: update to VLC media player 1.0.1 [2] [4].
Mplayer: please see Patches section.
---------
Abstract:
---------
Mplayer
Source file: stream/realrtsp/real.c
function: int real_get_rdt_chunk(rtsp_t *rtsp_session,
char **buffer,
int rdt_rawdata)
VLC
Source file: modules/access/rtsp/real.c
function: int real_get_rdt_chunk_header(rtsp_client_t *rtsp_session,
rmff_pheader_t *ph)
The original code is part of the xine library [3]:
Source file: src/input/libreal/real.c
function: int real_get_rdt_chunk(rtsp_t *rtsp_session,
unsigned char **buffer)
Function real_get_rdt_chunk() calls rtsp_read_data() to read RDT
(Real Data Transport) chunks headers from the network and after that it will
parse them.
A controled variable is used to allocate a buffer and later passed on to the
rtsp_read_data() function in order to specify the length of an RDT chunk
data to read from the network.
An integer underflow can be triggered when parsing a malformed RDT header chunk,
a remote attacker can exploit it to execute arbitrary code in the context of
the application.
The xine lib [3] seems not to be vulnerable due to an additional check in the
xio_rw_abort() funcion (file: src/xine-engine/io_helper.c), which takes the
length of an RDT packet as an off_t type and performs some comparison checks
(line: 350) before reading chunks from the network.
The Movie player [1] and the VLC media player [2] are vulnerable, the length
of an RDT packet is passed as an unsigned int to their own network read
functions.
-----------
Descripton:
-----------
xine-lib source file: src/input/libreal/real.c
int real_get_rdt_chunk(rtsp_t *rtsp_session, unsigned char **buffer) {
int n=1;
uint8_t header[8];
rmff_pheader_t ph;
int size;
int flags1;
int unknown1;
uint32_t ts;
n=rtsp_read_data(rtsp_session, header, 8);
if (n<8) return 0;
if (header[0] != 0x24)
{
lprintf("rdt chunk not recognized: got 0x%02x\n", header[0]);
return 0;
}
[1] size=(header[1]<<16)+(header[2]<<8)+(header[3]);
flags1=header[4];
if ((flags1!=0x40)&&(flags1!=0x42))
{
lprintf("got flags1: 0x%02x\n",flags1);
if (header[6]==0x06)
{
lprintf("got end of stream packet\n");
return 0;
}
...
[2] size-=9;
}
unknown1=(header[5]<<16)+(header[6]<<8)+(header[7]);
n=rtsp_read_data(rtsp_session, header, 6);
if (n<6) return 0;
ts=_X_BE_32(header);
lprintf("ts: %u size: %u, flags: 0x%02x, unknown values: %u 0x%02x 0x%02x\n",
ts, size, flags1, unknown1, header[4], header[5]);
[3] size+=2;
ph->object_version=0;
[4] ph->length=size;
ph->stream_number=(flags1>>1)&1;
ph->timestamp=ts;
ph->reserved=0;
ph->flags=0; /* TODO: determine keyframe flag and insert here? */
[5] xine_buffer_ensure_size(*buffer, 12+size);
rmff_dump_pheader(&ph, *buffer);
[6] size-=12;
[7] n=rtsp_read_data(rtsp_session, (*buffer)+12, size);
return (n <= 0) ? 0 : n+12;
}
[1] The signed int size variable is filled with data from the network.
[2] [3] Some arithmetics operations, we assume that at the end size == 11.
[4] The value of the size variable is assigned to the ph->length.
[5] The size variable is used to allocate (realloc) space for the buffer.
[6] An integer underflow is triggered, size == 0xffffffff.
[7] The size variable is passed to the rtsp_read_data() function as an
unsigned integer in order to specify the length of an RDT packet.
Mplayer:
Mplayer is vulnerable, the rtsp_read_data() function passes the length
to the read_stream() function (file: stream/librtsp/rtsp.c) as a size_t
type which can lead to read a big amount of data from the network and
cause a heap overflow.
VLC:
VLC is vulnerable, the real_get_rdt_chunk_header() function will read
and parse the header, the vulnerable call to the rtsp_read_data()
function is made by the real_get_rdt_chunk() function, the length is
passed to the __net_Read() function (file: src/network/io.c) as a
size_t type which can lead to read a big amount of data from the
network and cause a heap overflow.
--------
Patches:
--------
VLC
Official patch by the VideoLAN team (Patch development time: 2 hours) [4].
Mplayer
Unofficial patch by tixxDZ
diff -Naur stream/realrtsp/real.c stream/realrtsp/real.c.new
--- stream/realrtsp/real.c 2009-07-27 01:09:18.000000000 +0100
+++ stream/realrtsp/real.c.new 2009-07-27 01:12:35.000000000 +0100
@@ -386,6 +386,7 @@
return (n <= 0) ? 0 : n;
}
rmff_dump_pheader(&ph, *buffer);
+ if (size<12) return 0;
size-=12;
n=rtsp_read_data(rtsp_session, (*buffer)+12, size);
-----------
References:
-----------
[1] http://www.mplayerhq.hu/
[2] http://www.videolan.org/
[3] http://www.xine-project.org/
[4] http://git.videolan.org/?p=vlc.git;a=commitdiff;h=dc74600c97eb834
c08674676e209afa842053aca
-----------
Disclaimer:
-----------
The document is provided as is without warranty of any kind. The content
may change without notice. In no event shall the author be liable for any
special, direct or indirect damages, losses or unlawful offences.
Use at your own risk.
Copyright (c) 2009 tix tixxDZ, DZCORE Labs. All rights reserved.