Apache OpenOffice DOC WW8Fonts Constructor Code Execution Vulnerability(CVE-2017-9806)

2017-11-06T00:00:00
ID SSV:96797
Type seebug
Reporter Root
Modified 2017-11-06T00:00:00

Description

Summary

An exploitable out of bound write vulnerability exists in the WW8Fonts::WW8Fonts functionality of Apache OpenOffice 4.1.3. A specially crafted doc file can cause an out of bound write potentially resulting in arbitrary code execution. An attacker can send/provide a malicious doc file to trigger this vulnerability.

Tested Versions

Apache OpenOffice 4.1.3

Product URLs

http://www.openoffice.org/

CVSSv3 Score

8.3 - CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H

Details

This vulnerability is present in Apache OpenOffice (formerly OpenOffice.org), a free open source office suite. A specially crafted DOC file can lead to an out of bound write and ultimately to remote code execution.

Let's investigate this vulnerability. After OpenOffice Writer opens the malformed doc file we see the following state: ``` gdb-peda$ context [----------------------------------registers-----------------------------------] EAX: 0xa9788010 --> 0x30003 EBX: 0xa9c16000 --> 0x2a1b30 ECX: 0x28 ('(') EDX: 0x3 ESI: 0xffff EDI: 0xa96a800c --> 0xffff0000 EBP: 0xbfffd578 --> 0xbfffd778 --> 0xbfffd9a8 --> 0xbfffda48 --> 0xbfffdab8 --> 0xbfffdb78 --> 0xbfffdbf8 --> 0xbfffddd8 --> 0xbfffdea8 --> 0xbfffdf68 --> 0xbfffe018 -->
0xbfffe058 --> 0xbfffe0e8 --> 0xbfffe138 --> 0xbfffe1f8 --> 0xbfffe378 --> 0xbfffe3d8 --> 0xbfffe6c8 --> 0xbfffe718 --> 0xbfffe738 --> 0xbfffe758 --> 0xbfffe778 --> 0xbfffe818 --> 0xbfffe848 --> 0xbfffe898 --> 0xbfffe8c8 --> 0xbfffe8e8 --> 0x823f4b0 --> 0x2 ESP: 0xbfffd500 --> 0x10 EIP: 0xa9b5cdf7 (<WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1649>: mov WORD PTR [eax],dx) EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0xa9b5cdef <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1641>: add esp,0x10 0xa9b5cdf2 <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1644>: mov edx,eax 0xa9b5cdf4 <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1646>: mov eax,DWORD PTR [ebp-0x2c] => 0xa9b5cdf7 <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1649>: mov WORD PTR [eax],dx 0xa9b5cdfa <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1652>: add DWORD PTR [ebp-0x2c],0x2 0xa9b5cdfe <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1656>: add BYTE PTR [ebp-0x53],0x2 0xa9b5ce02 <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1660>: jmp 0xa9b5cddb <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1621> 0xa9b5ce04 <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1662>: mov eax,DWORD PTR [ebp-0x30] [------------------------------------stack-------------------------------------] 0000| 0xbfffd500 --> 0x10 0004| 0xbfffd504 --> 0xa9c22110 --> 0xa96a800c --> 0xffff0000 0008| 0xbfffd508 --> 0xa96a8008 --> 0xffff 0012| 0xbfffd50c --> 0xa9768000 --> 0x0 0016| 0xbfffd510 --> 0xffffffff 0020| 0xbfffd514 --> 0xa9cea310 --> 0x8 0024| 0xbfffd518 --> 0xa9c21f58 --> 0xb4b526a0 --> 0xb4b15a6a (<SotStorageStream::GetData(void*,
unsigned long)>: push ebp) 0028| 0xbfffd51c --> 0xa9c22110 --> 0xa96a800c --> 0xffff0000 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV gdb-peda$ bt 1

0 0xa9b5cdf7 in WW8Fonts::WW8Fonts (this=0xa9c22110, rSt=..., rFib=...) at /storage/aoo-

4.1.3/main/sw/source/filter/ww8/ww8scan.cxx:6571 (More stack frames follow...) gdb-peda$ info line $pc Line 6571 of "/storage/aoo-4.1.3/main/sw/source/filter/ww8/ww8scan.cxx" starts at address 0xa9b5cde4 <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1630> and ends at 0xa9b5cdfa <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1652>. gdb-peda$ list $pc 0xa9b5cdf7 is in WW8Fonts::WW8Fonts(SvStream&, WW8Fib&) (/storage/aoo- 4.1.3/main/sw/source/filter/ww8/ww8scan.cxx:6571). 6566 sal_uInt8 nLength = sizeof( pVer8->szFfn ) / sizeof( SVBT16 ); 6567 nLength = std::min( nLength, sal_uInt8( pVer8->cbFfnM1+1 ) ); 6568 for( sal_uInt16 pTmp = pVer8->szFfn; 6569 nLen < nLength; ++pTmp, nLen+=2 ) 6570 { 6571 pTmp = SVBT16ToShort( (SVBT16)pTmp ); 6572 } 6573 } 6574 #endif // defined __WW8_NEEDS_COPY 6575 ```

