redpig.dataspill.org: Multiple vulnerabilities in Ogg Tremor (and Vorbis)

»Multiple vulnerabilities in Ogg Tremor and Vorbis After running across a number of stack overflows in the older low-mem branch that don't longer exist in (tremor) trunk, a revisit to the codebase revealed a number of remaining vulnerabilities.

Background
Ogg Vorbis and Tremor are libraries for decoding Ogg media files. Tremor does so without relying on floating point unit support.
Details
Below are some unrefined findings. Monty(@xiph.org) was kind enough to take on analysis and patching when I reported preliminary information. In addition, various Linux vendors also contributed analysis and testing results, like Tomas Hoger of Redhat. Thanks!! So, the basic findings --

Tremor --
= NULL pointer dereference
+ Looks like it is related to incorrectly checking for valid data
after valid headers are read
- Samples: 010.ogg 011.ogg
* oggpack_readinit (b=0xffffcb8c, r=0x0) at bitwise.c:69:
b->headptr=b->head->buffer->data+b->head->begin;

= Divide by zero
+ The dimension of the codebook are used as the divisor without
checking to see if it is greater than zero
- Samples: 002.ogg
* _book_maptype1_quantvals (b=0x0) at sharedbook.c:150:  int
vals=b->entries>>((bits-1)*(b->dim-1)/b->dim);

= Divide by zero
+ partitions_per_word is zero and it SIGFPEs
- Samples: 014.ogg
* res012.c:278:res2_inverse.c:()         int
partwords=(partvals+partitions_per_word-1)/partitions_per_word;

= Integer overflow leading to a heap overflow
+ This occurs when partvals is derived from the supplied partition
  count and dimensions is moderately large.
- No sample
* res012.c:157-160

Vorbis --
= Infinite loop and/or crashing due to stack corruption
+ Looks to be related to the inline math functions. After the line
below, b and vals are the same value.  (dim==0 issue)
- Samples: 002.ogg
* _book_maptype1_quantvals (b=0x8065f20) at sharedbook.c:151:   long
vals=floor(pow((float)b->entries,1.f/b->dim));

= Additional corruption in pre-1.0 Vorbis
+ Tomas and Monty nailed this down to _make_decode_tree()
- Samples: 003.ogg, 004.ogg, 005.ogg


Vorbis and Tremor --
= Integer overflow in the computation of quantvals and of the space required for quantlist.
+ A codebook has 16-bit dimensions and 24-bit entries.  quantvals, the size of 
quantlist, is calculated by mutliplying them together.  This can easily overflow the 
unsigned 32-bit integer quantvals is stored in.  In addition, on ogg_malloc() of the 
quantlist, quantvals is multiplied times the size of a quantlist entry (4).  This is 
another integer overflow.  If only the second case is attacked, a straight heap 
overflow occurs in the subsequent for loop.  If the first one is attacked, then later
 out of bounds reads occur in decoding.  Note, the map type must be 2 for this to be 
reachable.  It's also worth noting that the range of the entries in the quantlist may
be up to 4 bits + 1.

- Samples: maptype2.ogg



Tremor/lowmem --
Most of the findings above in Tremor along with a large number of
potentially exploitable stack buffer overflows. Sample 001.ogg is 
good example of the codebook stack buffer overflow.

All of the samples can be found here. [Please go easy on my bandwidth!]
Impact
The impact of these vulnerabilities largely depends on the context of use. Denial of service attacks are quite simple and there is potential for successful code execution.
Remediation
Upgrade to the latest patched versions supplied by your vendor.
Testing methodology
Testing was primarily done using fuzz and flayer. Initial testing of tremor was handled with a simple test harness built on the supplied example_ivorbisfile.c. Purely random data sampled from /dev/urandom was fed to the example application. With flayer, clearly blocking checks were bypassed (memcmp for OggS and the page checksum test).

With the basic checks successfully removed (without recompilation, etc), fuzz was used against an existing, valid Ogg file applying the "Mexican Wave" byte-modification algorithm.

Once the wave had reached the codebook headers, numerous crashes occurred. With samples in tow, valid checksums were inserted (by snooping the test in gdb with a debugging build). The backtraces were then followed, and the vectors of the attack isolated. Once I saw the behavior in the codebook functions, I modified libvorbis to generate codebook entries based on environment variables (getenv()). Using the modifying library, I created a number of samples with unlikely and unchecked values. In some cases, the encoder would not be able to handle these cases and modifications were made dynamically during encoding using gdb.

The results can be found here.
References
  • CVEs: CVE-2008-1418,CVE-2008-1419, CVE-2008-1420, CVE-2008-1423, CVE-2008-2009
  • Credit
    Thanks to my employer who sponsored some of this work, and to Tomas Hoger of Redhat, and Monty and Ralph of Xiph for the hard work in getting everything up to date. (And to coley@mitre for dealing with the back and forth and CVE assignments!)

    0 comments:
    This page does not necessarily reflect the views of my employer or anyone I'm associated with.
    redpig@dataspill.org