QXlsx
QXlsx copied to clipboard
Crashes during parsing of malformed XLSX files
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)
Dear @retpoline
Can you show me some example code?
@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.
I made a repository for testing. https://github.com/JayTwoLab/QXlsx-issue-184
Can you make code for testing?
Hi I faced the same issue crashed with cell which is 0x0, does any func can checkout is it a null cell? thanks!
- 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.