** Please note that this issue is confidential and no information should be disclosed until it is made public, see "Whiteboard" for a date ** Drew Yao writes: We have found a security issue in libTIFF's handling of LZW-encoded images. The use of uninitialized data could lead to a buffer underflow and a crash or arbitrary code execution. CVE-ID: CVE-2008-2327 Versions known to be affected: v3.8.2 Timing: This issue should remain embargoed until 8/25/2008. Credit: Drew Yao of Apple Product Security We have contacted the libTIFF maintainers about this issue. A brief introduction to LZW decoding: http://www.fileformat.info/format/tiff/corion-lzw.htm http://en.wikipedia.org/wiki/Lzw#Decoding The LZW algorithm is based on a translation table, or string table, that maps strings of input characters into codes. The TIFF implementation uses variable-length codes, with a maximum code length of 12 bits The string table is initialized to contain all possible single- character strings. There are 256 of them, numbered 0 through 255, since our characters are bytes. There are also special codes: #define CODE_CLEAR 256 /* code to clear string table */ #define CODE_EOI 257 /* end-of-information code */ #define CODE_FIRST 258 /* first free code entry */ As decoding continues, longer strings are added to the string table as linked lists of characters. If the string table gets full(4096 entries), there is a "Clear code" which signals to reinitialize the string table. tif_lzw.c In LZWSetupDecode(): sp->dec_codetab = (code_t*)_TIFFmalloc(CSIZE*sizeof (code_t)); In LZWPreDecode(): sp->dec_free_entp = sp->dec_codetab + CODE_FIRST; /* * Zero entries that are not yet filled in. We do * this to guard against bogus input data that causes * us to index into undefined entries. If you can * come up with a way to safely bounds-check input codes * while decoding then you can remove this operation. */ _TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t)); In LZWDecodeCompat(), LZWDecode(), and LZWDecodeVector(), when a CODE_CLEAR code is received, the string table does not get re-zeroed, leading to uninitialized data in the table being used, if the next code after the CODE_CLEAR is > CODE_FIRST. For example in LZWDecodeCompat(): while (occ > 0) { NextCode(tif, sp, bp, code, GetNextCodeCompat); if (code == CODE_EOI) break; if (code == CODE_CLEAR) { free_entp = sp->dec_codetab + CODE_FIRST; <-- free_entp points to the first free entry after the constant entries. nbits = BITS_MIN; nbitsmask = MAXCODE(BITS_MIN); maxcodep = sp->dec_codetab + nbitsmask; NextCode(tif, sp, bp, code, GetNextCodeCompat); <-- get the next code. The implementation expects it to be < CODE_FIRST, but that might not be true in a malicious file. if (code == CODE_EOI) break; *op++ = code, occ--; oldcodep = sp->dec_codetab + code; continue; } codep = sp->dec_codetab + code; <--codep points into uninitialized data ... do { *--tp = codep->value; <-- potential buffer underflow } while( (codep = codep->next) != NULL); [...] A simple fix is to zero out the whole string table starting at CODE_FIRST whenever a CODE_CLEAR is received. The attached patch against 3.8.2 does this. I have tested this fix to properly display a bunch of valid files, and not crash after heavy fuzzing.
Drew also informed us about the following issue: http://bugzilla.maptools.org/show_bug.cgi?id=1929
Created attachment 162354 [details, diff] tiff-3.8.2-CVE-2008-2327.patch
Created attachment 162356 [details, diff] tiff-3.8.2-bug1929.patch
We have no upstream comment on either of the two patches, and probably won't have until after the embargo timeline. I'll attach an ebuild applying the existing patches, and we can update them later if upstream decides otherwise.
Created attachment 163378 [details, diff] tiff-3.8.2-r4.ebuild
Arch Security Liaisons, please test the attached ebuild and report it stable on this bug. Target keywords : "alpha amd64 arm hppa ia64 m68k ppc ppc64 s390 sh sparc x86" CC'ing current Liaisons: alpha : yoswink, armin76 amd64 : keytoaster, tester hppa : jer ppc : dertobi123 ppc64 : corsair sparc : fmccor x86 : maekke, armin76
HPPA is OK.
looks good on amd64/x86.
looks good on ppc64
alpha is ok
now public via http://secunia.com/advisories/31610/
I combined both patches into one because it was decided to combine both issues (Drew Yao and the upstream bug) into the CVE. Committed the ebuild to the tree with the gathered keywords, still to do: Arches, please test and mark stable: =media-libs/tiff-3.8.2-r4 Target keywords : "alpha amd64 arm hppa ia64 m68k ppc ppc64 s390 sh sparc x86" Already stabled : "alpha amd64 hppa ppc64 x86" Missing keywords: "arm ia64 m68k ppc s390 sh sparc"
ia64/sparc stable
ppc stable
GLSA request filed.
GLSA 200809-07