CVE-2017-2806
An exploitable arbitrary read exists in the XLS parsing of the Lexmark Perspective Document Filters conversion functionality. A crafted XLS document can lead to a arbitrary read resulting in memory disclosure. The vulnerability was confirmed on versions 11.3.0.2228 and 11.3.0.2400
Lexmark Perceptive Document Filters 11.3.0.2228 Lexmark Perceptive Document Filters 11.3.0.2400
4.3 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N
CWE-125 - Out-of-bounds Read
This vulnerability is present in the Lexmark Document filter parsing which is used for big data, eDiscovery, DLP, email archival, content management, business intelligence and intelligent capture services. This product is mainly used by MarkLogic for document conversions as part of their web based document search and rendering. It can convert common formats such as Microsoft’s document formats into more useable and easily viewed formats. There is a vulnerability in the parsing and conversion of XLS documents. A specially crafted XLS file can lead to an arbitrary read and ultimately memory disclosure.
Let’s investigate this vulnerability. After the Lexmark library attempts to read metadata from the malicious file, we see the following state:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff3818fdb in intermediate::Office::extract4BytesFromStringIt(char const**) () from ./libISYSreadershd.so
(gdb) peda_active
gdb-peda$ context
[----------------------------------registers-----------------------------------]
RAX: 0x3133701
RBX: 0x6ac3d0 --> 0x7ffff3f21210 --> 0x7ffff385c3f0 (<intermediate::Office::ShapeHLink::~ShapeHLink()>: mov QWORD PTR [rsp-0x8],rbp)
RCX: 0x3133700
RDX: 0x3133702
RSI: 0xa80000
RDI: 0x7ffffffecfd8 --> 0x3133700
RBP: 0x6ac458 --> 0xaaefbeadde000002
RSP: 0x7ffffffecfa8 --> 0x7ffff38310df (cdqe)
RIP: 0x7ffff3818fdb (movzx r8d,BYTE PTR [rcx])
R8 : 0x9c
R9 : 0x7ffff69417b8 --> 0x6b7b80 --> 0x0
R10: 0x6c00000067 ('g')
R11: 0x7ffff670a550 --> 0xfffcb240fffcabbe
R12: 0xffad
R13: 0x696fc0 --> 0x7ffff3f0b4f0 --> 0x7ffff35fb9c0 (<reader::excel97_2003::Sheet::~Sheet()>: mov QWORD PTR [rsp-0x10],rbp)
R14: 0x6ac3d0 --> 0x7ffff3f21210 --> 0x7ffff385c3f0 (<intermediate::Office::ShapeHLink::~ShapeHLink()>: mov QWORD PTR [rsp-0x8],rbp)
R15: 0x7ffff79c23f8 --> 0x0
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x7ffff3818fd0 <intermediate::Office::extract4BytesFromStringIt(char const**)>: mov rcx,QWORD PTR [rdi]
0x7ffff3818fd3: lea rax,[rcx+0x1]
0x7ffff3818fd7: lea rdx,[rcx+0x2]
=> 0x7ffff3818fdb: movzx r8d,BYTE PTR [rcx]
0x7ffff3818fdf: mov QWORD PTR [rdi],rax
0x7ffff3818fe2: movzx eax,BYTE PTR [rcx+0x1]
0x7ffff3818fe6: mov QWORD PTR [rdi],rdx
0x7ffff3818fe9: lea rdx,[rcx+0x3]
[------------------------------------stack-------------------------------------]
0000| 0x7ffffffecfa8 --> 0x7ffff38310df (cdqe)
0008| 0x7ffffffecfb0 --> 0x7ffffffecff0 --> 0x6a9e00 --> 0x7ffff3f09010 --> 0x7ffff352edf0 (<common::IRenderable::SetZIndex(int)>: mov DWORD PTR [rdi+0x8],esi)
0016| 0x7ffffffecfb8 --> 0x20 (' ')
0024| 0x7ffffffecfc0 --> 0x20 (' ')
0032| 0x7ffffffecfc8 --> 0x6ac3e8 --> 0x7ffff79c23f8 --> 0x0
0040| 0x7ffffffecfd0 --> 0x696fc0 --> 0x7ffff3f0b4f0 --> 0x7ffff35fb9c0 (<reader::excel97_2003::Sheet::~Sheet()>: mov QWORD PTR [rsp-0x10],rbp)
0048| 0x7ffffffecfd8 --> 0x3133700
0056| 0x7ffffffecfe0 --> 0x6a9e00 --> 0x7ffff3f09010 --> 0x7ffff352edf0 (<common::IRenderable::SetZIndex(int)>: mov DWORD PTR [rdi+0x8],esi)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
gdb-peda$ bt
#0 0x00007ffff3818fdb in intermediate::Office::extract4BytesFromStringIt(char const**) () from ./libISYSreadershd.so
#1 0x00007ffff38310df in intermediate::Office::ShapeHLink::ShapeHLink(std::string const&) () from ./libISYSreadershd.so
#2 0x00007ffff35f0497 in reader::excel97_2003::Sheet::parseImageObject(intermediate::common::ExcelDrawing*, reader::escher::MsofbtSpContainer*) () from ./libISYSreadershd.so
#3 0x00007ffff35f1224 in reader::excel97_2003::Sheet::parseDrawingObjects(intermediate::common::ExcelDrawing*, reader::escher::MsofbtSpContainer*, std::_List_const_iterator<reader::excel97_2003::BiffTxo*>*, std::_List_const_iterator<reader::excel97_2003::BiffTxo*>) () from ./libISYSreadershd.so
#4 0x00007ffff35f141e in reader::excel97_2003::Sheet::parseObject(intermediate::common::ExcelDrawing*, reader::escher::IMsoObject*, std::_List_const_iterator<reader::excel97_2003::BiffTxo*>*, std::_List_const_iterator<reader::excel97_2003::BiffTxo*>) () from ./libISYSreadershd.so
#5 0x00007ffff35f2c7c in reader::excel97_2003::Sheet::Commit(ISYS_NS::CDataReader&) () from ./libISYSreadershd.so
#6 0x00007ffff357ff52 in reader::excel97_2003::Workbook::Workbook(ISYS_NS::CStream*, IStorage*, wchar_t const*, bool) () from ./libISYSreadershd.so
#7 0x00007ffff399adca in ISYS_NS::LibraryHD::CDocument::openExcel(ISYS_NS::CStream*, IStorage*, bool) () from ./libISYSreadershd.so
#8 0x00007ffff399c2cf in ISYS_NS::LibraryHD::CDocument::open(IGR_Stream*, int, wchar_t const*) () from ./libISYSreadershd.so
#9 0x00007ffff3994d4a in ISYS_NS::LibraryHD::IGR_HDAPI_Open(IGR_Stream*, int, wchar_t const*, void**, wchar_t*) () from ./libISYSreadershd.so
#10 0x00007ffff61a22cb in ?? () from ./libISYSreaders.so
#11 0x00007ffff61a6307 in ?? () from ./libISYSreaders.so
#12 0x00007ffff7bcdb1b in IGR_Open_Stream_Ex () from ./libISYS11df.so
#13 0x00000000004091e0 in processStream(IGR_Stream*, long long&, ToXHTML&, std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >&) ()
#14 0x000000000040ab7b in processFile(std::string, std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >&) ()
#15 0x000000000040b7a0 in main ()
#16 0x00007ffff65a4f45 in __libc_start_main (main=0x40b0b0 <main>, argc=0x2, argv=0x7fffffffdf58, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdf48)
at libc-start.c:287
#17 0x00000000004089e9 in _start ()
As we can see in the function extract4BytesFromStringIt
an access violation occurred during a read from a very specific address rcx == 0x3133700
. The address from where these 4 bytes are extracted are fully
controlled by attacker. Let’s look at where this value comes from. We return to the place where rcx
was set:
gdb-peda$
[----------------------------------registers-----------------------------------]
RAX: 0x2a8729c
RBX: 0x6ac3d0 --> 0x7ffff3f21210 --> 0x7ffff385c3f0 (<intermediate::Office::ShapeHLink::~ShapeHLink()>: mov QWORD PTR [rsp-0x8],rbp)
RCX: 0x6ac464 --> 0xd3d3d3d3d3d3d3d3
RDX: 0x2000000
RSI: 0xa80000
RDI: 0x7ffffffecfd8 --> 0x6ac464 --> 0xd3d3d3d3d3d3d3d3
RBP: 0x6ac458 --> 0xaaefbeadde000002
RSP: 0x7ffffffecfb0 --> 0x7ffffffecff0 --> 0x6a9e00 --> 0x7ffff3f09010 --> 0x7ffff352edf0 (<common::IRenderable::SetZIndex(int)>: mov DWORD PTR [rdi+0x8],esi)
RIP: 0x7ffff383125f (add QWORD PTR [rsp+0x28],rax)
R8 : 0x9c
R9 : 0x7ffff69417b8 --> 0x6b7b80 --> 0x0
R10: 0x6c00000067 ('g')
R11: 0x7ffff670a550 --> 0xfffcb240fffcabbe
R12: 0xffad
R13: 0x696fc0 --> 0x7ffff3f0b4f0 --> 0x7ffff35fb9c0 (<reader::excel97_2003::Sheet::~Sheet()>: mov QWORD PTR [rsp-0x10],rbp)
R14: 0x6ac3d0 --> 0x7ffff3f21210 --> 0x7ffff385c3f0 (<intermediate::Office::ShapeHLink::~ShapeHLink()>: mov QWORD PTR [rsp-0x8],rbp)
R15: 0x7ffff79c23f8 --> 0x0
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x7ffff3831253: lea rdi,[rsp+0x28]
0x7ffff3831258: call 0x7ffff34f2178 <intermediate::Office::extract4BytesFromStringIt(char const**)@plt>
0x7ffff383125d: cdqe
=> 0x7ffff383125f: add QWORD PTR [rsp+0x28],rax
0x7ffff3831264: jmp 0x7ffff38310c6
0x7ffff3831269: lea rdi,[rsp+0x28]
0x7ffff383126e: call 0x7ffff34f2178 <intermediate::Office::extract4BytesFromStringIt(char const**)@plt>
0x7ffff3831273: mov rbx,QWORD PTR [rsp+0x28]
gdb-peda$ telescope $rsp+0x28 1
0000| 0x7ffffffecfd8 --> 0x6ac464 --> 0xd3d3d3d3d3d3d3d3
gdb-peda$ ni
gdb-peda$ telescope $rsp+0x28 1
0000| 0x7ffffffecfd8 --> 0x3133700
looking in the file for value the 0x2a8729c
we can find it at offset 0x6D82. It points to data inside the complexData
field of the OfficeArtRGFOPTE
record type (described in section 2.3.1 of the Office Drawing Binary File Format. Looking at the constructor name we can easily guess that the object which the currently library was parsing is related with a hyperlink
. Indeed, it is wrongly parsing the Hyperlink Object
structure (defined in section 2.3.7.1 of the Office Common Data Types and Objects Structures:
The Hyperlink
object has, among others, 2 string fields, dispalyName
and targetFrameName
. Both fields have variable lengths. The Perceptive Filter library reads the read string length from the file without extra checks and adds it to displayName
pointer to find the location of targetFrameName
. This lack of value sanitization leads to an arbitrary memory read and can result in memory disclosure.
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x3133701
RBX: 0x6ac3d0 --> 0x7ffff3f21210 --> 0x7ffff385c3f0 (<intermediate::Office::ShapeHLink::~ShapeHLink()>: mov QWORD PTR [rsp-0x8],rbp)
RCX: 0x3133700
RDX: 0x3133702
RSI: 0xa80000
RDI: 0x7ffffffecfd8 --> 0x3133700
RBP: 0x6ac458 --> 0xaaefbeadde000002
RSP: 0x7ffffffecfa8 --> 0x7ffff38310df (cdqe)
RIP: 0x7ffff3818fdb (movzx r8d,BYTE PTR [rcx])
R8 : 0x9c
R9 : 0x7ffff69417b8 --> 0x6b7b80 --> 0x0
R10: 0x6c00000067 ('g')
R11: 0x7ffff670a550 --> 0xfffcb240fffcabbe
R12: 0xffad
R13: 0x696fc0 --> 0x7ffff3f0b4f0 --> 0x7ffff35fb9c0 (<reader::excel97_2003::Sheet::~Sheet()>: mov QWORD PTR [rsp-0x10],rbp)
R14: 0x6ac3d0 --> 0x7ffff3f21210 --> 0x7ffff385c3f0 (<intermediate::Office::ShapeHLink::~ShapeHLink()>: mov QWORD PTR [rsp-0x8],rbp)
R15: 0x7ffff79c23f8 --> 0x0
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x7ffff3818fd0 <intermediate::Office::extract4BytesFromStringIt(char const**)>: mov rcx,QWORD PTR [rdi]
0x7ffff3818fd3: lea rax,[rcx+0x1]
0x7ffff3818fd7: lea rdx,[rcx+0x2]
=> 0x7ffff3818fdb: movzx r8d,BYTE PTR [rcx]
0x7ffff3818fdf: mov QWORD PTR [rdi],rax
0x7ffff3818fe2: movzx eax,BYTE PTR [rcx+0x1]
0x7ffff3818fe6: mov QWORD PTR [rdi],rdx
0x7ffff3818fe9: lea rdx,[rcx+0x3]
[------------------------------------stack-------------------------------------]
0000| 0x7ffffffecfa8 --> 0x7ffff38310df (cdqe)
0008| 0x7ffffffecfb0 --> 0x7ffffffecff0 --> 0x6a9e00 --> 0x7ffff3f09010 --> 0x7ffff352edf0 (<common::IRenderable::SetZIndex(int)>: mov DWORD PTR [rdi+0x8],esi)
0016| 0x7ffffffecfb8 --> 0x20 (' ')
0024| 0x7ffffffecfc0 --> 0x20 (' ')
0032| 0x7ffffffecfc8 --> 0x6ac3e8 --> 0x7ffff79c23f8 --> 0x0
0040| 0x7ffffffecfd0 --> 0x696fc0 --> 0x7ffff3f0b4f0 --> 0x7ffff35fb9c0 (<reader::excel97_2003::Sheet::~Sheet()>: mov QWORD PTR [rsp-0x10],rbp)
0048| 0x7ffffffecfd8 --> 0x3133700
0056| 0x7ffffffecfe0 --> 0x6a9e00 --> 0x7ffff3f09010 --> 0x7ffff352edf0 (<common::IRenderable::SetZIndex(int)>: mov DWORD PTR [rdi+0x8],esi)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00007ffff3818fdb in intermediate::Office::extract4BytesFromStringIt(char const**) () from ./libISYSreadershd.so
gdb-peda$ exploitable -m
Warning: machine string printing is deprecated and may be removed in a future release.
EXCEPTION_FAULTING_ADDRESS:0x00000003133700
EXCEPTION_CODE:0xb
FAULTING_INSTRUCTION:movzx r8d,BYTE PTR [rcx]
MAJOR_HASH:435211badab532edaeeaf65b62cabc34
MINOR_HASH:dd8a6e134c95f47c9f18aac4b3c591c2
STACK_DEPTH:16
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreadershd.so!intermediate::Office::extract4BytesFromStringIt(char const**)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreadershd.so!intermediate::Office::ShapeHLink::ShapeHLink(std::string const&)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreadershd.so!reader::excel97_2003::Sheet::parseImageObject(intermediate::common::ExcelDrawing*, reader::escher::MsofbtSpContainer*)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreadershd.so!reader::excel97_2003::Sheet::parseDrawingObjects(intermediate::common::ExcelDrawing*, reader::escher::MsofbtSpContainer*, std::_List_const_iterator<reader::excel97_2003::BiffTxo*>*, std::_List_const_iterator<reader::excel97_2003::BiffTxo*>)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreadershd.so!reader::excel97_2003::Sheet::parseObject(intermediate::common::ExcelDrawing*, reader::escher::IMsoObject*, std::_List_const_iterator<reader::excel97_2003::BiffTxo*>*, std::_List_const_iterator<reader::excel97_2003::BiffTxo*>)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreadershd.so!reader::excel97_2003::Sheet::Commit(ISYS_NS::CDataReader&)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreadershd.so!reader::excel97_2003::Workbook::Workbook(ISYS_NS::CStream*, IStorage*, wchar_t const*, bool)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreadershd.so!ISYS_NS::LibraryHD::CDocument::openExcel(ISYS_NS::CStream*, IStorage*, bool)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreadershd.so!ISYS_NS::LibraryHD::CDocument::open(IGR_Stream*, int, wchar_t const*)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreadershd.so!ISYS_NS::LibraryHD::IGR_HDAPI_Open(IGR_Stream*, int, wchar_t const*, void**, wchar_t*)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreaders.so+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYSreaders.so+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/libISYS11df.so!IGR_Open_Stream_Ex+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/convert!processStream(IGR_Stream*, long long&, ToXHTML&, std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >&)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/convert!processFile(std::string, std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >&)+0x0
STACK_FRAME:/home/icewall/bugs/cvtisys_86/convert!main+0x0
INSTRUCTION_ADDRESS:0x007ffff3818fdb
INVOKING_STACK_FRAME:0
DESCRIPTION:Access violation on source operand
SHORT_DESCRIPTION:SourceAv (26/29)
OTHER_RULES:AccessViolation (28/29)
CLASSIFICATION:UNKNOWN
EXPLANATION:The target crashed on an access violation at an address matching the source operand of the current instruction. This likely indicates a read access violation.
Description: Access violation on source operand
Short description: SourceAv (26/29)
Hash: 435211badab532edaeeaf65b62cabc34.dd8a6e134c95f47c9f18aac4b3c591c2
Exploitability Classification: UNKNOWN
Explanation: The target crashed on an access violation at an address matching the source operand of the current instruction. This likely indicates a read access violation.
Other tags: AccessViolation (28/29)
2017-04-05 - Vendor Disclosure
2017-04-18 - Public Release
Discovered by Marcin ‘Icewall’ Noga of Cisco Talos.