So we see that write access violation appeared in the WW8Fonts::WW8Fonts constructor. The definition of this function is located in file /storage/aoo-4.1.3/main/sw/source/filter/ww8/ww8scan.cxx:6571. Checking the pTmp pointer value we see: gdb-peda$ p pTmp $25 = (sal_uInt16 *) 0xa9788010 gdb-peda$ vmmap 0xa9788010 Start End Perm Name 0xa9788000 0xa9823000 r-xp /storage/aoo- 4.1.3/main/instsetoo_native/unxlngi6.pro/Apache_OpenOffice/installed/install/en- US/openoffice4/program/libunoxml.so

When an attempt to write to the address pointed to by the pTmp pointer, we encounter an access violation will because it points to mapped libunoxml.so library. Looking at source code we see (the lines here have different numbers than the lines in the original source code): 1 WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib ) 2 : pFontA(0), nMax(0) 3 { 4 // sal_uInt16 nMax; 5 (...) 6 rSt.Seek( rFib.fcSttbfffn ); 7 8 sal_Int32 nFFn = rFib.lcbSttbfffn - 2; 9 10 // allocate Font Array 11 sal_uInt8* pA = new sal_uInt8[ nFFn ]; 12 memset(pA, 0, nFFn); 13 WW8_FFN* p = (WW8_FFN*)pA; 14 15 ww::WordVersion eVersion = rFib.GetFIBVersion(); 16 17 if( eVersion &gt;= ww::eWW8 ) 18 { 19 // bVer8: read the count of strings in nMax 20 rSt &gt;&gt; nMax; 21 } 22 23 (...) 24 WW8_FFN_Ver8* pVer8 = (WW8_FFN_Ver8*)pA; 25 sal_uInt8 c2; 26 for(sal_uInt16 i=0; i&lt;nMax; ++i, ++p) 27 { 28 29 (...) 30 sal_uInt8 nLen = 0x28; 31 sal_uInt8 nLength = sizeof( pVer8-&gt;szFfn ) / sizeof( SVBT16 ); 32 nLength = std::min( nLength, sal_uInt8( pVer8-&gt;cbFfnM1+1 ) ); 33 for( sal_uInt16* pTmp = pVer8-&gt;szFfn; 34 nLen &lt; nLength; ++pTmp, nLen+=2 ) 35 { 36 *pTmp = SVBT16ToShort( *(SVBT16*)pTmp ); 37 } 38 (...) 39 // Zeiger auf Ursprungsarray einen Font nach hinten setzen 40 pVer8 = (WW8_FFN_Ver8*)( ((sal_uInt8*)pVer8) + pVer8-&gt;cbFfnM1 + 1 ); 41 }

The loop at line 26 is based on nMax value. Each time at the end of this loop (at line 40) pVer8 pointer is set to new location based on the cbFfnM1 field value. pVer8 is a pointer to a dynamically allocated buffer, which is allocated at line 11, with a size equal to rFib.lcbSttbfffn - 2. As we can see there is no check to see whether after first iteration pVer8 is pointing outside buffer range or not. That situation leads to out of bound read/writes in certain places and finally can lead to remote code execution.

A dump of some important fields: gdb-peda$ p rFib.lcbSttbfffn $30 = 0xb6 gdb-peda$ p rFib.fcSttbfffn $31 = 0x501 gdb-peda$ p nMax $32 = 0xffff gdb-peda$ p eVersion $33 = ww::eWW8 gdb-peda$ p *(WW8_FFN_Ver8*)pA $38 = { &lt;WW8_FFN_BASE&gt; = { cbFfnM1 = 0x0, prg = 0x0, fTrueType = 0x0, ff = 0x0, wWeight = 0xffff, chs = 0x0, ibszAlt = 0x0

Crash Information

``` [----------------------------------registers-----------------------------------] EAX: 0xa9788010 --> 0x30003 EBX: 0xa9c16000 --> 0x2a1b30 ECX: 0x28 ('(') EDX: 0x3 ESI: 0xffff EDI: 0xa96a800c --> 0xffff0000 EBP: 0xbfffd578 --> 0xbfffd778 --> 0xbfffd9a8 --> 0xbfffda48 --> 0xbfffdab8 --> 0xbfffdb78 --> 0xbfffdbf8 --> 0xbfffddd8 --> 0xbfffdea8 --> 0xbfffdf68 --> 0xbfffe018 --> 0xbfffe058 --> 0xbfffe0e8 --> 0xbfffe138 --> 0xbfffe1f8 --> 0xbfffe378 --> 0xbfffe3d8 --> 0xbfffe6c8 --> 0xbfffe718 --> 0xbfffe738 --> 0xbfffe758 --> 0xbfffe778 --> 0xbfffe818 --> 0xbfffe848 --> 0xbfffe898 --> 0xbfffe8c8 --> 0xbfffe8e8 --> 0x823f4b0 --> 0x2 ESP: 0xbfffd500 --> 0x10 EIP: 0xa9b5cdf7 (<WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1649>: mov WORD PTR [eax],dx) EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0xa9b5cdef <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1641>: add esp,0x10 0xa9b5cdf2 <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1644>: mov edx,eax 0xa9b5cdf4 <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1646>: mov eax,DWORD PTR [ebp-0x2c] => 0xa9b5cdf7 <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1649>: mov WORD PTR [eax],dx 0xa9b5cdfa <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1652>: add DWORD PTR [ebp-0x2c],0x2 0xa9b5cdfe <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1656>: add BYTE PTR [ebp-0x53],0x2 0xa9b5ce02 <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1660>: jmp 0xa9b5cddb <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1621> 0xa9b5ce04 <WW8Fonts::WW8Fonts(SvStream&, WW8Fib&)+1662>: mov eax,DWORD PTR [ebp-0x30] [------------------------------------stack-------------------------------------] 0000| 0xbfffd500 --> 0x10 0004| 0xbfffd504 --> 0xa9c22110 --> 0xa96a800c --> 0xffff0000 0008| 0xbfffd508 --> 0xa96a8008 --> 0xffff 0012| 0xbfffd50c --> 0xa9768000 --> 0x0 0016| 0xbfffd510 --> 0xffffffff 0020| 0xbfffd514 --> 0xa9cea310 --> 0x8 0024| 0xbfffd518 --> 0xa9c21f58 --> 0xb4b526a0 --> 0xb4b15a6a (<SotStorageStream::GetData(void*, unsigned long)>: push ebp) 0028| 0xbfffd51c --> 0xa9c22110 --> 0xa96a800c --> 0xffff0000 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV gdb-peda$ exploitable Description: Access violation on destination operand Short description: DestAv (9/29) Hash: 35ea22a685538a48f0dc54bae45e3da2.afc0f1decc0f689aa835fa8a3e7bfbc3 Exploitability Classification: EXPLOITABLE Explanation: The target crashed on an access violation at an address matching the destination operand of the instruction. This likely indicates a write access violation, which means the attacker may control the write address and/or value. Other tags: AccessViolation (28/29) gdb-peda$ bt

0 0xa9b5cdf7 in WW8Fonts::WW8Fonts (this=0xa9c22110, rSt=..., rFib=...) at /storage/aoo-

4.1.3/main/sw/source/filter/ww8/ww8scan.cxx:6571

1 0xa9ae4b57 in SwWW8ImplReader::CoreLoad (this=0xabc86c0c, pGloss=0x0, rPos=...) at /storage/aoo-

4.1.3/main/sw/source/filter/ww8/ww8par.cxx:4390

2 0xa9ae8606 in SwWW8ImplReader::LoadThroughDecryption (this=0xabc86c0c, rPaM=..., pGloss=0x0) at

/storage/aoo-4.1.3/main/sw/source/filter/ww8/ww8par.cxx:5163

3 0xa9ae94dd in SwWW8ImplReader::LoadDoc (this=0xabc86c0c, rPaM=..., pGloss=0x0) at /storage/aoo-

4.1.3/main/sw/source/filter/ww8/ww8par.cxx:5430

4 0xa9ae976a in WW8Reader::Read (this=0xa9cdff84, rDoc=..., rBaseURL=..., rPam=...) at /storage/aoo-

4.1.3/main/sw/source/filter/ww8/ww8par.cxx:5499

5 0xaaa4d71e in SwReader::Read (this=0xa9c1e2b4, rOptions=...) at /storage/aoo-

4.1.3/main/sw/source/filter/basflt/shellio.cxx:189

6 0xaab67bc1 in SwDocShell::ConvertFrom (this=0xacafe034, rMedium=...) at /storage/aoo-

4.1.3/main/sw/source/ui/app/docsh.cxx:258

7 0xb7243e0f in SfxObjectShell::DoLoad (this=0xacafe034, pMed=0xa9cf4e90) at /storage/aoo-

4.1.3/main/sfx2/source/doc/objstor.cxx:753

8 0xb728bcfc in SfxBaseModel::load (this=0xabb98ad4, seqArguments=...) at /storage/aoo-

4.1.3/main/sfx2/source/doc/sfxbasemodel.cxx:1878

9 0xb7342be9 in SfxFrameLoader_Impl::load (this=0xabb7758c, rArgs=..., _rTargetFrame=...) at

/storage/aoo-4.1.3/main/sfx2/source/view/frmload.cxx:607

10 0xae5786d8 in framework::LoadEnv::impl_loadContent (this=0xaf31e964) at /storage/aoo-

4.1.3/main/framework/source/loadenv/loadenv.cxx:1205

11 0xae574e16 in framework::LoadEnv::startLoading (this=0xaf31e964) at /storage/aoo-

4.1.3/main/framework/source/loadenv/loadenv.cxx:433

12 0xae505c67 in framework::LoadDispatcher::impl_dispatch (this=0xaf31e918, rURL=..., lArguments=...,

xListener=...) at /storage/aoo-4.1.3/main/framework/source/ dispatch/loaddispatcher.cxx:165

13 0xae5059a8 in framework::LoadDispatcher::dispatchWithReturnValue (this=0xaf31e918, rURL=...,

lArguments=...) at /storage/aoo-4.1.3/main/framework/source/dispatch/ loaddispatcher.cxx:102

14 0xb782d5f4 in comphelper::SynchronousDispatch::dispatch (xStartPoint=..., sURL=..., sTarget=...,

nFlags=0x0, lArguments=...) at /storage/aoo-4.1.3/main/comphelper/ source/misc/synchronousdispatch.cxx:81

15 0xb7d753f4 in desktop::DispatchWatcher::executeDispatchRequests (this=0xad4129a8,

aDispatchRequestsList=..., bNoTerminate=0x0) at /storage/aoo-4.1.3/main/desktop/ source/app/dispatchwatcher.cxx:333

16 0xb7d83108 in desktop::OfficeIPCThread::ExecuteCmdLineRequests (aRequest=...) at /storage/aoo-

4.1.3/main/desktop/source/app/officeipcthread.cxx:993

17 0xb7d562b4 in desktop::Desktop::OpenClients () at /storage/aoo-

4.1.3/main/desktop/source/app/app.cxx:3204

18 0xb7d51dfd in desktop::Desktop::OpenClients_Impl (this=0xbfffed88) at /storage/aoo-

4.1.3/main/desktop/source/app/app.cxx:2536

19 0xb7d51db1 in desktop::Desktop::LinkStubOpenClients_Impl (pThis=0xbfffed88, pCaller=0x0) at

/storage/aoo-4.1.3/main/desktop/source/app/app.cxx:2532

20 0xb5b07fc4 in Link::Call (this=0xae90c2ec, pCaller=0x0) at /storage/aoo-

4.1.3/main/solver/413/unxlngi6.pro/inc/tools/link.hxx:135

21 0xb5efa9a1 in ImplHandleUserEvent (pSVEvent=0xacafa0f8) at /storage/aoo-

4.1.3/main/vcl/source/window/winproc.cxx:1996

22 0xb5efbc22 in ImplWindowFrameProc (pWindow=0xae90e1d4, nEvent=0x16, pEvent=0xacafa0f8) at

/storage/aoo-4.1.3/main/vcl/source/window/winproc.cxx:2568

23 0xb20e0fd5 in SalFrame::CallCallback (this=0xaf321a60, nEvent=0x16, pEvent=0xacafa0f8) at

/storage/aoo-4.1.3/main/vcl/inc/salframe.hxx:281

24 0xb20f4c25 in SalDisplay::DispatchInternalEvent (this=0xb22b4008) at /storage/aoo-

4.1.3/main/vcl/unx/generic/app/saldisp.cxx:2231

25 0xb22582f4 in GtkXLib::userEventFn (data=0xb24c9308) at /storage/aoo-

4.1.3/main/vcl/unx/gtk/app/gtkdata.cxx:817

26 0xb225820e in call_userEventFn (data=0xb24c9308) at /storage/aoo-

4.1.3/main/vcl/unx/gtk/app/gtkdata.cxx:790

27 0xb1799610 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0

28 0xb179cd9b in g_main_context_dispatch () from /lib/i386-linux-gnu/libglib-2.0.so.0

29 0xb179d189 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0

30 0xb179d254 in g_main_context_iteration () from /lib/i386-linux-gnu/libglib-2.0.so.0

31 0xb22584e2 in GtkXLib::Yield (this=0xb24c9308, bWait=0x1, bHandleAllCurrentEvents=0x0) at

/storage/aoo-4.1.3/main/vcl/unx/gtk/app/gtkdata.cxx:869

32 0xb2103187 in X11SalInstance::Yield (this=0xb2cec290, bWait=0x1, bHandleAllCurrentEvents=0x0) at

/storage/aoo-4.1.3/main/vcl/unx/generic/app/salinst.cxx:278

33 0xb5b19e67 in ImplYield (i_bWait=0x1, i_bAllEvents=0x0) at /storage/aoo-

4.1.3/main/vcl/source/app/svapp.cxx:476

34 0xb5b15a93 in Application::Yield (i_bAllEvents=0x0) at /storage/aoo-

4.1.3/main/vcl/source/app/svapp.cxx:510

35 0xb5b15a2c in Application::Execute () at /storage/aoo-4.1.3/main/vcl/source/app/svapp.cxx:453

36 0xb7d5051a in desktop::Desktop::Main (this=0xbfffed88) at /storage/aoo-

4.1.3/main/desktop/source/app/app.cxx:2232

37 0xb5b20296 in ImplSVMain () at /storage/aoo-4.1.3/main/vcl/source/app/svmain.cxx:196

38 0xb5b20423 in SVMain () at /storage/aoo-4.1.3/main/vcl/source/app/svmain.cxx:237

39 0xb7d8543a in soffice_main () at /storage/aoo-4.1.3/main/desktop/source/app/sofficemain.cxx:45

40 0x08048df5 in sal_main () at main.c:31

41 0x08048ddb in main (argc=0x6, argv=0xbfffeea4) at main.c:30

42 0xb798a637 in __libc_start_main (main=0x8048dbb <main>, argc=0x6, argv=0xbfffeea4, init=0x80493a0

<__libc_csu_init>, fini=0x8049400 <__libc_csu_fini>, rtld_fini=0xb7fea780 <_dl_fini>, stack_end=0xbfffee9c) at ../csu/libc-start.c:291

43 0x08048ce1 in _start ()

```

Timeline

  • 2017-03-16 - Vendor Disclosure
  • 2017-10-26 - Public Release