Talos Vulnerability Report

TALOS-2017-0301

Apache OpenOffice DOC ImportOldFormatStyles Code Execution Vulnerability

October 26, 2017
CVE Number

CVE-2017-12608

Summary

An exploitable out-of-bounds write vulnerability exists in the WW8RStyle::ImportOldFormatStyles functionality of Apache OpenOffice 4.1.3. A specially crafted doc file can cause a out-of-bounds write resulting in arbitrary code execution. An attacker can send/provide 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

CWE

CWE-787 - Out-of-bounds Write

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-bounds write and ultimately to remote code execution.

Let's investigate this vulnerability. After opening Writer with a malformed doc file we see the following state:

gdb-peda$ context
[----------------------------------registers-----------------------------------]
EAX: 0xab73dffc --> 0x0 
EBX: 0xab90d3fc --> 0x15ecc8 
ECX: 0xbfffd0d8 --> 0xab73849c --> 0x106 
EDX: 0xb6c ('l\x0b')
ESI: 0xb6c ('l\x0b')
EDI: 0xbfffd0d8 --> 0xab73849c --> 0x106 
EBP: 0xbfffd138 --> 0xbfffd158 --> 0xbfffd1a8 --> 0xbfffd3e8 --> 0xbfffd6a8 (0xbfffd738)
ESP: 0xbfffd050 --> 0xb7fff000 --> 0x23f3c 
EIP: 0xab887c90 (mov    BYTE PTR [eax+0x4],0x0)
EFLAGS: 0x210286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0xab887c87:  mov    eax,edi
   0xab887c89:  mov    edx,esi
   0xab887c8b:  call   0xab886212
=> 0xab887c90:  mov    BYTE PTR [eax+0x4],0x0
   0xab887c94:  mov    al,BYTE PTR [ebp-0x10]
   0xab887c97:  mov    BYTE PTR [ebp-0xd1],al
   0xab887c9d:  inc    al
   0xab887c9f:  je     0xab887d2c
[------------------------------------stack-------------------------------------]
0000| 0xbfffd050 --> 0xb7fff000 --> 0x23f3c 
0004| 0xbfffd054 --> 0x82587d8 --> 0xab7ae000 --> 0x464c457f 
0008| 0xbfffd058 --> 0xbfffd070 --> 0x20001 
0012| 0xbfffd05c --> 0xab7b875e ("_ZN14SvxLRSpaceItemC1Et")
0016| 0xbfffd060 --> 0x0 
0020| 0xbfffd064 --> 0xffd104 
0024| 0xbfffd068 --> 0xb7837c7b (<__pthread_mutex_unlock_usercnt+11>:   add    
    edi,0x10385)
0028| 0xbfffd06c --> 0xb7fd0af8 --> 0x1bf974 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
gdb-peda$ bt
#0  0xab887c90 in ?? () from /opt/openoffice4/program/libmsword.so
#1  0xab888507 in ?? () from /opt/openoffice4/program/libmsword.so
#2  0xab88d9a3 in ?? () from /opt/openoffice4/program/libmsword.so
#3  0xab876b17 in ?? () from /opt/openoffice4/program/libmsword.so
#4  0xab8786ec in ?? () from /opt/openoffice4/program/libmsword.so
#5  0xab878a8b in ?? () from /opt/openoffice4/program/libmsword.so
#6  0xab879f9a in ?? () from /opt/openoffice4/program/libmsword.so
#7  0xac162c7b in ?? () from /opt/openoffice4/program/../program/libsw.so
#8  0xac21c730 in ?? () from /opt/openoffice4/program/../program/libsw.so
#9  0xb7408b73 in SfxObjectShell::DoLoad(SfxMedium*) () from 
     /opt/openoffice4/program/libsfx.so
#10 0xb7434353 in 
SfxBaseModel::load(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> 
const&) () from /opt/openoffice4/program/libsfx.so
#11 0xb749aaa4 in ?? () from /opt/openoffice4/program/libsfx.so
#12 0xb4e0c621 in ?? () from /opt/openoffice4/program/libfwk.so
#13 0xb4e0cf19 in ?? () from /opt/openoffice4/program/libfwk.so
#14 0xb4dbec7a in ?? () from /opt/openoffice4/program/libfwk.so
#15 0xb4dbeec4 in ?? () from /opt/openoffice4/program/libfwk.so
#16 0xb77b7715 in    

