Vulnerabilities > CVE-2016-8389 - Integer Overflow or Wraparound vulnerability in Iceni Argus 6.6.04

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-190

Summary

An exploitable integer-overflow vulnerability exists within Iceni Argus. When it attempts to convert a malformed PDF to XML, it will attempt to convert each character from a font into a polygon and then attempt to rasterize these shapes. As the application attempts to iterate through the rows and initializing the polygon shape in the buffer, it will write outside of the bounds of said buffer. This can lead to code execution under the context of the account running it.

Vulnerable Configurations

Part Description Count
Application
Iceni
1

Common Weakness Enumeration (CWE)

Common Attack Pattern Enumeration and Classification (CAPEC)

  • Forced Integer Overflow
    This attack forces an integer variable to go out of range. The integer variable is often used as an offset such as size of memory allocation or similarly. The attacker would typically control the value of such variable and try to get it out of range. For instance the integer in question is incremented past the maximum possible value, it may wrap to become a very small, or negative number, therefore providing a very incorrect value which can lead to unexpected behavior. At worst the attacker can execute arbitrary code.

Seebug

bulletinFamilyexploit
description### Summary An exploitable integer-overflow vulnerability exists within Iceni Argus. When it attempts to convert a malformed PDF to XML, it will attempt to convert each character from a font into a polygon and then attempt to rasterize these shapes. When rasterizing these shapes, the tool will perform a multiplication to determine the bounds at which the shape can be filled as well as use it to perform an allocation. Due to a lack of bounds checking, this multiplication can result in an integer larger than 32-bits which is an integer overflow. As the application attempts to iterate through the rows and initializing the polygon shape in the buffer, it will write outside of the bounds of said buffer. This can lead to code execution under the context of the account running it. ### Tested Versions Iceni Argus Version 6.6.04 (Sep 7 2012) 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 ### Details This is an integer overflow that occurs in Iceni Argus. This tool is used primarily by MarkLogic Server to convert PDF files to (X)HTML form. Due to the integer overflow, two different lengths will be used for an allocation and for a copy. The object that contains the objects with the sizes which are used in the overflow is created in the `ripPDF` function. Inside this function an object of size 0xadf8 is allocated. ``` 8175f06: c7 04 24 f8 ad 00 00 movl $0xadf8,(%esp) 8175f0d: 89 85 d8 f9 ff ff mov %eax,-0x628(%ebp) ; size 8175f13: 8d 83 dd f1 49 ff lea -0xb60e23(%ebx),%eax ; "RENDER" 8175f19: 89 44 24 04 mov %eax,0x4(%esp) 8175f1d: e8 4e b6 02 00 call 81a1570 <icnMalloc> 8175f22: 85 c0 test %eax,%eax 8175f24: 89 c7 mov %eax,%edi 8175f26: 0f 84 be 03 00 00 je 81762ea <ripPDF+0x40a> ``` For every single text item inside the document that uses the `showTextOld` opcode, the showTextOld function is called. Inside this function the `addFontToStoredFonts` function will copy a pointer from the +4 field (+0xaa0c:4) into the +8 field (+0xaa0c:8) of the 0xadf8 sized object. ``` 817888c: 8b 45 e4 mov -0x1c(%ebp),%eax 817888f: 89 44 24 14 mov %eax,0x14(%esp) 8178893: 8b 8d ec fd ff ff mov -0x214(%ebp),%ecx 8178899: 89 4c 24 10 mov %ecx,0x10(%esp) 817889d: 8b 45 08 mov 0x8(%ebp),%eax ; 0xadf8 object 81788a0: 89 44 24 0c mov %eax,0xc(%esp) 81788a4: 8b 55 18 mov 0x18(%ebp),%edx 81788a7: 89 54 24 08 mov %edx,0x8(%esp) 81788ab: 8b 4d 0c mov 0xc(%ebp),%ecx 81788ae: 89 4c 24 04 mov %ecx,0x4(%esp) 81788b2: 8b 45 14 mov 0x14(%ebp),%eax 81788b5: 89 04 24 mov %eax,(%esp) 81788b8: e8 63 26 15 00 call 82caf20 <addFontToStoredFonts> \ 82cb0fa: 8b 45 14 mov 0x14(%ebp),%eax 82cb0fd: 8b 90 0c aa 00 00 mov 0xaa0c(%eax),%edx ; +0xaa0c 82cb103: 8b 45 1c mov 0x1c(%ebp),%eax 82cb106: 8b 4a 04 mov 0x4(%edx),%ecx ; +0xaa0c:4 to %ecx 82cb109: 89 81 d4 00 00 00 mov %eax,0xd4(%ecx) 82cb10f: 8b 02 mov (%edx),%eax 82cb111: 89 4a 08 mov %ecx,0x8(%edx) ; write to +0xaa0c:8 82cb114: 85 c0 test %eax,%eax 82cb116: 74 08 je 82cb120 <addFontToStoredFonts+0x200> ``` For each character, the tool will processor a character, convert it into a TextPath and then convert it into a polygon. After a polygon is completed, the tool will call `enumPolys` to fill each of the polygons. While calling `enumPolys` the application will execute the following code in `processText`. This code will take the product of the dword at 0x108(%esi) and the one at 0x10c(%esi) and store it in %edi at 0x821432d. Later this register will be passed as an argument to `icnMalloc` at 0x821434d which will allocate space that will later be written to. Due to a missing check that the product of these two values are not larger than 31-bits, the resulting product may wrap which will cause the allocation size to be smaller than expected. The buffer that's allocated will then be written to +0x108 (+0xaa0c:8:108) of the 0xadf8 object. These lengths will later be used as boundaries for rasterizing a polygon. ``` 8214fc5: c7 04 24 00 00 00 00 movl $0x0,(%esp) 8214fcc: 8b 55 08 mov 0x8(%ebp),%edx 8214fcf: 89 f1 mov %esi,%ecx 8214fd1: 8b 45 14 mov 0x14(%ebp),%eax 8214fd4: e8 f7 eb ff ff call 8213bd0 <processText> ; \ \ 8213c9d: 8b 40 08 mov 0x8(%eax),%eax 8213ca0: 85 f6 test %esi,%esi 8213ca2: 89 45 e0 mov %eax,-0x20(%ebp) ... 8214317: 6b 45 dc 54 imul $0x54,-0x24(%ebp),%eax 821431b: 8b 55 e0 mov -0x20(%ebp),%edx 821431e: 8d 34 10 lea (%eax,%edx,1),%esi 8214321: 8b 86 08 01 00 00 mov 0x108(%esi),%eax 8214327: 8b be 10 01 00 00 mov 0x110(%esi),%edi ; XXX: size > 16-bits 821432d: 0f af be 0c 01 00 00 imul 0x10c(%esi),%edi ; XXX: size > 16-bits 8214334: 85 c0 test %eax,%eax 8214336: 74 08 je 8214340 <processText+0x770> ... 8214340: 8d 83 3f 21 4a ff lea -0xb5dec1(%ebx),%eax 8214346: 89 44 24 04 mov %eax,0x4(%esp) ; XXX: allocation size 821434a: 89 3c 24 mov %edi,(%esp) 821434d: e8 1e d2 f8 ff call 81a1570 <icnMalloc> 8214352: 85 c0 test %eax,%eax 8214354: 89 86 08 01 00 00 mov %eax,0x108(%esi) ``` Later while filling a polygon, the tool will load these values into the floating point co-processor to perform some math. Afterwards, the instructions will store the results as integers into variables on the stack at -0x98(%ebp) and -0xa0(%ebp). The first Y index will also be stored in integer form at -0x14(%ebp) and within the %esi register. ``` 82b0fff: d9 07 flds (%edi) 82b1001: d9 95 5c ff ff ff fsts -0xa4(%ebp) ; X 82b1007: d9 47 10 flds 0x10(%edi) 82b100a: d9 7d f2 fnstcw -0xe(%ebp) ; fpcw 82b100d: d9 95 60 ff ff ff fsts -0xa0(%ebp) ; Y 82b1013: d9 c9 fxch %st(1) 82b1015: d8 83 28 2a 44 ff fadds -0xbbd5d8(%ebx) 82b101b: 0f b7 45 f2 movzwl -0xe(%ebp),%eax ; fpcw 82b101f: b4 0c mov $0xc,%ah 82b1021: 66 89 45 f0 mov %ax,-0x10(%ebp) 82b1025: d9 6d f0 fldcw -0x10(%ebp) 82b1028: db 5d ec fistpl -0x14(%ebp) ; start Y (integer) 82b102b: d9 6d f2 fldcw -0xe(%ebp) ; fpcw 82b102e: 8b 75 ec mov -0x14(%ebp),%esi ; start Y (integer) 82b1031: d9 6d f0 fldcw -0x10(%ebp) 82b1034: db 9d 68 ff ff ff fistpl -0x98(%ebp) ; X 82b103a: d9 6d f2 fldcw -0xe(%ebp) ; fpcw ``` Aftewards, the code will enter a loop that will iterate through using these values. Due to the only the product of these integers overflowing, the call to `drawPixel` will be called for every pixel inside the under-allocated buffer as defined by the integers stored in -0x38(%ebp) and -0xa4(%ebp). The `drawPixel` function will essentially wrap `setCharMapPixel` which actually performs the write.. ``` 82b10a2: 89 44 24 0c mov %eax,0xc(%esp) 82b10a6: 8b 55 c8 mov -0x38(%ebp),%edx ; XXX: Y larger than 16-bits 82b10a9: 89 54 24 08 mov %edx,0x8(%esp) 82b10ad: d9 85 5c ff ff ff flds -0xa4(%ebp) ; XXX: X larger than 16-bits 82b10b3: d9 6d f0 fldcw -0x10(%ebp) 82b10b6: db 5c 24 04 fistpl 0x4(%esp) ; X 82b10ba: d9 6d f2 fldcw -0xe(%ebp) 82b10bd: 8b 45 08 mov 0x8(%ebp),%eax 82b10c0: 89 04 24 mov %eax,(%esp) ; object 82b10c3: e8 18 d5 00 00 call 82be5e0 <drawPixel> ``` Within `setCharMapPixel` the application will check to see if the current values are within the correct bounds, and then later use these values to write a null byte relative to the buffer at +0xaa0c:8:108. Due to the buffer being undersized while the tool attempts to fill the rasterized polygon, a buffer overflow may occur. ``` 82becc6: 8b 55 08 mov 0x8(%ebp),%edx 82becc9: 8b 4d 10 mov 0x10(%ebp),%ecx ; XXX: y value larger than 16-bits 82beccc: 89 34 24 mov %esi,(%esp) 82beccf: 8b 75 0c mov 0xc(%ebp),%esi ; XXX: x value larger than 16-bits 82becd2: 89 7c 24 04 mov %edi,0x4(%esp) 82becd6: 8b 82 0c aa 00 00 mov 0xaa0c(%edx),%eax ; XXX: pointer to object (+0xaa0c) 82becdc: 85 c9 test %ecx,%ecx 82becde: 8b 78 08 mov 0x8(%eax),%edi ; XXX: pointer to object (+0xaa0c:8) 82bece1: 0f b7 82 1c aa 00 00 movzwl 0xaa1c(%edx),%eax 82bece8: 78 2b js 82bed15 <setCharMapPixel+0x55> 82becea: 0f b7 c0 movzwl %ax,%eax ... 82becf0: 01 f8 add %edi,%eax ; XXX: base ... 82bed08: 0f af ca imul %edx,%ecx 82bed0b: 03 b0 08 01 00 00 add 0x108(%eax),%esi ; XXX: under-allocated buffer 82bed11: c6 04 0e 00 movb $0x0,(%esi,%ecx,1) ; XXX: write \x00 into buffer ``` ### Crash Information ``` $ gdb --quiet --args /opt/MarkLogic/converters/cvtpdf/convert ~/config/ Reading symbols from /opt/MarkLogic/Converters/cvtpdf/convert...done. (gdb) r Starting program: /opt/MarkLogic/Converters/cvtpdf/convert /home/user/config/ [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". 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... Analysing '/home/user/poc.pdf' Pages 1 to 2 Processing page 1 Catchpoint 4 (signal SIGSEGV), 0x082bed11 in setCharMapPixel () (gdb) bt 10 #0 0x082bed11 in setCharMapPixel () #1 0x082be68e in drawPixel () #2 0x082b10c8 in rendFillPoly () #3 0x08176fd5 in fillPoly () #4 0x082154c9 in enumPolys () #5 0x082cb837 in convertTextPathToPolys () #6 0x0817b351 in convertPathToPolys () #7 0x082cc5e1 in ProcessCharacter () #8 0x08179993 in showTextOld () #9 0x08179b39 in showText () #10 0x08183fb2 in processTextItem () #11 0x0818497d in icnProcessDisplayListX () #12 0x081856c0 in icnProcessDisplayList () #13 0x0818605d in icnRenderPage () #14 0x0817635d in ripPDF () #15 0x0817576e in renderZone () (More stack frames follow...) (gdb) h -=[registers]=- [eax: 0xf7237e40] [ebx: 0x08f57000] [ecx: 0xfffdaab0] [edx: 0x000269c2] [esi: 0x9f23a8e9] [edi: 0xf7237e40] [esp: 0xfffbe820] [ebp: 0xfffbe828] [eflags: NZ SF OF NC ND NI] -=[stack]=- fffbe820 | 0001a858 098ddfc0 fffbe858 082be68e | X.......X.....+. fffbe830 | 098ddfc0 000238e1 0001a858 fffbeb10 | .....8..X....... fffbe840 | 00000010 57fe85a8 f7200040 08f57000 | .......W@. ..p.. fffbe850 | 000238e2 f7236628 fffbe958 082b10c8 | .8..(f#.X.....+. -=[disassembly]=- => 0x82bed11 <setCharMapPixel+81>: movb $0x0,(%esi,%ecx,1) 0x82bed15 <setCharMapPixel+85>: mov (%esp),%esi 0x82bed18 <setCharMapPixel+88>: mov 0x4(%esp),%edi 0x82bed1c <setCharMapPixel+92>: mov %ebp,%esp 0x82bed1e <setCharMapPixel+94>: pop %ebp 0x82bed1f <setCharMapPixel+95>: ret ``` ### Timeline * 2016-10-10 - Vendor Disclosure * 2017-02-27 - Public Release ### CREDIT * Discovered by Marcin Noga of Cisco Talos.
idSSV:96552
last seen2017-11-19
modified2017-09-20
published2017-09-20
reporterRoot
titleIceni Argus PDF TextToPolys Rasterization Code Execution Vulnerability(CVE-2016-8389)

Talos

idTALOS-2016-0214
last seen2019-05-29
published2017-02-27
reporterTalos Intelligence
sourcehttp://www.talosintelligence.com/vulnerability_reports/TALOS-2016-0214
titleIceni Argus PDF TextToPolys Rasterization Code Execution Vulnerability