Vulnerabilities > CVE-2017-12110 - Integer Overflow or Wraparound vulnerability in Libxls Project Libxls 1.4

047910
CVSS 6.8 - MEDIUM
Attack vector
NETWORK
Attack complexity
MEDIUM
Privileges required
NONE
Confidentiality impact
PARTIAL
Integrity impact
PARTIAL
Availability impact
PARTIAL
network
libxls-project
CWE-190
nessus

Summary

An exploitable integer overflow vulnerability exists in the xls_appendSST function of libxls 1.4.A specially crafted XLS file can cause memory corruption resulting in remote code execution.

Vulnerable Configurations

Part Description Count
Application
Libxls_Project
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.

Nessus

  • NASL familyDebian Local Security Checks
    NASL idDEBIAN_DSA-4173.NASL
    descriptionMarcin Noga discovered multiple vulnerabilities in readxl, a GNU R package to read Excel files (via the integrated libxls library), which could result in the execution of arbitrary code if a malformed spreadsheet is processed.
    last seen2020-06-01
    modified2020-06-02
    plugin id109065
    published2018-04-17
    reporterThis script is Copyright (C) 2018 and is owned by Tenable, Inc. or an Affiliate thereof.
    sourcehttps://www.tenable.com/plugins/nessus/109065
    titleDebian DSA-4173-1 : r-cran-readxl - security update
  • NASL familyGentoo Local Security Checks
    NASL idGENTOO_GLSA-202003-64.NASL
    descriptionThe remote host is affected by the vulnerability described in GLSA-202003-64 (libxls: Multiple vulnerabilities) Multiple vulnerabilities have been discovered in libxls. Please review the CVE identifiers referenced below for details. Impact : A remote attacker could entice a user to process a specially crafted Excel file using libxls, possibly resulting in execution of arbitrary code with the privileges of the process or a Denial of Service condition. Workaround : There is no known workaround at this time.
    last seen2020-04-04
    modified2020-03-31
    plugin id135019
    published2020-03-31
    reporterThis script is Copyright (C) 2020 and is owned by Tenable, Inc. or an Affiliate thereof.
    sourcehttps://www.tenable.com/plugins/nessus/135019
    titleGLSA-202003-64 : libxls: Multiple vulnerabilities

Seebug

