QXlsx icon indicating copy to clipboard operation
QXlsx copied to clipboard

Crashes during parsing of malformed XLSX files

Open retpoline opened this issue 4 years ago • 5 comments

Hi,

During fuzz testing of QXlsx library there were a couple crashes discovered in parsing XLSX files. The example HelloWorld binary was slightly modified to parse arbitrary files (instead of test.xlsx) and used for such testing. The crashes appears to occur in libz.so actually, but the library appears to no longer be maintained. QXlsx may be able to fixed before they reach the zlib library with additional hardening / sanity checks in the QXlsx code.

Although these malformed files only crash the program, they could potentially be crafted further into security issues where a malformed XLSX file would be able compromise the process's memory through memory corruption, so hardening the code to prevent these kinds of bugs would be great.

You can download the crashing files in a zip from Ufile to to debug and understand where the code is crashing.

Here's a couple crash logs for reference as well.

crash-1.log

cmdline ['QXlsx/build/HelloWorld', 'repro1.xlsx'] exited with invalid memory access (SIGSEGV)

[Repro]

-> QXlsx/build/HelloWorld repro1.xlsx

Reading symbols from QXlsx/build/HelloWorld...
(No debugging symbols found in QXlsx/build/HelloWorld)

Starting program: QXlsx/build/HelloWorld repro1.xlsx
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
QZip: Z_DATA_ERROR: Input data is corrupted

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6e45e66 in ?? () from /lib/x86_64-linux-gnu/libz.so.1
#0  0x00007ffff6e45e66 in ?? () from /lib/x86_64-linux-gnu/libz.so.1
#1  0x00007ffff6e470be in inflate () from /lib/x86_64-linux-gnu/libz.so.1
#2  0x00007ffff7c7c63a in QZipReader::fileData(QString const&) const ()
   from /lib/x86_64-linux-gnu/libQt5Gui.so.5
#3  0x0000555555616365 in QXlsx::ZipReader::fileData(QString const&) const ()
#4  0x000055555559d8b3 in QXlsx::DocumentPrivate::loadPackage(QIODevice*) ()
#5  0x00005555555a2b72 in QXlsx::Document::Document(QString const&, QObject*)
    ()
#6  0x00005555556169ec in main ()

