CVE-2017-12607
An exploitable out of bound write vulnerability exists in the PPTStyleSheet::PPTStyleSheet functionality of Apache OpenOffice. A specially crafted PPT file can cause an out of bound write resulting in arbitrary code execution. An attacker can send/provide a malicious PPT file to trigger this vulnerability.
Apache OpenOffice 4.1.3 x64 Apache OpenOffice 4.1.3 x86
8.3 - CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H
This vulnerability is present in the Apache OpenOffice (formerly OpenOffice.org) a free open source office suite.
A specially crafted PPT file can lead to an out of bound write and ultimately to remote code execution.
Let's investigate this vulnerability. After opening Impress with the malformed PPT file we see following state:
gdb-peda$ context
[----------------------------------registers-----------------------------------]
RAX: 0xb70 ('p\x0b')
RBX: 0x28a
RCX: 0x7fffc2ef0fdc --> 0x800000000010000
RDX: 0x7fffc2a4fd88 --> 0x64000020220000 ('')
RSI: 0x7fffc2a45170 --> 0x0
RDI: 0x7fffc2ef0ff0 --> 0x800000000010000
RBP: 0x28a
RSP: 0x7fffffffa7b0 --> 0x1
RIP: 0x7fffc2571dfc (mov WORD PTR [rdi+0x10],ax)
R8 : 0x5140 ('@Q')
R9 : 0x0
R10: 0x7fffc2a4f9c8 --> 0x7ffff09eca80 --> 0x7ffff07bfa64 (<_ZN16SotStorageStream7GetDataEPvm>: push rbp)
R11: 0xc8
R12: 0x0
R13: 0x28a
R14: 0x7fffc2a3f148 --> 0x7fffc2a77848 --> 0x7fffc2a413e8 --> 0x7b ('{')
R15: 0x7fffc2a4f9c8 --> 0x7ffff09eca80 --> 0x7ffff07bfa64 (<_ZN16SotStorageStream7GetDataEPvm>: push rbp)
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x7fffc2571df0: mov rax,QWORD PTR [rcx+0x8]
0x7fffc2571df4: mov QWORD PTR [rdi+0x8],rax
0x7fffc2571df8: movzx eax,WORD PTR [rcx+0x10]
=> 0x7fffc2571dfc: mov WORD PTR [rdi+0x10],ax
0x7fffc2571e00: mov rax,QWORD PTR [rsp+0x28]
0x7fffc2571e05: movzx r12d,r9b
0x7fffc2571e09: mov r8d,ebx
0x7fffc2571e0c: mov r9d,r12d
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa7b0 --> 0x1
0008| 0x7fffffffa7b8 --> 0x966f08 --> 0x7ffff7ffe480 --> 0x6db1b0 --> 0x7ffff7ffe1c8 --> 0x0
0016| 0x7fffffffa7c0 --> 0x7fffffffb160 --> 0x1
0024| 0x7fffffffa7c8 --> 0x7ffff7ed8808 --> 0x7fffc27ab310 --> 0x7fffc25730b0
(<_ZNK19SdrPowerPointImport9ImportOLEElRK7GraphicRK9RectangleS5_il>: push r15)
0032| 0x7fffffffa7d0 --> 0x7fffffffb0b0 --> 0xfc9000f0000b10f
0040| 0x7fffffffa7d8 --> 0x7fffc2a45170 --> 0x0
0048| 0x7fffffffa7e0 --> 0x7ffff7ed9000 --> 0x10000000b
0056| 0x7fffffffa7e8 --> 0x3e8a00000000
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
gdb-peda$ bt
#0 0x00007fffc2571dfc in ?? () from /opt/openoffice4/program/libmsfilter.so
#1 0x00007fffc2577c4d in SdrPowerPointImport::SdrPowerPointImport(PowerPointImportParam&, String const&) () from /opt/
openoffice4/program/
libmsfilter.so
#2 0x00007fffc27c702e in ?? () from /opt/openoffice4/program/libsdfilt.so
#3 0x00007fffc27c74e9 in ?? () from /opt/openoffice4/program/libsdfilt.so
#4 0x00007fffc27ceafb in ImportPPT () from /opt/openoffice4/program/libsdfilt.so
#5 0x00007fffc326c4c8 in ?? () from /opt/openoffice4/program/../program/libsd.so
#6 0x00007fffc318884d in sd::DrawDocShell::ConvertFrom(SfxMedium&) () from /opt/openoffice4/program/../program/libsd.so
#7 0x00007ffff4ccc02f in SfxObjectShell::DoLoad(SfxMedium*) () from /opt/openoffice4/program/libsfx.so
#8 0x00007ffff4cf2202 in SfxBaseModel::load(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&)
() from /opt/
openoffice4/program/libsfx.so
#9 0x00007ffff4d47093 in ?? () from /opt/openoffice4/program/libsfx.so
#10 0x00007fffee2a6750 in ?? () from /opt/openoffice4/program/libfwk.so
#11 0x00007fffee2a707e in ?? () from /opt/openoffice4/program/libfwk.so
#12 0x00007fffee2619a0 in ?? () from /opt/openoffice4/program/libfwk.so
#13 0x00007fffee261c0e in ?? () from /opt/openoffice4/program/libfwk.so
#14 0x00007ffff5d38868 in
comphelper::SynchronousDispatch::dispatch(com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const&,
rtl::OUString const&, rtl::OUString const&, int, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&)
() from /opt/
openoffice4/program/libcomphelpgcc3.so
#15 0x00007ffff77971a3 in ?? () from /opt/openoffice4/program/libsofficeapp.so
#16 0x00007ffff77a33a6 in ?? () from /opt/openoffice4/program/libsofficeapp.so
#17 0x00007ffff77831f0 in ?? () from /opt/openoffice4/program/libsofficeapp.so
#18 0x00007ffff7784d0a in ?? () from /opt/openoffice4/program/libsofficeapp.so
#19 0x00007ffff2ec6ab3 in ?? () from /opt/openoffice4/program/libvcl.so
#20 0x00007fffea8f9b27 in SalDisplay::DispatchInternalEvent() () from /opt/openoffice4/program/libvclplug_gen.so
#21 0x00007fffeabb63b4 in ?? () from /opt/openoffice4/program/libvclplug_gtk.so
#22 0x00007fffe9aed175 in g_main_dispatch (context=0x65ea80) at gmain.c:3154
#23 g_main_context_dispatch (context=context@entry=0x65ea80) at gmain.c:3769
#24 0x00007fffe9aed4e8 in g_main_context_iterate (context=context@entry=0x65ea80, block=block@entry=0x0,
dispatch=dispatch@entry=0x1,
self=<optimized out>) at gmain.c:3840
#25 0x00007fffe9aed58c in g_main_context_iteration (context=0x65ea80, may_block=0x0) at gmain.c:3901
#26 0x00007fffeabb61f0 in ?? () from /opt/openoffice4/program/libvclplug_gtk.so
#27 0x00007ffff2caa45f in ?? () from /opt/openoffice4/program/libvcl.so
#28 0x00007ffff2ca9667 in Application::Execute() () from /opt/openoffice4/program/libvcl.so
#29 0x00007ffff777e93e in ?? () from /opt/openoffice4/program/libsofficeapp.so
#30 0x00007ffff2cad7eb in ?? () from /opt/openoffice4/program/libvcl.so
#31 0x00007ffff2cad8b6 in SVMain() () from /opt/openoffice4/program/libvcl.so
#32 0x00007ffff77a5f8c in soffice_main () from /opt/openoffice4/program/libsofficeapp.so
#33 0x0000000000400f7b in main ()
#34 0x00007ffff6646f45 in __libc_start_main (main=0x400f70 <main>, argc=0x6, argv=0x7fffffffdf18, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffdf08)
at libc-start.c:287
#35 0x0000000000400eb9 in _start ()
let's check the write address `rdi+0x10`:
gdb-peda$ vmmap $rdi+0x10
Start End Perm Name
0x00007fffc2ef1000 0x00007fffc3568000 r-xp /opt/openoffice4/program/libsd.so
As we can see an attempt to write is made in an address range of the mapped file libsd.so, which results in an access violation because of the pages that contain this mapped file are set to read and execute permissions, but not write. To understand why this vulnerability appears, we will look at the vulnerable function in the source code:
filter\source\msfilter\svdfppt.cxx : 4343
PPTStyleSheet::PPTStyleSheet( const DffRecordHeader& rSlideHd, SvStream& rIn, SdrPowerPointImport& rManager,
const PPTTextCharacterStyleAtomInterpreter& /
*rTxCFStyle*/, const PPTTextParagraphStyleAtomInterpreter& rTxPFStyle,
const PPTTextSpecInfo& rTextSpecInfo ) :
Line 4373 DffRecordHeader* pEnvHeader = rManager.aDocRecManager.GetRecordHeader( PPT_PST_Environment );
Line 4374 if ( pEnvHeader )
Line 4375 {
Line 4376 pEnvHeader->SeekToContent( rIn );
Line 4377 DffRecordHeader aTxMasterStyleHd;
Line 4378 while ( rIn.Tell() < pEnvHeader->GetRecEndFilePos() )
Line 4379 {
Line 4380 rIn >> aTxMasterStyleHd;
Line 4381 if ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom )
Line 4382 {
Line 4383 sal_uInt16 nLevelAnz;
Line 4384 rIn >> nLevelAnz;
Line 4385
Line 4386 sal_uInt16 nLev = 0;
Line 4387 sal_Bool bFirst = sal_True;
Line 4388 bFoundTxMasterStyleAtom04 = sal_True;
Line 4389 while ( rIn.GetError() == 0 && rIn.Tell() < aTxMasterStyleHd.GetRecEndFilePos() &&
nLev < nLevelAnz )
Line 4390 {
Line 4391 if ( nLev )
Line 4392 {
Line 4393 mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maParaLevel[ nLev ] =
mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maParaLevel[ nLev - 1 ];
Line 4394 mpCharSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maCharLevel[ nLev ] =
mpCharSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maCharLevel[ nLev - 1 ];
Line 4395 }
Line 4396 mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->Read( rManager, rIn, sal_True,
nLev, bFirst );
(...)
Line 4412 mpCharSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->Read( rIn, sal_True, nLev,
bFirst );
Line 4413 mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->UpdateBulletRelSize( nLev,
mpCharSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maCharLevel[ nLev ].mnFontHeight );
Line 4414 bFirst = sal_False;
Line 4415 nLev++;
(...)
Line 4418 }
Line 4419 else
Line 4420 aTxMasterStyleHd.SeekToEndOfRecord( rIn );
First of all code in the while loop at Line 4378
searches for a PPT_PST_TxMasterStyleAtom record ( [MS-PPT] 2.9.35 TextMasterStyleAtom ). It finds it in the file at offset 0x957c
.
(gdb) p aTxMasterStyleHd
$8 = {nRecVer = 0 '\000', nRecInstance = 4, nImpVerInst = 64, nRecType = 4003, nRecLen = 4294901870, nFilePos = 380}
Next, we see that nLevelAnz
is read at line 4384
. According to documentation:
cLevels (2 bytes): An unsigned integer that specifies the number of style levels. It MUST be less than or equal to 0x0005.
but in our case its value is equal:
(gdb) n
4384 rIn >> nLevelAnz;
(gdb) p nLevelAnz
$9 = 65535 (0xffff)
We also see the following: PPTParaLevel maParaLevel[ 5 ]; and PPTCharLevel maCharLevel[ 5 ];
The lack of enforcement of the constraint that nLevelAnz
must be less than 5 results in the vulnerability. The variables maParaLevel
and maCharLevel
are written to at lines 4393-4394
. Our invalid value will cause nLev
to be bigger than 4 in the loop, which will result in an out of bound write. This can then lead to arbitrary code execution.
gdb-peda$ context
[----------------------------------registers-----------------------------------]
RAX: 0xb70 ('p\x0b')
RBX: 0x28a
RCX: 0x7fffc2ef0fdc --> 0x800000000010000
RDX: 0x7fffc2a4fd88 --> 0x64000020220000 ('')
RSI: 0x7fffc2a45170 --> 0x0
RDI: 0x7fffc2ef0ff0 --> 0x800000000010000
RBP: 0x28a
RSP: 0x7fffffffa7b0 --> 0x1
RIP: 0x7fffc2571dfc (mov WORD PTR [rdi+0x10],ax)
R8 : 0x5140 ('@Q')
R9 : 0x0
R10: 0x7fffc2a4f9c8 --> 0x7ffff09eca80 --> 0x7ffff07bfa64 (<_ZN16SotStorageStream7GetDataEPvm>: push rbp)
R11: 0xc8
R12: 0x0
R13: 0x28a
R14: 0x7fffc2a3f148 --> 0x7fffc2a77848 --> 0x7fffc2a413e8 --> 0x7b ('{')
R15: 0x7fffc2a4f9c8 --> 0x7ffff09eca80 --> 0x7ffff07bfa64 (<_ZN16SotStorageStream7GetDataEPvm>: push rbp)
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x7fffc2571df0: mov rax,QWORD PTR [rcx+0x8]
0x7fffc2571df4: mov QWORD PTR [rdi+0x8],rax
0x7fffc2571df8: movzx eax,WORD PTR [rcx+0x10]
=> 0x7fffc2571dfc: mov WORD PTR [rdi+0x10],ax
0x7fffc2571e00: mov rax,QWORD PTR [rsp+0x28]
0x7fffc2571e05: movzx r12d,r9b
0x7fffc2571e09: mov r8d,ebx
0x7fffc2571e0c: mov r9d,r12d
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa7b0 --> 0x1
0008| 0x7fffffffa7b8 --> 0x966f08 --> 0x7ffff7ffe480 --> 0x6db1b0 --> 0x7ffff7ffe1c8 --> 0x0
0016| 0x7fffffffa7c0 --> 0x7fffffffb160 --> 0x1
0024| 0x7fffffffa7c8 --> 0x7ffff7ed8808 --> 0x7fffc27ab310 --> 0x7fffc25730b0
(<_ZNK19SdrPowerPointImport9ImportOLEElRK7GraphicRK9RectangleS5_il>: push r15)
0032| 0x7fffffffa7d0 --> 0x7fffffffb0b0 --> 0xfc9000f0000b10f
0040| 0x7fffffffa7d8 --> 0x7fffc2a45170 --> 0x0
0048| 0x7fffffffa7e0 --> 0x7ffff7ed9000 --> 0x10000000b
0056| 0x7fffffffa7e8 --> 0x3e8a00000000
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
gdb-peda$ bt
#0 0x00007fffc2571dfc in ?? () from /opt/openoffice4/program/libmsfilter.so
#1 0x00007fffc2577c4d in SdrPowerPointImport::SdrPowerPointImport(PowerPointImportParam&, String const&) () from /opt/
openoffice4/program/libmsfilter.so
#2 0x00007fffc27c702e in ?? () from /opt/openoffice4/program/libsdfilt.so
#3 0x00007fffc27c74e9 in ?? () from /opt/openoffice4/program/libsdfilt.so
#4 0x00007fffc27ceafb in ImportPPT () from /opt/openoffice4/program/libsdfilt.so
#5 0x00007fffc326c4c8 in ?? () from /opt/openoffice4/program/../program/libsd.so
#6 0x00007fffc318884d in sd::DrawDocShell::ConvertFrom(SfxMedium&) () from /opt/openoffice4/program/../program/libsd.so
#7 0x00007ffff4ccc02f in SfxObjectShell::DoLoad(SfxMedium*) () from /opt/openoffice4/program/libsfx.so
#8 0x00007ffff4cf2202 in SfxBaseModel::load(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&)
() from /opt/openoffice4/program/libsfx.so
#9 0x00007ffff4d47093 in ?? () from /opt/openoffice4/program/libsfx.so
#10 0x00007fffee2a6750 in ?? () from /opt/openoffice4/program/libfwk.so
#11 0x00007fffee2a707e in ?? () from /opt/openoffice4/program/libfwk.so
#12 0x00007fffee2619a0 in ?? () from /opt/openoffice4/program/libfwk.so
#13 0x00007fffee261c0e in ?? () from /opt/openoffice4/program/libfwk.so
#14 0x00007ffff5d38868 in
comphelper::SynchronousDispatch::dispatch(com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const&,
rtl::OUString const&, rtl::OUString const&, int,
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) () from /opt/openoffice4/program/
libcomphelpgcc3.so
#15 0x00007ffff77971a3 in ?? () from /opt/openoffice4/program/libsofficeapp.so
#16 0x00007ffff77a33a6 in ?? () from /opt/openoffice4/program/libsofficeapp.so
#17 0x00007ffff77831f0 in ?? () from /opt/openoffice4/program/libsofficeapp.so
#18 0x00007ffff7784d0a in ?? () from /opt/openoffice4/program/libsofficeapp.so
#19 0x00007ffff2ec6ab3 in ?? () from /opt/openoffice4/program/libvcl.so
#20 0x00007fffea8f9b27 in SalDisplay::DispatchInternalEvent() () from /opt/openoffice4/program/libvclplug_gen.so
#21 0x00007fffeabb63b4 in ?? () from /opt/openoffice4/program/libvclplug_gtk.so
#22 0x00007fffe9aed175 in g_main_dispatch (context=0x65ea80) at gmain.c:3154
#23 g_main_context_dispatch (context=context@entry=0x65ea80) at gmain.c:3769
#24 0x00007fffe9aed4e8 in g_main_context_iterate (context=context@entry=0x65ea80, block=block@entry=0x0,
dispatch=dispatch@entry=0x1, self=<optimized out>) at gmain.c:3840
#25 0x00007fffe9aed58c in g_main_context_iteration (context=0x65ea80, may_block=0x0) at gmain.c:3901
#26 0x00007fffeabb61f0 in ?? () from /opt/openoffice4/program/libvclplug_gtk.so
#27 0x00007ffff2caa45f in ?? () from /opt/openoffice4/program/libvcl.so
#28 0x00007ffff2ca9667 in Application::Execute() () from /opt/openoffice4/program/libvcl.so
#29 0x00007ffff777e93e in ?? () from /opt/openoffice4/program/libsofficeapp.so
#30 0x00007ffff2cad7eb in ?? () from /opt/openoffice4/program/libvcl.so
#31 0x00007ffff2cad8b6 in SVMain() () from /opt/openoffice4/program/libvcl.so
#32 0x00007ffff77a5f8c in soffice_main () from /opt/openoffice4/program/libsofficeapp.so
#33 0x0000000000400f7b in main ()
#34 0x00007ffff6646f45 in __libc_start_main (main=0x400f70 <main>, argc=0x6, argv=0x7fffffffdf18, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdf08)
at libc-start.c:287
#35 0x0000000000400eb9 in _start ()
gdb-peda$ exploitable
Description: Access violation on destination operand
Short description: DestAv (9/29)
Hash: 0bbf6be05d7aaa5fd446172b8afe89c9.4e7dfbc3f1e3222a4c595e370f909d8b
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)
2017-03-29 - Vendor Disclosure
2017-10-26 - Public Release
Discovered by Marcin 'Icewall' Noga of Cisco Talos.