CVE-2017-2794
An exploitable stack-based buffer overflow vulnerability exists in the DHFSummary functionality of AntennaHouse DMC HTMLFilter as used by MarkLogic 8.0-6. A specially crafted PPT file can cause a stack corruption resulting in arbitrary code execution. An attacker can send/provide malicious PPT file to trigger this vulnerability.
AntennaHouse DMC HTMLFilter shipped with MarkLogic 8.0-6 fb1a22fa08c986ec3614284f4e912b0a /opt/MarkLogic/Converters/cvtofc/libdhf_rdoc.so 15b0acc464fba28335239f722a62037f /opt/MarkLogic/Converters/cvtofc/libdmc_comm.so 1eabb31236c675f9856a7d001b339334 /opt/MarkLogic/Converters/cvtofc/libdhf_rxls.so 1415cbc784f05db0e9db424636df581a /opt/MarkLogic/Converters/cvtofc/libdhf_comm.so 4ae366fbd4540dd4c750e6679eb63dd4 /opt/MarkLogic/Converters/cvtofc/libdmc_conf.so 81db1b55e18a0cb70a78410147f50b9c /opt/MarkLogic/Converters/cvtofc/libdhf_HTMLif.so d716dd77c8e9ee88df435e74fad687e6 /opt/MarkLogic/Converters/cvtofc/libdhf_wHTML.so e01d37392e2b2cea757a52ddb7873515 /opt/MarkLogic/Converters/cvtofc/convert
https://www.antennahouse.com/antenna1/
8.3 - CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H CVSSv3 Calculator: https://www.first.org/cvss/calculator/3.0
This vulnerability is present in the AntennaHouse DMC HTMLFilter which is used, among others, to convert PPT files to (X)HTML form.
This product is mainly used by MarkLogic for office document conversions as part of their web based document search and rendering engine.
A specially crafted PPT file can lead to an stack corruption and ultimately to remote code execution.
Let’s investigate this vulnerability. After executing the PPT to HTML converter with the malformed PPT file as an input we can easily observe a problem using Valgrind:
gdb-peda$ context
b[----------------------------------registers-----------------------------------]
EAX: 0x80ad640 --> 0xb3e3
EBX: 0xf7f06000 --> 0x1aada8
ECX: 0xebfebe6f
EDX: 0xffffdff0 --> 0xb3d3
ESI: 0x7c ('|')
EDI: 0xfffe9f58 ("TSER")
EBP: 0xfffe9f18 --> 0xfffea788 --> 0x50 ('P')
ESP: 0xfffe9e88 --> 0xf7cd2848 --> 0x3770 ('p7')
EIP: 0xf7e8f2fd (movntdq XMMWORD PTR [edx+0x10],xmm1)
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xf7e8f2f0: lfence
0xf7e8f2f3: sub ecx,0x80
0xf7e8f2f9: movntdq XMMWORD PTR [edx],xmm0
=> 0xf7e8f2fd: movntdq XMMWORD PTR [edx+0x10],xmm1
0xf7e8f302: movntdq XMMWORD PTR [edx+0x20],xmm2
0xf7e8f307: movntdq XMMWORD PTR [edx+0x30],xmm3
0xf7e8f30c: movntdq XMMWORD PTR [edx+0x40],xmm4
0xf7e8f311: movntdq XMMWORD PTR [edx+0x50],xmm5
[------------------------------------stack-------------------------------------]
0000| 0xfffe9e88 --> 0xf7cd2848 --> 0x3770 ('p7')
0004| 0xfffe9e8c --> 0xf7cd130d (add esp,0x10)
0008| 0xfffe9e90 --> 0xfffe9f58 ("TSER")
0012| 0xfffe9e94 --> 0x8099528 ("TSER")
0016| 0xfffe9e98 --> 0xec000007
0020| 0xfffe9e9c --> 0xf7cd100a (pop ebx)
0024| 0xfffe9ea0 --> 0xfffe9f00 --> 0xfffea788 --> 0x50 ('P')
0028| 0xfffe9ea4 --> 0xf7fea161 (sub esp,0x14)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
gdb-peda$ bt 10
#0 __memcpy_ssse3_rep () at ../sysdeps/i386/i686/multiarch/memcpy-ssse3-rep.S:1295
#1 0xf7cd130d in DHFSummary () from ./libdhf_comm.so
#2 0xf7cd1576 in DHF_SummaryInfo () from ./libdhf_comm.so
#3 0x00000050 in ?? ()
#4 0x00000051 in ?? ()
#5 0x00000051 in ?? ()
#6 0x00000052 in ?? ()
#7 0x00000052 in ?? ()
#8 0x00000053 in ?? ()
#9 0x00000053 in ?? ()
(More stack frames follow...)
gdb-peda$ exploitable
Description: Possible stack corruption
Short description: PossibleStackCorruption (8/29)
Hash: ea379fd123d7bb722a0a3ac6a0b24fd7.4e17f16447b1c349dcaf3f667f35ae8d
Exploitability Classification: EXPLOITABLE
Explanation: GDB generated an error while unwinding the stack and/or the stack contained return addresses that were not mapped in the inferior's process address space and/or the stack pointer is pointing to a location outside the default stack region. These conditions likely indicate stack corruption, which is generally considered exploitable.
Other tags: DestAv (9/29), AccessViolation (28/29)
we see that memcpy
called in DHFSummary
function caused a stack based buffer overflow which resulted in stack corruption. Let’s investigate the moment when memcpy
is called:
[----------------------------------registers-----------------------------------]
EAX: 0x9228528 ("TSER")
EBX: 0xf740f848 --> 0x3770 ('p7')
ECX: 0x92284a8 --> 0x1
EDX: 0xff833340 --> 0x0
ESI: 0x7c ('|')
EDI: 0xff833358 ("Slide 1")
EBP: 0xff833318 --> 0xff833b88 --> 0xff835cd8 --> 0xff835d08 --> 0xff835d38 --> 0xff836118 --> 0xff846488 --> 0x0
ESP: 0xff833290 --> 0xff833358 ("Slide 1")
EIP: 0xf740e308 --> 0xffec77e8
EFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xf740e300: push DWORD PTR [edx+0x820]
0xf740e306: push eax
0xf740e307: push edi
=> 0xf740e308: call 0xf740cf84 <memcpy@plt>
0xf740e30d: add esp,0x10
0xf740e310: mov ecx,DWORD PTR [ebp+0x8]
0xf740e313: cmp DWORD PTR [ecx+0x820],0x100
0xf740e31d: jle 0xf740e333
Guessed arguments:
arg[0]: 0xff833358 ("Slide 1")
arg[1]: 0x9228528 ("TSER")
arg[2]: 0xec000007
The size
parameter is huge and equals 0xec000007
. We can easily observe in the pseudo-code where the value is coming from:
Line 1 signed int __cdecl DHFSummary(struct_a1 *a1, int a2, int a3)
Line 2 {
Line 3 int 20;
Line 4 (...)
Line 5 else if ( v17 > 3 )
Line 6 {
Line 7 if ( v17 == 30 )
Line 8 {
Line 9 v19 = DHFSum_GetDWord(a1, &fileBuffer[offset]);
Line 10 a1->overflowSize = v19;
Line 11 if ( v19 )
Line 12 {
Line 13 v20 = v19 - 1;
Line 14 a1->overflowSize = v20;
Line 15 if ( v20 > 1026 )
Line 16 a1->overflowSize = 1026;
Line 17 memcpy(&a1->stackBuffer, &fileBuffer[offset + 4], a1->overflowSize);
Line 18 if ( a1->overflowSize > 256 )
Line 19 DHFCutString(&a1->stackBuffer, &a1->overflowSize);
Line 20 DHFSum_CodeConv(a1, 2);
Line 21 memcpy(dest, src, a1->dword824);
Line 22 }
Line 23 }
We see that v20
variable is read directly from the file by the DHFSum_GetDWord
function line 9
, so an attacker has nearly full control of this value. Nearly, because
v20
is checked to see if its value exceeds 1026 at line 15
. The problem is that v20
is a signed value and values greater than 0x7fffffff will cause a negative value to be compared, which bypasses this check causing stack corruption.
File structure analysis reveal that the value 0xec000007
(0xec000008 in the file, it’s decreased by one before the memcpy at line 13
) is located in Summary Information
data structure.
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
00001A00 FE FF 00 00 05 01 02 00 00 00 00 00 00 00 00 00 ˛ˇ…………..
00001A10 00 00 00 00 00 00 00 00 01 00 00 00 E0 85 9F F2 …………‡ÖüÚ
00001A20 F9 4F 68 10 AB 91 08 00 2B 27 B3 D9 30 00 00 00 ˘Oh.´ë..+’≥Ÿ0…
00001A30 A4 05 00 00 0B 00 00 00 01 00 00 00 60 00 00 00 §……….....
00001A40 02 00 00 00 68 00 00 00 04 00 00 00 78 00 00 00 ....h.......x...
00001A50 08 00 00 00 88 00 00 00 09 00 00 00 98 00 00 00 ....à.......ò...
00001A60 12 00 00 00 A4 00 00 00 0A 00 00 00 C8 00 00 00 ....§.......»...
00001A70 0C 00 00 00 D4 00 00 00 0D 00 00 00 E0 00 00 00 ....‘.......‡...
00001A80 0F 00 00 00 EC 00 00 00 11 00 00 00 F4 00 00 00 ....Ï.......Ù...
00001A90 02 00 00 00 B6 03 00 00 1E 00 00 00 08 00 00 00 ....∂...........
00001AA0 53 6C 69 64 65 20 31 00 1E 00 00 00 08 00 00 EC Slide 1........Ï
00001AB0 54 53 45 52 00 00 00 00 1E 00 00 00 08 00 00 00 TSER............
00001AC0 55 53 45 52 00 00 00 00 1E 00 00 00 04 00 00 00 USER............
00001AD0 36 00 00 00 1E 00 00 00 1C 00 00 00 4D 69 63 72 6...........Micr
00001AE0 6F 73 6F 66 74 20 4F 66 66 69 63 7C 20 50 6F 77 osoft Offic| Pow
00001AF0 65 72 50 6F 69 6E 74 00 40 00 00 00 10 E3 A3 A9 erPoint.@....㣩
00001B00 00 00 00 00 40 00 00 00 A0 1E CC 1E D8 39 C5 01 ....@...†.Ã.ÿ9≈.
00001B10 40 00 00 00 30 9F 60 87 D9 39 C5 01 03 00 00 00 @...0ü
áŸ9≈…..
00001B20 18 00 00 00 47 00 00 00 A8 04 00 00 FF FF FF FF ….G…®…ˇˇˇˇ
Summary Information
starts at offset 00001A00 in the file, and the field used in the memcpy operation is located at offset: 0x1AAC.
gdb-peda$ context
b[----------------------------------registers-----------------------------------]
EAX: 0x80ad640 --> 0xb3e3
EBX: 0xf7f06000 --> 0x1aada8
ECX: 0xebfebe6f
EDX: 0xffffdff0 --> 0xb3d3
ESI: 0x7c ('|')
EDI: 0xfffe9f58 ("TSER")
EBP: 0xfffe9f18 --> 0xfffea788 --> 0x50 ('P')
ESP: 0xfffe9e88 --> 0xf7cd2848 --> 0x3770 ('p7')
EIP: 0xf7e8f2fd (movntdq XMMWORD PTR [edx+0x10],xmm1)
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xf7e8f2f0: lfence
0xf7e8f2f3: sub ecx,0x80
0xf7e8f2f9: movntdq XMMWORD PTR [edx],xmm0
=> 0xf7e8f2fd: movntdq XMMWORD PTR [edx+0x10],xmm1
0xf7e8f302: movntdq XMMWORD PTR [edx+0x20],xmm2
0xf7e8f307: movntdq XMMWORD PTR [edx+0x30],xmm3
0xf7e8f30c: movntdq XMMWORD PTR [edx+0x40],xmm4
0xf7e8f311: movntdq XMMWORD PTR [edx+0x50],xmm5
[------------------------------------stack-------------------------------------]
0000| 0xfffe9e88 --> 0xf7cd2848 --> 0x3770 ('p7')
0004| 0xfffe9e8c --> 0xf7cd130d (add esp,0x10)
0008| 0xfffe9e90 --> 0xfffe9f58 ("TSER")
0012| 0xfffe9e94 --> 0x8099528 ("TSER")
0016| 0xfffe9e98 --> 0xec000007
0020| 0xfffe9e9c --> 0xf7cd100a (pop ebx)
0024| 0xfffe9ea0 --> 0xfffe9f00 --> 0xfffea788 --> 0x50 ('P')
0028| 0xfffe9ea4 --> 0xf7fea161 (sub esp,0x14)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
gdb-peda$ bt 10
#0 __memcpy_ssse3_rep () at ../sysdeps/i386/i686/multiarch/memcpy-ssse3-rep.S:1295
#1 0xf7cd130d in DHFSummary () from ./libdhf_comm.so
#2 0xf7cd1576 in DHF_SummaryInfo () from ./libdhf_comm.so
#3 0x00000050 in ?? ()
#4 0x00000051 in ?? ()
#5 0x00000051 in ?? ()
#6 0x00000052 in ?? ()
#7 0x00000052 in ?? ()
#8 0x00000053 in ?? ()
#9 0x00000053 in ?? ()
(More stack frames follow...)
gdb-peda$ exploitable
Description: Possible stack corruption
Short description: PossibleStackCorruption (8/29)
Hash: ea379fd123d7bb722a0a3ac6a0b24fd7.4e17f16447b1c349dcaf3f667f35ae8d
Exploitability Classification: EXPLOITABLE
Explanation: GDB generated an error while unwinding the stack and/or the stack contained return addresses that were not mapped in the inferior's process address space and/or the stack pointer is pointing to a location outside the default stack region. These conditions likely indicate stack corruption, which is generally considered exploitable.
Other tags: DestAv (9/29), AccessViolation (28/29)
2017-02-21 - Vendor Disclosure
2017-05-04 - Public Release
Discovered by Marcin 'Icewall' Noga of Cisco Talos.