comphelper::SynchronousDispatch::dispatch(com::sun::star::uno::Reference<com::sun::star::uno ::XInterface> const&, rtl::OUString const&, rtl::OUString const&, long,

com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) ()from    
/opt/openoffice4/program/libcomphelpgcc3.so
#17 0xb7dd9bf4 in ?? () from /opt/openoffice4/program/libsofficeapp.so
#18 0xb7de2a92 in ?? () from /opt/openoffice4/program/libsofficeapp.so
#19 0xb7dc61cd in ?? () from /opt/openoffice4/program/libsofficeapp.so
#20 0xb7dc650b in ?? () from /opt/openoffice4/program/libsofficeapp.so
#21 0xb7dc65b3 in ?? () from /opt/openoffice4/program/libsofficeapp.so
#22 0xb64784dd in ?? () from /opt/openoffice4/program/libvcl.so
#23 0xb66dd92e in ?? () from /opt/openoffice4/program/libvcl.so
#24 0xb2fb7de9 in ?? () from /opt/openoffice4/program/libvclplug_gen.so
#25 0xb2fc3b52 in SalDisplay::DispatchInternalEvent() () from 
/opt/openoffice4/program/libvclplug_gen.so
#26 0xb3074fa9 in ?? () from /opt/openoffice4/program/libvclplug_gtk.so
#27 0xb3074fd8 in ?? () from /opt/openoffice4/program/libvclplug_gtk.so
#28 0xb2d82610 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
#29 0xb2d85d9b in g_main_context_dispatch () from /lib/i386-linux-gnu/libglib-2.0.so.0
#30 0xb2d86189 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
#31 0xb2d86254 in g_main_context_iteration () from /lib/i386-linux-gnu/libglib-2.0.so.0
#32 0xb3074d80 in ?? () from /opt/openoffice4/program/libvclplug_gtk.so
#33 0xb2fcafb9 in X11SalInstance::Yield(bool, bool) () from 
/opt/openoffice4/program/libvclplug_gen.so
#34 0xb6484ff2 in ?? () from /opt/openoffice4/program/libvcl.so
#35 0xb6481dbe in Application::Yield(bool) () from /opt/openoffice4/program/libvcl.so
#36 0xb6483ccb in Application::Execute() () from /opt/openoffice4/program/libvcl.so
#37 0xb7dc32a0 in ?? () from /opt/openoffice4/program/libsofficeapp.so
#38 0xb6488d8b in ?? () from /opt/openoffice4/program/libvcl.so
#39 0xb6488e79 in SVMain() () from /opt/openoffice4/program/libvcl.so
#40 0xb7de3e10 in soffice_main () from /opt/openoffice4/program/libsofficeapp.so
#41 0x08048c84 in main ()
#42 0xb789a637 in __libc_start_main (main=0xab9bf618, argc=0xab8884df, 
argv=0xab90d3fc, init=0xab963010, fini=0xbfffd1a8, rtld_fini=0xab88d9a3, 
stack_end=0xaae2c5a8) at ../csu/libc-
start.c:291

The write to `eax+0x4` causes an access violation because :

gdb-peda$ vmmap $eax+4
Start      End        Perm      Name
0xab73e000 0xab795000 r-xp      /opt/openoffice4/program/libunoxml.so

Let's investigate the vulnerable code:

