To comment on the following update, log in, then open the issue:
http://www.openoffice.org/issues/show_bug.cgi?id=98145
Issue #|98145
Summary|OpenOffice writer doc filetype Prl Parsing Heap Overf
|low Vuln
Component|Word processor
Version|OOO300m9
Platform|PC
URL|
OS/Version|All
Status|UNCONFIRMED
Status whiteboard|
Keywords|
Resolution|
Issue type|DEFECT
Priority|P3
Subcomponent|code
Assigned to|writerneedsconfirm
Reported by|wooshi
--- Additional comments from woo...@openoffice.org Fri Jan 16 13:47:37
+ 2009 ---
OpenOffice Prl Parsing Heap Overflow Vuln
Test version: Version 3.0.0 OOO300m9 Build 9358 on Windows XP
Description:
1. Abstract
There is a heap overflow problem in OpenOffice which could allow an
attacker to
execute arbitrary code with the privileges of the current user. The Heap
overflow issues exist within the code responsible for parsing Prl in a DOC file.
This allows an attacker to overflow heap memory with data they supplied.
Files in MS-DOC format store the properties of characters, paragraphs,
tables,
pictures, and sections as lists of differences from the default. A Prl specifies
each difference. It consists of a Single Property Modifier (Sprm) and its
operand.
by the way : where could I upload the demo vuln files?
2. Structures
a) Prl
Sprm2 Bytes
operand variableDepending on the content of Sprm
b) TDefTableOperand
When Sprm is “0xD608”, it means the operand followed is TDefTableOperand
cb 2 Bytes The number of bytes used by the remainder of this structure,
plus one
NoC 1 Byte Number of columns, [0, 63]
rgdxaCenter[] variableArray of XAS which size is 2 bytes, for every
column, so
there is (NoC + 1) XAS
rgTc80[]variableArray of rgTc80 structure which size is 20 bytes
c) Tc80
tcgrf 2 Bytes
wWidth 2 Bytes
brcTop 4 Bytes
brcLeft 4 Bytes
brcBottom 4 Bytes
brcRight4 Bytes
3. Details
When process the Prl chain, the program read each Prl and judge the
Sprm to
determine to use which function. If the Sprm is “0xD608” which means the operand
is TDefTableOperand, it calls the ReadDef function. In WW8TabDesc::WW8TabDesc():
…
while (aSprmIter.GetSprms() 0 != (pParams =
aSprmIter.GetAktParams()))
{
sal_uInt16 nId = aSprmIter.GetAktId();
wwTableSprm eSprm = GetTableSprm(nId, pIo-GetFib().GetFIBVersion());
switch (eSprm)
{
…
case sprmTDefTable:
pNewBand-ReadDef(bOldVer, pParams);
bTabRowJustRead = true;
break;
…
}
}
In the function ReadDef, it “new” a pointer pTCs for rgTc80 array which
member
count is determined by nCols variable (NoC). But when copy data to pTCs, it use
the nFileCols variable in loop, which is calculated by cb. So if the nFileCols
is greater than nCols, it will generate a heap overflow by memcpy. In
WW8TabBandDesc::ReadDef():
/* pS point at Noc */
…
short nLen = (INT16)SVBT16ToShort( pS - 2 ); //nLen = cb
BYTE nCols = *pS;
…
const BYTE* pT = pS[1]; //point at rgdxaCenter
nLen --; //decrease the length of NoC
int i;
for(i=0; i=nCols; i++, pT+=2 ) //Read rgdxaCenter, so pT point at rgTc80
nCenter[i] = (INT16)SVBT16ToShort( pT );
nLen -= 2 * ( nCols + 1 ); //decrease the length of rgdxaCenter
short nFileCols = nLen / ( bVer67 ? 10 : 20 ); //calculate the member
count of
rgTc80, the bVer67 indicate the FIB(File Information Block) Version, we use 8
(bVer67 equal zero)
if (!pTCs nCols)
{
pTCs = new WW8_TCell[nCols]; //Here, new a pTCs use nCols, which is NoC
…
}
If (nFileCols)
{
WW8_TCell* pAktTC = pTCs;
if(bVer67)
{
…
}
else
{
WW8_TCellVer8* pTc = (WW8_TCellVer8*)pT;
for (int k = 0; k nFileCols; ++k, ++pAktTC, ++pTc )
{
…
memcpy( pAktTC-rgbrc, pTc-rgbrcVer8, 4 * sizeof( WW8_BRC ) );
//HERE, heap will be coverd
}
}
…
}
…
In my file, I construct a Prl data like this:
{08 D6, 24 37, 03, {(3+1)*2 Bytes fill}, {4 Bytes fill}, {16 Bytes
0xaa}, {4
Bytes fill}, {16 Bytes 0xaa}, {4 Bytes fill}, {16 Bytes 0xaa}, {4 Bytes fill},
{16 Bytes 0xaa}, {4 Bytes fill}, {16 Bytes 0xaa}, …}
08 D6 is Sprm; 24 37 is cb, can result nFileCols equal 0x2C1; 03 is
NoC, can
result nCols equal 0x3; the 0xaa will be filled in pTCs and cover heap. My trace
result is as follows:
1:001 bp 5D02E032 === break point at new[] for