Talos Vulnerability Report

TALOS-2017-0271

Iceni Argus ipStringCreate Code Execution Vulnerability

February 27, 2017

Report ID

CVE-2017-2777

Summary

An exploitable heap overflow vulnerability exists in the ipStringCreate function of Iceni Argus Version 6.6.05. A specially crafted pdf file can cause an integer overflow resulting in heap overflow. An attacker can send file to trigger this vulnerability.

Tested Versions

Iceni Argus 6.6.05 (Sep 22 2016) NK

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
CVSSv3 Calculator: https://www.first.org/cvss/calculator/3.0

CWE

CWE-190: Integer Overflow or Wraparound

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.

The problem exists in one of general functions, this is `ipStringCreate`. As its name says, the function is responsible for creating string object from supplied parameters: a buffer and its size. Let's take a look at body of this function:

Line 1 	_DWORD *__cdecl ipStringCreate(int a1, void *buffPtr, size_t size)
Line 2 	{
Line 3 	  _DWORD *v3; // esi@2
Line 4
Line 5 	  if ( a1 )
Line 6 		v3 = (_DWORD *)icnChainAlloc(a1, size + 11);
Line 7 	  else
Line 8 		v3 = icnMalloc(size + 11, (unsigned int)"IPSTRING");
Line 9 	  if ( v3 )
Line 10	  {
Line 11		v3[1] = size;
Line 12		*(_BYTE *)v3 = 0;
Line 13		memmove(v3 + 2, buffPtr, size);
Line 14	  }
Line 15	  return v3;
Line 16	}

In Line 6 where the buffer for the string object is allocated, an integer overflow can appear in the second argument. For size, an argument value bigger than 0xfffffff4 will trigger this occurence. Next in line 13 we see that the buffPtr argument content is copied to the allocated buffer. As we can see the size argument will have bigger value than size+11 which will lead to heap corruption.

An example of a place where the `ipStringCreate` function can receive a huge `size` argument is shown below:

Line 1 int __cdecl ipXRefGetStreamObj(int a1, unsigned int a2, size_t *size)
Line 2 {
Line 3 (...)
Line 4 (.text:081602A3)
Line 5   buffPtr = icnMalloc(*size, (unsigned int)"ipXRefGetStreamObj");
Line 6   if ( !buffPtr
Line 7     || (*size = ipDataFeedRead(v42->pstruct_a1_118, buffPtr, *size),
Line 8         ipStreamClose((int)v42),
Line 9         (v20 = ipStringCreate(0, buffPtr, *size)) == 0) )
Line 10  {
Line 11

this piece of code belongs to the `ipXRefGetStreamObj` function.

There is a missing check for a potential error code returned from ipDataFeedRead which is requal -1 (0xffffffff). We see in line 7 that returned value is directly assigned to size variable and next this variable is passed as 3th argument to ipStringCreate. As mentioned before, for values bigger than 0xfffffff4 integer overflow will occure in ipStringCreate leading to heap overflow.

Crash Information

Loading configuration...
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...

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xf79f5e28 --> 0x0
EBX: 0xf7f0c000 --> 0x1aada8
ECX: 0xfffb915f
EDX: 0x999b000
ESI: 0x9954258 --> 0xf7f0c400 --> 0xf7dd8ca0 (: push ebx)
EDI: 0xffffffff
EBP: 0xfffc6c3c --> 0xffffffff
ESP: 0xfffc6b18 --> 0x8fbc6e8 --> 0x8fbbe90 --> 0x1
EIP: 0xf7e972d9 (movntdq XMMWORD PTR [edx],xmm0)
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xf7e972ca: lea eax,[eax+0x80]
0xf7e972d0: lfence
0xf7e972d3: sub ecx,0x80
=> 0xf7e972d9: movntdq XMMWORD PTR [edx],xmm0
0xf7e972dd: movntdq XMMWORD PTR [edx+0x10],xmm1
0xf7e972e2: movntdq XMMWORD PTR [edx+0x20],xmm2
0xf7e972e7: movntdq XMMWORD PTR [edx+0x30],xmm3
0xf7e972ec: movntdq XMMWORD PTR [edx+0x40],xmm4
[------------------------------------stack-------------------------------------]
0000| 0xfffc6b18 --> 0x8fbc6e8 --> 0x8fbbe90 --> 0x1
0004| 0xfffc6b1c --> 0x81053ef (add esp,0x10)
0008| 0xfffc6b20 --> 0x9954260 --> 0x0
0012| 0xfffc6b24 --> 0xf79af008 --> 0x0
0016| 0xfffc6b28 --> 0xffffffff
0020| 0xfffc6b2c --> 0x8fbc6e8 --> 0x8fbbe90 --> 0x1
0024| 0xfffc6b30 --> 0x8fbc6e8 --> 0x8fbbe90 --> 0x1
0028| 0xfffc6b34 --> 0x33 ('3')
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
__memmove_ssse3_rep () at ../sysdeps/i386/i686/multiarch/memcpy-ssse3-rep.S:1294
1294 ../sysdeps/i386/i686/multiarch/memcpy-ssse3-rep.S: No such file or directory.
gdb-peda$ bt
#0 __memmove_ssse3_rep () at ../sysdeps/i386/i686/multiarch/memcpy-ssse3-rep.S:1294
#1 0x081053ef in ipStringCreate ()
#2 0x081602eb in ipXRefGetStreamObj ()
#3 0x0809d13b in ipObjResolveMem ()
#4 0x0809d6de in ipObjResolve ()
#5 0x0808ae89 in ipDocGetNofPages ()
#6 0x080dd105 in indexPageRefs ()
#7 0x08090d43 in ipDocCreate ()
#8 0x0806a3ec in icnDocCreate ()
#9 0x080556a7 in dumpFile ()
#10 0x080558e3 in dumpCommandLine ()
#11 0x08051ef5 in icnArgusExtract ()
#12 0x08050f76 in main ()
#13 0xf7d7aaf3 in __libc_start_main (main=0x8050810 , argc=0x2, argv=0xffffd124, init=0x83a20b0 , fini=0x83a20a0 , rtld_fini=0xf7feb160 ,
stack_end=0xffffd11c) at libc-start.c:287
#14 0x08050779 in _start ()
gdb-peda$ exploitable -m
Warning: machine string printing is deprecated and may be removed in a future release.
EXCEPTION_FAULTING_ADDRESS:0x0000000999b000
EXCEPTION_CODE:0xb
FAULTING_INSTRUCTION:movntdq XMMWORD PTR [edx],xmm0
MAJOR_HASH:11fb4e93a4aed79572ed69570240cdbc
MINOR_HASH:5448472d466da074f83d513d364816da
STACK_DEPTH:13
STACK_FRAME:/lib/i386-linux-gnu/libc-2.19.so!__memmove_ssse3_rep+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!ipStringCreate+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!ipXRefGetStreamObj+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!ipObjResolveMem+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!ipObjResolve+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!ipDocGetNofPages+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!indexPageRefs+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!ipDocCreate+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!icnDocCreate+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!dumpFile+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!dumpCommandLine+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!icnArgusExtract+0x0
STACK_FRAME:/home/icewall/bugs/cvtpdf_86/convert!main+0x0
INSTRUCTION_ADDRESS:0x000000f7e972d9
INVOKING_STACK_FRAME:1
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: 11fb4e93a4aed79572ed69570240cdbc.5448472d466da074f83d513d364816da
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)

Credit

Discovered by Marcin Noga of Cisco Talos .

Timeline

2017-01-11 - Vendor Disclosure
2017-02-27 - Public Release