sw\source\filter\ww8\ww8par2.cxx
Line 4462   void WW8RStyle::ImportOldFormatStyles()
            {
                (...)
Line 4474               sal_uInt16 cstcStd;
Line 4475               rSt >> cstcStd;
Line 4476
Line 4477               sal_uInt16 cbName;
Line 4478               rSt >> cbName;
Line 4479               sal_uInt16 nByteCount = 2;
Line 4480               sal_uInt16 stcp=0;
Line 4481               while (nByteCount < cbName)
                        {
                            (...)
Line 4518                   stcp++
                        }
                        (...)
Line 4521               sal_uInt16 nStyles=stcp;
Line 4522
Line 4523               std::vector<pxoffset> aCHPXOffsets(stcp);
Line 4524               sal_uInt16 cbChpx;
Line 4525               rSt >> cbChpx;
Line 4526               nByteCount = 2;
Line 4527               stcp=0;
Line 4528               std::vector< std::vector<sal_uInt8> > aConvertedChpx;
Line 4529               while (nByteCount < cbChpx)
Line 4530               {
Line 4531                   sal_uInt8 cb;
Line 4532                   rSt >> cb;
Line 4533                   nByteCount++;
Line 4534
Line 4535                   aCHPXOffsets[stcp].mnSize = 0;      
                        (...)
Line 4553                   stcp++;
                        }

At line 4480 we see that stcp is initialized with a 0 value. Next, if read directly from the file, cbName value won't be bigger than 2, stcp won't be increased and stay with initialized value (0). Based on stcp at line 4523, the aCHPXOffsets vector is allocated. The cbChpx variable value is read directly from the file at line 4525 and then used as a constrain in a while loop. The while loop will be executed as many times as indicated by cbChpx, there is no check to see whether its value is greater than stcp, which leads to an out-of-bounds write at line 4535. That situation causes memory corruption and can lead to arbitrary code execution by the attacker.

Values for significant variables are coming from offset 0xFF:
Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

000000F0                                                 09                  .
00000100   00 00 00 00 88 88 00 05                            ....ˆˆ..    

cstcStd = WORD 09 00
cbName  = WORD 00 00
cbChpx  = WORD 88 88

Crash Information

gdb-peda$ context
[----------------------------------registers-----------------------------------]
EAX: 0xab73dffc --> 0x0 
EBX: 0xab90d3fc --> 0x15ecc8 
ECX: 0xbfffd0d8 --> 0xab73849c --> 0x106 
EDX: 0xb6c ('l\x0b')
ESI: 0xb6c ('l\x0b')
EDI: 0xbfffd0d8 --> 0xab73849c --> 0x106 
EBP: 0xbfffd138 --> 0xbfffd158 --> 0xbfffd1a8 --> 0xbfffd3e8 --> 0xbfffd6a8 (0xbfffd738)
ESP: 0xbfffd050 --> 0xb7fff000 --> 0x23f3c 
EIP: 0xab887c90 (mov    BYTE PTR [eax+0x4],0x0)
EFLAGS: 0x210286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0xab887c87:  mov    eax,edi
   0xab887c89:  mov    edx,esi
   0xab887c8b:  call   0xab886212
=> 0xab887c90:  mov    BYTE PTR [eax+0x4],0x0
   0xab887c94:  mov    al,BYTE PTR [ebp-0x10]
   0xab887c97:  mov    BYTE PTR [ebp-0xd1],al
   0xab887c9d:  inc    al
   0xab887c9f:  je     0xab887d2c
[------------------------------------stack-------------------------------------]
0000| 0xbfffd050 --> 0xb7fff000 --> 0x23f3c 
0004| 0xbfffd054 --> 0x82587d8 --> 0xab7ae000 --> 0x464c457f 
0008| 0xbfffd058 --> 0xbfffd070 --> 0x20001 
0012| 0xbfffd05c --> 0xab7b875e ("_ZN14SvxLRSpaceItemC1Et")
0016| 0xbfffd060 --> 0x0 
0020| 0xbfffd064 --> 0xffd104 
0024| 0xbfffd068 --> 0xb7837c7b (<__pthread_mutex_unlock_usercnt+11>:   add    edi,0x10385)
0028| 0xbfffd06c --> 0xb7fd0af8 --> 0x1bf974 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
gdb-peda$ exploitable -m
Warning: machine string printing is deprecated and may be removed in a future release.
EXCEPTION_FAULTING_ADDRESS:0x000000ab73e000
EXCEPTION_CODE:0xb
FAULTING_INSTRUCTION:mov    BYTE PTR [eax+0x4],0x0
MAJOR_HASH:267590b160c1d882cadfa5981b70941e
MINOR_HASH:79312db15af9cfd3ad94d7a16227d7d3
STACK_DEPTH:42
STACK_FRAME:/opt/openoffice4/program/libmsword.so+0x0
STACK_FRAME:/opt/openoffice4/program/libmsword.so+0x0
STACK_FRAME:/opt/openoffice4/program/libmsword.so+0x0
STACK_FRAME:/opt/openoffice4/program/libmsword.so+0x0
STACK_FRAME:/opt/openoffice4/program/libmsword.so+0x0
STACK_FRAME:/opt/openoffice4/program/libmsword.so+0x0
STACK_FRAME:/opt/openoffice4/program/libmsword.so+0x0
STACK_FRAME:/opt/openoffice4/program/libsw.so+0x0
STACK_FRAME:/opt/openoffice4/program/libsw.so+0x0
STACK_FRAME:/opt/openoffice4/program/libsfx.so!SfxObjectShell::DoLoad(SfxMedium*)+
    0x0
   STACK_FRAME:/opt/openoffice4/program/libsfx.so!SfxBaseModel::load(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&)+0x0
STACK_FRAME:/opt/openoffice4/program/libsfx.so+0x0
STACK_FRAME:/opt/openoffice4/program/libfwk.so+0x0
STACK_FRAME:/opt/openoffice4/program/libfwk.so+0x0
STACK_FRAME:/opt/openoffice4/program/libfwk.so+0x0
STACK_FRAME:/opt/openoffice4/program/libfwk.so+0x0 
    STACK_FRAME:/opt/openoffice4/program/libcomphelpgcc3.so!comphelper::Synchronous
    Dispatch::dispatch(com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const&,     
    rtl::OUString  
    const&, rtl::OUString const&, long, 
    com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&)+0x0

      STACK_FRAME:/opt/openoffice4/program/libcomphelpgcc3.so!comphelper::SynchronousDispatch::dispatch
STACK_FRAME:/opt/openoffice4/program/libsofficeapp.so+0x0
STACK_FRAME:/opt/openoffice4/program/libsofficeapp.so+0x0
STACK_FRAME:/opt/openoffice4/program/libsofficeapp.so+0x0
STACK_FRAME:/opt/openoffice4/program/libsofficeapp.so+0x0
STACK_FRAME:/opt/openoffice4/program/libsofficeapp.so+0x0
STACK_FRAME:/opt/openoffice4/program/libvcl.so+0x0
STACK_FRAME:/opt/openoffice4/program/libvcl.so+0x0
STACK_FRAME:/opt/openoffice4/program/libvclplug_gen.so+0x0
STACK_FRAME:/opt/openoffice4/program/libvclplug_gen.so!SalDisplay::DispatchInternalEv
    ent()+0x0
STACK_FRAME:/opt/openoffice4/program/libvclplug_gtk.so+0x0
STACK_FRAME:/opt/openoffice4/program/libvclplug_gtk.so+0x0
STACK_FRAME:/lib/i386-linux-gnu/libglib-2.0.so.0.4800.2+0x0
STACK_FRAME:/lib/i386-linux-gnu/libglib-2.0.so.0.4800.2!g_main_context_dispatch+0x0
STACK_FRAME:/lib/i386-linux-gnu/libglib-2.0.so.0.4800.2+0x0
STACK_FRAME:/lib/i386-linux-gnu/libglib-2.0.so.0.4800.2!g_main_context_iteration+0x0
STACK_FRAME:/opt/openoffice4/program/libvclplug_gtk.so+0x0
STACK_FRAME:/opt/openoffice4/program/libvclplug_gen.so!X11SalInstance::Yield(bool, 
    bool)+0x0
STACK_FRAME:/opt/openoffice4/program/libvcl.so+0x0
STACK_FRAME:/opt/openoffice4/program/libvcl.so!Application::Yield(bool)+0x0
STACK_FRAME:/opt/openoffice4/program/libvcl.so!Application::Execute()+0x0
STACK_FRAME:/opt/openoffice4/program/libsofficeapp.so+0x0
STACK_FRAME:/opt/openoffice4/program/libvcl.so+0x0
STACK_FRAME:/opt/openoffice4/program/libvcl.so!SVMain()+0x0
STACK_FRAME:/opt/openoffice4/program/libsofficeapp.so!soffice_main+0x0
STACK_FRAME:/opt/openoffice4/program/soffice.bin!main+0x0
INSTRUCTION_ADDRESS:0x000000ab887c90
INVOKING_STACK_FRAME:0
DESCRIPTION:Access violation on destination operand
SHORT_DESCRIPTION:DestAv (9/29)
OTHER_RULES:AccessViolation (28/29)
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.
Description: Access violation on destination operand
Short description: DestAv (9/29)
Hash: 267590b160c1d882cadfa5981b70941e.79312db15af9cfd3ad94d7a16227d7d3
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)

Timeline

2017-04-05 - Vendor Disclosure
2017-10-26 - Public Release

Credit

Discovered by Marcin 'Icewall' Noga of Cisco Talos.