Vulnerabilities > CVE-2017-2792 - Improper Restriction of Operations within the Bounds of a Memory Buffer vulnerability in Marklogic 8.06

047910
CVSS 6.8 - MEDIUM
Attack vector
NETWORK
Attack complexity
MEDIUM
Privileges required
NONE
Confidentiality impact
PARTIAL
Integrity impact
PARTIAL
Availability impact
PARTIAL

Summary

An exploitable heap corruption vulnerability exists in the iBldDirInfo functionality of Antenna House DMC HTMLFilter used by MarkLogic 8.0-6. A specially crafted xls file can cause a heap corruption resulting in arbitrary code execution. An attacker can provide a malicious xls file to trigger this vulnerability.

Vulnerable Configurations

Part Description Count
Application
Marklogic
1

Common Attack Pattern Enumeration and Classification (CAPEC)

  • Buffer Overflow via Environment Variables
    This attack pattern involves causing a buffer overflow through manipulation of environment variables. Once the attacker finds that they can modify an environment variable, they may try to overflow associated buffers. This attack leverages implicit trust often placed in environment variables.
  • Overflow Buffers
    Buffer Overflow attacks target improper or missing bounds checking on buffer operations, typically triggered by input injected by an attacker. As a consequence, an attacker is able to write past the boundaries of allocated buffer regions in memory, causing a program crash or potentially redirection of execution as per the attackers' choice.
  • Client-side Injection-induced Buffer Overflow
    This type of attack exploits a buffer overflow vulnerability in targeted client software through injection of malicious content from a custom-built hostile service.
  • Filter Failure through Buffer Overflow
    In this attack, the idea is to cause an active filter to fail by causing an oversized transaction. An attacker may try to feed overly long input strings to the program in an attempt to overwhelm the filter (by causing a buffer overflow) and hoping that the filter does not fail securely (i.e. the user input is let into the system unfiltered).
  • MIME Conversion
    An attacker exploits a weakness in the MIME conversion routine to cause a buffer overflow and gain control over the mail server machine. The MIME system is designed to allow various different information formats to be interpreted and sent via e-mail. Attack points exist when data are converted to MIME compatible format and back.

Seebug