rax            0x0                 0
rbx            0x3a                58
rcx            0x55555569a85d      93824993568861
rdx            0x0                 0
rsi            0xb                 11
rdi            0x7fffffffdfb0      140737488347056
rbp            0x55555569a87b      0x55555569a87b
rsp            0x7fffffffde68      0x7fffffffde68
r8             0x55555569a87e      93824993568894
r9             0x1                 1
r10            0x555555690718      93824993527576
r11            0x5555556901c0      93824993526208
r12            0x55555569a85a      93824993568858
r13            0x555555690f98      93824993529752
r14            0x7ffff4044000      140737287307264
r15            0x21                33
rip            0x7ffff6e45e66      0x7ffff6e45e66
eflags         0x10293             [ CF AF SF IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0

'exploitable' version 1.32
Linux ubuntu 5.4.0-48-generic #52-Ubuntu SMP Thu Sep 10 10:58:49 UTC 2020 x86_64
Signal si_signo: 11 Signal si_addr: 140737287307265
Nearby code:
/usr/local/lib/python3.8/dist-packages/exploitable-1.32-py3.8.egg/exploitable/exploitable.py:168: UserWarning: No function contains specified address.
  warnings.warn(str(e))
  
Stack trace:
#  0 None at 0x7ffff6e45e66 in /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
#  1 inflate at 0x7ffff6e470be in /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
#  2 QZipReader::fileData(QString const&) const at 0x7ffff7c7c63a in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.12.8
#  3 QXlsx::ZipReader::fileData(QString const&) const at 0x555555616365 in QXlsx/build/HelloWorld
#  4 QXlsx::DocumentPrivate::loadPackage(QIODevice*) at 0x55555559d8b3 in QXlsx/build/HelloWorld
#  5 QXlsx::Document::Document(QString const&, QObject*) at 0x5555555a2b72 in QXlsx/build/HelloWorld
#  6 main at 0x5555556169ec in QXlsx/build/HelloWorld

Faulting frame: #  0 None at 0x7ffff6e45e66 in /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
Description: Access violation on source operand
Short description: SourceAv (19/22)
Hash: 03d458a8fc5868eb6e5c80c3483f5f7a.968bc0ba105f4304689a6e7da4ffbc74
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 (21/22)

crash-2.log

cmdline ['QXlsx/build/HelloWorld', 'repro2.xlsx'] exited with invalid memory access (SIGSEGV)

[Repro]

-> QXlsx/build/HelloWorld repro2.xlsx 

Reading symbols from QXlsx/build/HelloWorld...
(No debugging symbols found in QXlsx/build/HelloWorld)

Starting program: QXlsx/build/HelloWorld repro2.xlsx
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
QZip: Unsupported compression method 18240 is needed to extract the data.
"Premature end of document."
QZip: Z_DATA_ERROR: Input data is corrupted
Error when read style file:  "Opening and ending tag mismatch."

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6e462c0 in ?? () from /lib/x86_64-linux-gnu/libz.so.1
#0  0x00007ffff6e462c0 in ?? () from /lib/x86_64-linux-gnu/libz.so.1
#1  0x00007ffff6e470be in inflate () from /lib/x86_64-linux-gnu/libz.so.1
#2  0x00007ffff7c7c63a in QZipReader::fileData(QString const&) const ()
   from /lib/x86_64-linux-gnu/libQt5Gui.so.5
#3  0x0000555555616365 in QXlsx::ZipReader::fileData(QString const&) const ()
#4  0x000055555559d8b3 in QXlsx::DocumentPrivate::loadPackage(QIODevice*) ()
#5  0x00005555555a2b72 in QXlsx::Document::Document(QString const&, QObject*)
    ()
#6  0x00005555556169ec in main ()

rax            0x0                 0
rbx            0x0                 0
rcx            0x10                16
rdx            0x3                 3
rsi            0xc                 12
rdi            0x7fffffffdfb0      140737488347056
rbp            0x3                 0x3
rsp            0x7fffffffde68      0x7fffffffde68
r8             0x55555569a9bd      93824993569213
r9             0x1                 1
r10            0x555555690258      93824993526360
r11            0x55555568fd00      93824993524992
r12            0x55555569a999      93824993569177
r13            0x555555690ad8      93824993528536
r14            0x7ffff4044000      140737287307264
r15            0x21                33
rip            0x7ffff6e462c0      0x7ffff6e462c0
eflags         0x10293             [ CF AF SF IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0

'exploitable' version 1.32
Linux ubuntu 5.4.0-48-generic #52-Ubuntu SMP Thu Sep 10 10:58:49 UTC 2020 x86_64
Signal si_signo: 11 Signal si_addr: 140737287307265
Nearby code:
/usr/local/lib/python3.8/dist-packages/exploitable-1.32-py3.8.egg/exploitable/exploitable.py:168: UserWarning: No function contains specified address.
  warnings.warn(str(e))
  
Stack trace:
#  0 None at 0x7ffff6e462c0 in /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
#  1 inflate at 0x7ffff6e470be in /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
#  2 QZipReader::fileData(QString const&) const at 0x7ffff7c7c63a in /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5.12.8
#  3 QXlsx::ZipReader::fileData(QString const&) const at 0x555555616365 in QXlsx/build/HelloWorld
#  4 QXlsx::DocumentPrivate::loadPackage(QIODevice*) at 0x55555559d8b3 in QXlsx/build/HelloWorld
#  5 QXlsx::Document::Document(QString const&, QObject*) at 0x5555555a2b72 in QXlsx/build/HelloWorld
#  6 main at 0x5555556169ec in QXlsx/build/HelloWorld

Faulting frame: #  0 None at 0x7ffff6e462c0 in /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
Description: Access violation on source operand
Short description: SourceAv (19/22)
Hash: cd322d8afaff15fdac6bce88240d1465.6a20a45ea4845db0016d4f1b271ac0f4
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 (21/22)

retpoline avatar Sep 15 '21 17:09 retpoline

Dear @retpoline

Can you show me some example code?

j2doll avatar Jan 04 '23 06:01 j2doll

@j2doll example code for the crashing the parser as show above in the debug session?

It was attached long ago at the Ufile URL, but I'll drop it here directly now.

repro1.zip repro2.zip

retpoline avatar Jan 07 '23 17:01 retpoline

I made a repository for testing. https://github.com/JayTwoLab/QXlsx-issue-184

Can you make code for testing?

j2doll avatar Jan 12 '23 09:01 j2doll

Hi I faced the same issue crashed with cell which is 0x0, does any func can checkout is it a null cell? thanks!

juneleung avatar Apr 26 '23 04:04 juneleung

  • It's clear that the repro1.xlsx file is corrupted.
7-Zip 22.01 (x64) : Copyright (c) 1999-2022 Igor Pavlov : 2022-07-15

Scanning the drive for archives:
1 file, 5657 bytes (6 KiB)

Testing archive: C:\Users\WJJ\Downloads\repro1.xlsx
--
Path = C:\Users\WJJ\Downloads\repro1.xlsx
Type = zip
Physical Size = 5657

T xl\worksheets\sheet1.xml
T xl\workbook.xml
ERROR: Data Error : xl\workbook.xml
T xl\_rels\workbook.xml.rels
T docProps\app.xml
ERROR: Data Error : docProps\app.xml
T docProps\core.xml
ERROR: Data Error : docProps\core.xml
T xl\sharedStrings.xml
T xl\calcChain.xml
ERROR: CRC Failed : xl\calcChain.xml
T xl\styles.xml
T xl\theme\theme1.xml
ERROR: Headers Error : xl\theme\theme1.xml
T _rels\.rels
ERROR: Data Error : _rels\.rels
T [Content_Types].xml
ERROR: Headers Error : [Content_Types].xml

Sub items Errors: 7

Archives with Errors: 1

Sub items Errors: 7
  • Running the test example with the latest QXlsx source code gives the following results:
./test
QZip: Z_DATA_ERROR: Input data is corrupted
QZip: Z_DATA_ERROR: Input data is corrupted
QZip: Unsupported compression method 21408 is needed to extract the data.
"Premature end of document."
QZip: Unsupported compression method 8256 is needed to extract the data.

j2doll avatar May 08 '23 00:05 j2doll