Talos Vulnerability Report


libxls xls_getfcell Code Execution Vulnerability

November 15, 2017
CVE Number



An exploitable stack based buffer overflow vulnerability exists in the xls_getfcell function of libxls 1.3.4. A specially crafted XLS file can cause a memory corruption resulting in remote code execution. An attacker can send malicious XLS file to trigger this vulnerability.

Tested Versions

libxls 1.3.4

Product URLs


CVSSv3 Score

8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H


CWE-121: Stack-based Buffer Overflow


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 of the Microsoft R programming language. A stack based buffer overflow is present in the xls_getfcell function. Let's take a look at the vulnerable code:

Line 377    char*  xls_getfcell(xlsWorkBook* pWB,struct st_cell_data* cell)
Line 378    {
Line 379        struct st_xf_data*  xf;
Line 380        char ret[10240];
Line 381        
Line 382        (...)   
Line 383        //LABELSST
Line 384        switch (cell->id)
Line 385        {
Line 386        case 0x0FD:
Line 387            sprintf(ret,"%s",pWB->sst.string[cell->l].str);
Line 388            break;  

As the comment at line 383 states, this fragment of code is responsible for parsing LabelSst cells.

According to the definition in the 2.4.149 LabelSst in the MS-XLS 6.0 documentation :

> The LabelSst record specifies a cell that contains a string.

> cell (6 bytes): A Cell structure that specifies the cell containing the string from the shared string table.
> isst (4 bytes): An unsigned integer that specifies the zero-based index of an element in the array of XLUnicodeRichExtendedString structure in the rgb field of the SST record in this Workbook Stream ABNF that specifies 
                      the string contained in the cell. MUST be greater than or equal to zero and less than the number of elements in the rgb field of the SST record.

The cell which causes an overflow in our PoC is located at offset : 0x11957 Its values look as follows:

p/x *cell
$2 = {id = 0xfd, row = 0x0, col = 0x0, xf = 0xf, d = 0x0, l = 0xf9, str = 0x6100000000000000, ishiden = 0x0, width = 0x0, colspan = 0x0, rowspan = 0x0}

Based on the cell's isst field which in code is represented as the l field, the XLUnicodeRichExtendedString is located in the SST record. We see that operation performed at line 387 is a classic stack based buffer overflow, because as we can see ret array has fixed size 10240, where string coming from XLUnicodeRichExtendedString SST record can exceed that size and cause an overflow.

(rr) p pWB->sst.string[0xf9]
$3 = {str = 0x143fd40 "prueba de exportaci\363n prueba de exportaci\363nprueba de exportaci\363nprueba de exportaci\363nprueba de exportaci\363nprueba de 
exportaci\363nprueba de exportaci\363nprueba de exportaci\363nprueba de exportaci\363nprueba de "...}

Crash Information

Reading symbols from ./xls2csv...done.
(gdb) r
Starting program: /home/icewall/bugs/libxls-0.2.0/build/bin/xls2csv ./crashes/16ae3756c8a7d987860ec5abe5fa5600
Program received signal SIGSEGV, Segmentation fault.
__strcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:241
241     ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: No such file or directory.
(gdb) bt 20
#0  __strcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:241
#1  0x00007ffff7bce9e2 in xls_getfcell (pWB=0x603010, cell=0x62a1d9) at xlstool.c:389
#2  0x2065642061626575 in ?? ()
#3  0x636174726f707865 in ?? ()
#4  0x62657572706ef369 in ?? ()
#5  0x7078652065642061 in ?? ()
#6  0x6ef369636174726f in ?? ()
#7  0x6420616265757270 in ?? ()
#8  0x74726f7078652065 in ?? ()
#9  0x7572706ef3696361 in ?? ()
#10 0x6520656420616265 in ?? ()
#11 0x69636174726f7078 in ?? ()
#12 0x6162657572706ef3 in ?? ()
#13 0x6f70786520656420 in ?? ()
#14 0x706ef36963617472 in ?? ()
#15 0x6564206162657572 in ?? ()
#16 0x6174726f70786520 in ?? ()
#17 0x657572706ef36963 in ?? ()
#18 0x7865206564206162 in ?? ()
#19 0xf369636174726f70 in ?? ()
(More stack frames follow...)


2017-08-29 - Vendor Disclosure
2017-11-15 - Public Release


Discovered by Marcin 'Icewall' Noga of Cisco Talos.