bulletinFamilyexploit
description### Summary An exploitable integer overflow vulnerability exists in the xls_appendSST function of libxls 1.4. A specially crafted XLS file can cause memory corruption resulting in remote code execution. An attacker can send a malicious XLS file to trigger this vulnerability. ### Tested Versions libxls 1.4 readxl package 1.0.0 for R (tested using Microsoft R 4.3.1) ### Product URLs http://libxls.sourceforge.net/ ### 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-787: Out-of-bounds Write ### Details libxls is a C library supported on windows, mac, cygwin which can read Microsoft Excel File Format ( XLS ) files. The library is used by the readxl package that can be installed in the R programming language. Before we will discuss the location where the out-of-bounds write appears, first let's check code where space allocation for that array takes place: ``` Line 120 void xls_addSST(xlsWorkBook* pWB,SST* sst,DWORD size) Line 121 { Line 122 verbose("xls_addSST"); Line 123 Line 124 pWB->sst.continued=0; Line 125 pWB->sst.lastln=0; Line 126 pWB->sst.lastid=0; Line 127 pWB->sst.lastrt=0; Line 128 pWB->sst.lastsz=0; Line 129 Line 130 pWB->sst.count = sst->num; Line 131 pWB->sst.string =(struct str_sst_string *)calloc(pWB->sst.count, sizeof(struct str_sst_string)); Line 132 xls_appendSST(pWB,&sst->strings,size-8); Line 133 } ``` As you can see at `line 131` space for `pWB->sst.string` array is allocated based on the `pWB->sst.count` value. This value is obtained at `line 130` from `sst->num`. The `sst` structure passed as argument is fully controlled by attacker. By controlling the `sst` structure, we can force allocation for any size, for example 1. The malformed `SST` record is located at offset 0x088F: ``` 088Fh: FC 00 20 20 E7 01 00 00 00 00 00 00 0F 00 00 43 ü. ç..........C 089Fh: 69 73 63 6F 54 61 6C 6F 73 20 20 20 20 20 03 00 iscoTalos .. 08AFh: 00 53 37 38 03 00 00 53 37 39 03 00 00 53 37 36 .S78...S79...S76 08BFh: 04 00 00 53 31 30 33 04 00 00 53 31 30 32 03 00 ...S103...S102.. 08CFh: 00 53 37 37 03 00 00 53 37 34 03 00 00 53 37 35 .S77...S74...S75 08DFh: 03 00 00 53 32 39 03 00 00 53 32 38 03 00 00 53 ...S29...S28...S 08EFh: 32 37 03 00 00 53 37 33 03 00 00 53 32 32 03 00 27...S73...S22.. 08FFh: 00 . (...) ``` The `sst` strcture looks as follows in memory: ``` p *sst $2 = { num = 0x0, numofstr = 0x0, strings = 0xf } ``` The `num` field is at offset 0x897. With an `sst` structure where values are set like these above, the `pWB->sst.string` array will have space for just one element. Going further inside the `xls_appendSST` function. Each string entry in `sst->strings`, after optional conversion, will be assigned (its address exactly) to separate entry in `pWB->sst.string` array. These string entries look as follows: ``` [string_size](SHORT)[flags](BYTE)[string...] example: 0F 00 00 43 69 73 63 6F 54 61 6C 6F .......CiscoTalo 73 20 20 20 20 20 ``` We can observe this in the code below, where the `ret` variable at `line 235` containing a "decoded" string address is assigned to the `pWB->sst.string` array entry at `line 257`. Notice that for each string, `lastid` field value is increased being used as a index in `pWB->sst.string` array. ``` Line 135 void xls_appendSST(xlsWorkBook* pWB,BYTE* buf,DWORD size) Line 136 { Line 137 DWORD ln; // String character count Line 138 DWORD ofs; // Current offset in SST buffer Line 139 DWORD rt; // Count of rich text formatting runs Line 140 DWORD sz; // Size of asian phonetic settings block Line 141 BYTE flag; // String flags Line 142 BYTE* ret; (...) Line 163 else Line 164 { Line 165 ln=xlsShortVal(*(WORD_UA *)(buf+ofs)); Line 166 rt = 0; Line 167 sz = 0; Line 168 Line 169 ofs+=2; Line 170 } (...) Line 231 else Line 232 { Line 233 ln_toread = min((size-ofs), ln); Line 234 Line 235 ret = utf8_decode((buf+ofs), ln_toread, pWB->charset); Line 236 Line 237 ln -= ln_toread; Line 238 ofs +=ln_toread; Line 239 Line 240 if (xls_debug) { Line 241 printf("String8SST: %s(%u) \n",ret,ln); Line 242 } Line 243 } (...) Line 250 if ( (ln_toread > 0) Line 251 ||(!pWB->sst.continued) ) Line 252 { Line 253 // Concat string if it's a continue, or add string in table Line 254 if (!pWB->sst.continued) Line 255 { Line 256 pWB->sst.lastid++; Line 257 pWB->sst.string[pWB->sst.lastid-1].str=ret; Line 258 } ``` In our case, the attempt to assign a second string to that array will cause an out-of-bounds write, resulting in memory corruption and potential code execution. ### Crash Information ``` Microsoft R crash (96c.954): Access violation - code c0000005 (!!! second chance !!!) *** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Users\Icewall\Documents\R\win-library\3.4\readxl\libs\x64\readxl.dll - readxl!xls_appendSST+0xa4: 00000000`6534a974 4c890cc2 mov qword ptr [rdx+rax*8],r9 ds:00000000`30b49000=???????????????? 0:000> r rax=0000000000000002 rbx=000000000000001e rcx=0000000000000000 rdx=0000000030b48ff0 rsi=0000000031619f70 rdi=0000000000000000 rip=000000006534a974 rsp=000000000440ba00 rbp=0000000000000000 r8=0000000000000000 r9=0000000030b4eff0 r10=000000000000001b r11=0000000030b4eff0 r12=0000000000002018 r13=0000000000000000 r14=0000000000000003 r15=0000000000000003 iopl=0 nv up ei pl zr na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010244 readxl!xls_appendSST+0xa4: 00000000`6534a974 4c890cc2 mov qword ptr [rdx+rax*8],r9 ds:00000000`30b49000=???????????????? 0:000> kb 5 # RetAddr : Args to Child : Call Site 00 00000000`6534bdf9 : 00000000`31796ff0 00000000`31798fe8 00000000`3161bfb0 00000000`65349fe7 : readxl!xls_appendSST+0xa4 01 00000000`6534cc96 : 00000000`31619f70 00000000`00000006 00000000`00000000 00000000`0440bd68 : readxl!xls_parseWorkBook+0x3d9 02 00000000`6538025b : 00000000`0000003e 00000000`0440bc10 00000000`106f0788 00007ffe`155d9a00 : readxl!xls_open+0x136 03 00000000`65344d9d : 00000000`00000001 00000000`6cbfdb68 000cc587`59d3b80a 00000000`106f0788 : readxl!ZN11XlsWorkBookC1ERKSs+0x11b 04 00000000`65341efa : 00000000`00000000 00000000`0440be80 00000000`0440c700 00000000`6c87662c : readxl!Z10xls_sheetsSs+0x1d 0:000> lmv m readxl Browse full module list start end module name 00000000`65340000 00000000`6543f000 readxl (export symbols) C:\Users\Icewall\Documents\R\win-library\3.4\readxl\libs\x64\readxl.dll Loaded symbol image file: C:\Users\Icewall\Documents\R\win-library\3.4\readxl\libs\x64\readxl.dll Image path: C:\Users\Icewall\Documents\R\win-library\3.4\readxl\libs\x64\readxl.dll Image name: readxl.dll Browse all global symbols functions data Timestamp: Wed Aug 30 18:38:23 2017 (59A6E9FF) CheckSum: 001018F6 ImageSize: 000FF000 Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4 Linux version icewall@ubuntu:~/bugs/libxls-1.4.0/build/bin$ valgrind ./xls2csv test/poc.xls ==37508== Memcheck, a memory error detector ==37508== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==37508== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==37508== Command: ./xls2csv test/poc.xls ==37508== ==37508== Invalid write of size 8 ==37508== at 0x4E4207E: xls_appendSST (xls.c:257) ==37508== by 0x4E41D25: xls_addSST (xls.c:132) ==37508== by 0x4E43B12: xls_parseWorkBook (xls.c:781) ==37508== by 0x4E44F7B: xls_open (xls.c:1272) ==37508== by 0x400E80: main (xls2csv.c:108) ==37508== Address 0x54607d0 is 0 bytes after a block of size 0 alloc'd ==37508== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==37508== by 0x4E41CFD: xls_addSST (xls.c:131) ==37508== by 0x4E43B12: xls_parseWorkBook (xls.c:781) ==37508== by 0x4E44F7B: xls_open (xls.c:1272) ``` ### Timeline * 2017-10-25 - Vendor Disclosure * 2017-11-15 - Public Release
idSSV:96897
last seen2017-12-25
modified2017-11-29
published2017-11-29
reporterRoot
titlelibxls xls_appendSST Code Execution Vulnerability(CVE-2017-12110)

Talos

idTALOS-2017-0462
last seen2019-05-29
published2017-11-15
reporterTalos Intelligence
sourcehttp://www.talosintelligence.com/vulnerability_reports/TALOS-2017-0462
titlelibxls xls_appendSST Code Execution Vulnerability