bulletinFamilyexploit
description### Summary An exploitable heap corruption vulnerability exists in the iBldDirInfo functionality of AntennaHouse DMC HTMLFilter used by MarkLogic 8.0-6. A specially crafted xls file can cause a heap corruption resulting in arbitrary code execution. An attacker can provide a malicious xls file to trigger this vulnerability. ### Tested Versions 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 ``` ### Product URLs https://www.antennahouse.com/antenna1/ ### 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 the AntennaHouse DMC HTMLFilter which is used, among others, to convert xls files to (x)html form. This product is mainly used by MarkLogic for xls document conversions as part of their web based document search and rendering engine. A specially crafted XLS file can lead to heap corruption and ultimately to remote code execution. Let's investigate this vulnerability. After execution of the XLS to html converter with a malformed xls file as an input we can easily observe the following when using Valgrind: ``` icewall@ubuntu:~/bugs/cvtofc_86$ valgrind ./convert config_xls/ ==43073== Memcheck, a memory error detector ==43073== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==43073== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==43073== Command: ./convert config_xls/ ==43073== input=/home/icewall/bugs/cvtofc_86/config_xls/toconv.xls output=/home/icewall/bugs/cvtofc_86/config_xls/conv.html type=2 info.options='0' ==43073== Invalid write of size 1 ==43073== at 0x42E012A: iBldDirInfo (in /home/icewall/bugs/cvtofc_86/libdmc_comm.so) ==43073== by 0x42DEDDA: DMC_2OLEopen (in /home/icewall/bugs/cvtofc_86/libdmc_comm.so) ==43073== by 0x42C0941: CommOLEOpen (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42BB8C9: autoOLE (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42BFD2C: detectFormat (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42C0269: DMC_FileDtct (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x4038144: DHF_GetFileInfo_V1 (in /home/icewall/bugs/cvtofc_86/libdhf_htmlif.so) ==43073== by 0x80498B4: main (in /home/icewall/bugs/cvtofc_86/convert) ==43073== Address 0x4bedb90 is 0 bytes after a block of size 1,536 alloc'd ==43073== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==43073== by 0x42DCCB1: DMC_malloc (in /home/icewall/bugs/cvtofc_86/libdmc_comm.so) ==43073== by 0x42DFFAD: iBldDirInfo (in /home/icewall/bugs/cvtofc_86/libdmc_comm.so) ==43073== by 0x42DEDDA: DMC_2OLEopen (in /home/icewall/bugs/cvtofc_86/libdmc_comm.so) ==43073== by 0x42C0941: CommOLEOpen (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42BB8C9: autoOLE (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42BFD2C: detectFormat (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42C0269: DMC_FileDtct (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x4038144: DHF_GetFileInfo_V1 (in /home/icewall/bugs/cvtofc_86/libdhf_htmlif.so) ==43073== by 0x80498B4: main (in /home/icewall/bugs/cvtofc_86/convert) ==43073== ==43073== Invalid write of size 1 ==43073== at 0x42E0151: iBldDirInfo (in /home/icewall/bugs/cvtofc_86/libdmc_comm.so) ==43073== by 0x42DEDDA: DMC_2OLEopen (in /home/icewall/bugs/cvtofc_86/libdmc_comm.so) ==43073== by 0x42C0941: CommOLEOpen (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42BB8C9: autoOLE (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42BFD2C: detectFormat (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42C0269: DMC_FileDtct (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x4038144: DHF_GetFileInfo_V1 (in /home/icewall/bugs/cvtofc_86/libdhf_htmlif.so) ==43073== by 0x80498B4: main (in /home/icewall/bugs/cvtofc_86/convert) ==43073== Address 0x4bedb91 is 1 bytes after a block of size 1,536 alloc'd ==43073== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==43073== by 0x42DCCB1: DMC_malloc (in /home/icewall/bugs/cvtofc_86/libdmc_comm.so) ==43073== by 0x42DFFAD: iBldDirInfo (in /home/icewall/bugs/cvtofc_86/libdmc_comm.so) ==43073== by 0x42DEDDA: DMC_2OLEopen (in /home/icewall/bugs/cvtofc_86/libdmc_comm.so) ==43073== by 0x42C0941: CommOLEOpen (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42BB8C9: autoOLE (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42BFD2C: detectFormat (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x42C0269: DMC_FileDtct (in /home/icewall/bugs/cvtofc_86/libdmc_dtct.so) ==43073== by 0x4038144: DHF_GetFileInfo_V1 (in /home/icewall/bugs/cvtofc_86/libdhf_htmlif.so) ==43073== by 0x80498B4: main (in /home/icewall/bugs/cvtofc_86/convert) ``` We see that a heap-based buffer overflow occurs in the function `iBldDirInfo`. The overflowed buffer is also allocated in this function. Running our target with an instrumented heap we stop in the following place : ``` Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] EAX: 0x93 EBX: 0xf7c1acac --> 0x5ebf4 ECX: 0xe04a0fa0 --> 0x84938493 EDX: 0x60 ('`') ESI: 0x60 ('`') EDI: 0x60 ('`') EBP: 0xfffec748 --> 0xfffec788 --> 0xfffec7b8 --> 0xfffec9b8 --> 0xfffec9d8 --> 0xfffeca08 --> 0xfffeccc8 --> 0xffffd038 --> 0x0 ESP: 0xfffec640 --> 0xffffffff EIP: 0xf7bc412a (mov BYTE PTR [edx+ecx*1],al) EFLAGS: 0x10a06 (carry PARITY adjust zero sign trap INTERRUPT direction OVERFLOW) [-------------------------------------code-------------------------------------] 0xf7bc411d: movsx edx,si 0xf7bc4120: shr ax,0x8 0xf7bc4124: mov ecx,DWORD PTR [ebp-0xcc] => 0xf7bc412a: mov BYTE PTR [edx+ecx*1],al 0xf7bc412d: inc esi 0xf7bc412e: movsx eax,si 0xf7bc4131: mov dl,BYTE PTR [ebp-0xfa] 0xf7bc4137: jmp 0xf7bc414b [------------------------------------stack-------------------------------------] 0000| 0xfffec640 --> 0xffffffff 0004| 0xfffec644 --> 0xffffffff 0008| 0xfffec648 --> 0xffffffff 0012| 0xfffec64c --> 0x93840000 0016| 0xfffec650 --> 0xe057e340 --> 0x0 0020| 0xfffec654 --> 0xe057cde0 --> 0xe049e000 --> 0xaaaaaaaa 0024| 0xfffec658 --> 0xe049ee00 --> 0x1 0028| 0xfffec65c --> 0xe049f000 --> 0x0 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0xf7bc412a in iBldDirInfo () from ./libdmc_comm.so gdb-peda$ bt #0 0xf7bc412a in iBldDirInfo () from ./libdmc_comm.so #1 0xf7bc2ddb in DMC_2OLEopen () from ./libdmc_comm.so #2 0xf7c25942 in CommOLEOpen () from ./libdmc_dtct.so #3 0xf7c208ca in autoOLE () from ./libdmc_dtct.so #4 0xf7c24d2d in detectFormat () from ./libdmc_dtct.so #5 0xf7c2526a in DMC_FileDtct () from ./libdmc_dtct.so #6 0xf7fc0145 in DHF_GetFileInfo_V1 () from ./libdhf_htmlif.so #7 0x080498b5 in main () #8 0xf7d60af3 in __libc_start_main (main=0x8049730 <main>, argc=0x2, argv=0xffffd0d4, init=0x8049f70 <__libc_csu_init>, fini=0x8049f60 <__libc_csu_fini>, rtld_fini=0xf7feb160 <_dl_fini>, stack_end=0xffffd0cc) at libc-start.c:287 #9 0x08048ad1 in _start () ``` To figure out something more about the place where the out-of-bound write appears, we can review the pseudo code of the `iBldDirInfo` function: ``` Line 1 signed int __cdecl iBldDirInfo(struct_a1 *a1) Line 2 { Line 3 (...) Line 4 Line 5 v24 = 0; Line 6 v18 = -2; Line 7 v17 = 0; Line 8 v1 = (unsigned int)(a1->dword2C * a1->dword38) >> 2; Line 9 v21 = a1->dword38 / 128; Line 10 v23 = 1; Line 11 v2 = 0; Line 12 for ( i = lGetSect(a1, a1->dwordC); ; i = lGetSect(a1, v19) ) Line 13 { Line 14 v19 = i; Line 15 if ( i == -1 ) Line 16 break; Line 17 if ( i <= -2 ) Line 18 { Line 19 v5 = v21 * v23; Line 20 a1->dword48 = v5; Line 21 v6 = DMC_malloc(96 * v5); Line 22 a1->buffer = v6; Line 23 if ( v6 ) Line 24 { Line 25 v20 = a1->dwordC; Line 26 if ( !DMC_FileSeek(a1->pfile0, (v20 << a1->word8) + 512, 0) ) Line 27 { Line 28 a1->word52 = 0; Line 29 elementIndex = 0; Line 30 while ( DMC_FileRead(rawDirectoryEntry, 1u, 0x80u, a1->pfile0) && elementIndex < a1->dword48 ) Line 31 { Line 32 directoryEntry = (a1->buffer + 96 * elementIndex); Line 33 v7 = usGetShort(&v26); Line 34 if ( v7 ) Line 35 { Line 36 directoryEntry->unsigned20 = v7; Line 37 ++a1->word52; Line 38 } Line 39 else Line 40 { Line 41 v24 = 1; Line 42 } Line 43 if ( v7 && !v24 ) Line 44 { Line 45 memset(directoryEntry, 0, 0x20u); Line 46 v8 = 0; Line 47 index = 0; Line 48 directoryEntry->unsigned20; Line 49 while ( index <= 127 ) Line 50 { Line 51 v10 = DMC_unicodetosjis(((rawDirectoryEntry[index + 1] << 8) | rawDirectoryEntry[index])); Line 52 v15 = v10; Line 53 if ( v10 ) Line 54 { Line 55 v11 = v10 & 0xFF00; Line 56 if ( v11 ) Line 57 directoryEntry->Name[v8++] = BYTE1(v11); Line 58 v12 = v8; Line 59 v13 = v15; Line 60 } Line 61 else Line 62 { Line 63 v12 = v8; Line 64 v13 = rawDirectoryEntry[index]; Line 65 } Line 66 directoryEntry->Name[v12] = v13; Line 67 ++v8; Line 68 index += 2; Line 69(...) ``` The out of bound write occurs at `line 57`. This code parses a `Compound File Directory Entry`, doing name conversion from Unicode to SJIS (Shift Japanese Industrial Standards) and fills dynamically allocated structure `directoryEntry` with the converted name. According to the documentation Directory Name should not be bigger than 64 bytes. We see a check for that in the while loop at `line 49`. The problem appears because instead of only increasing the counter `index` by 2 each time in the `while loop`, the developers also increase `v8` by 2 when a correct conversion took place from Unicode to SJIS. `We see v8` being incremented at lines `57` and `67`. `v8` as a `Directory Name` string index should not exceed 64 and should definitely not exceed 96 as is expected at `line 32`. As we can imagine, v8 can easly reach a value like 126 which occurs when: there is still space for more `Directory Entry` structures (see allocation at `line 21`, `v5` equals the amount of `Directory Entries`), a write on buffer space dedicated for the next `Directory Entry` which will cause the current `Directory Entry` name to be overwritten during the next `Directory Entry` read. But the most dangerous scenario appears when the parsed `Directory Entry` is the last one, writing outside of the `Name` buffer will cause a heap based buffer overflow, causing heap corruption which can lead to arbitrary code execution. ### Crash Information ``` Program received signal SIGABRT, Aborted. [----------------------------------registers-----------------------------------] EAX: 0x0 EBX: 0xab33 ECX: 0xab33 EDX: 0x6 ESI: 0x68 ('h') EDI: 0xf7f06000 --> 0x1aada8 EBP: 0xfffec698 --> 0x8095590 --> 0x84938493 ESP: 0xfffec3d4 --> 0xfffec698 --> 0x8095590 --> 0x84938493 EIP: 0xf7fdacd9 (pop ebp) EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0xf7fdacd3: mov ebp,esp 0xf7fdacd5: sysenter 0xf7fdacd7: int 0x80 => 0xf7fdacd9: pop ebp 0xf7fdacda: pop edx 0xf7fdacdb: pop ecx 0xf7fdacdc: ret 0xf7fdacdd: and edi,edx [------------------------------------stack-------------------------------------] 0000| 0xfffec3d4 --> 0xfffec698 --> 0x8095590 --> 0x84938493 0004| 0xfffec3d8 --> 0x6 0008| 0xfffec3dc --> 0xab33 0012| 0xfffec3e0 --> 0xf7d89687 (xchg ebx,edi) 0016| 0xfffec3e4 --> 0xf7f06000 --> 0x1aada8 0020| 0xfffec3e8 --> 0xfffec484 --> 0x270f 0024| 0xfffec3ec --> 0xf7d8cab3 (mov edx,DWORD PTR gs:0x8) 0028| 0xfffec3f0 --> 0x6 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGABRT 0xf7fdacd9 in ?? () gdb-peda$ exploitable Description: Heap error Short description: HeapError (15/29) Hash: eeae24290f4714292e59633fa30e2480.ff49ca1e4902951bc44eee297b21de88 Exploitability Classification: EXPLOITABLE Explanation: The target's backtrace indicates that libc has detected a heap error or that the target was executing a heap function when it stopped. This could be due to heap corruption, passing a bad pointer to a heap function such as free(), etc. Since heap errors might include buffer overflows, use-after-free situations, etc. they are generally considered exploitable. Other tags: AbortSignal (27/29) ``` ### Timeline * 2017-02-09 - Vendor Disclosure * 2017-05-04 - Public Release ### CREDIT * Discovered by Marcin 'Icewall' Noga of Cisco Talos.
idSSV:96522
last seen2017-11-19
modified2017-09-19
published2017-09-19
reporterRoot
titleAntennaHouse DMC HTMLFilter iBldDirInfo Code Execution Vulnerability(CVE-2017-2792)

Talos

idTALOS-2017-0284
last seen2019-05-29
published2017-05-04
reporterTalos Intelligence
sourcehttp://www.talosintelligence.com/vulnerability_reports/TALOS-2017-0284
titleAntennaHouse DMC HTMLFilter iBldDirInfo Code Execution Vulnerability