ckolivas / lrzip

Long Range Zip
http://lrzip.kolivas.org
GNU General Public License v2.0
618 stars 76 forks source link

invalid memory read in lzo1x_decompress, which is different from CVE-2017-8845 #108

Closed N3vv closed 5 years ago

N3vv commented 5 years ago

On lrzip 0.631, there is an invalid memory read in lzo1x_decompress, which is different from CVE-2017-8845.

POC is here: POC.zip

nevv@ubuntu:~/Desktop/lrzip-master$ ./lrzip -d -o 1234 -f ../id\:000002\,sig\:06\,src\:000008\,op\:flip2\,pos\:35
Output filename is: 1234
Warning, inadequate free space detected, but attempting to decompress due to -f option being used.
Decompressing...
ASAN:SIGSEGV
=================================================================
==30767==ERROR: AddressSanitizer: SEGV on unknown address 0x603000010000 (pc 0x7f9ef7f49144 bp 0x62100001cd20 sp 0x7f9ef43fed50 T1)
    #0 0x7f9ef7f49143 in lzo1x_decompress (/lib/x86_64-linux-gnu/liblzo2.so.2+0x13143)
    #1 0x43f231 in lzo_decompress_buf /home/nevv/Desktop/lrzip-master/stream.c:588
    #2 0x43f231 in ucompthread /home/nevv/Desktop/lrzip-master/stream.c:1525
    #3 0x7f9ef78f66b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)
    #4 0x7f9ef6d8b41c in clone (/lib/x86_64-linux-gnu/libc.so.6+0x10741c)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 lzo1x_decompress
Thread T1 created by T0 here:
    #0 0x7f9ef818e253 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x36253)
    #1 0x43febc in create_pthread /home/nevv/Desktop/lrzip-master/stream.c:133

==30767==ABORTING
N3vv commented 5 years ago

And here is the debug result of executing lrzip without the -asan option(The version of LZO library is 2.10):

pwndbg> file ./lrzip
Reading symbols from ./lrzip...done.
pwndbg> set args -d -f ../id:000002,sig:06,src:000008,op:flip2,pos:35 
pwndbg> r
Starting program: /home/nevv/Desktop/lrzip-master (copy)/lrzip -d -f ../id:000002,sig:06,src:000008,op:flip2,pos:35 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Output filename is: ../id:000002,sig:06,src:000008,op:flip2,pos:35
Warning, inadequate free space detected, but attempting to decompress due to -f option being used.
Decompressing...
[New Thread 0x7ffff6902700 (LWP 30631)]

Thread 2 "lrzip" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff6902700 (LWP 30631)]
0x00007ffff7bc8144 in lzo1x_decompress () from /lib/x86_64-linux-gnu/liblzo2.so.2
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────────────────────────────────────────────
 RAX  0x1ef2ae4
 RBX  0x7ffff000148a ◂— 0x0
 RCX  0x7ffff6901ed0 ◂— 0x0
 RDX  0x7ffff00008c0 ◂— 0xda5bd6f00000000
 RDI  0x65c310 ◂— 0xbd6f000000000200
 RSI  0x18
 R8   0x0
 R9   0x67c000
 R10  0x65cee2 ◂— 0x0
 R11  0x65ced9 ◂— 0x0
 R12  0x0
 R13  0x43b0a0 ◂— push   -3
 R14  0x0
 R15  0x65c310 ◂— 0xbd6f000000000200
 RBP  0x7ffff000148a ◂— 0x0
 RSP  0x7ffff6901e80 —▸ 0x65c130 —▸ 0x7ffff00008c0 ◂— 0xda5bd6f00000000
 RIP  0x7ffff7bc8144 (lzo1x_decompress+276) ◂— movzx  r8d, byte ptr [r9]
──────────────────────────────────────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────────────────────────────────────────
 ► 0x7ffff7bc8144 <lzo1x_decompress+276>    movzx  r8d, byte ptr [r9]
   0x7ffff7bc8148 <lzo1x_decompress+280>    add    rax, 0xff
   0x7ffff7bc814e <lzo1x_decompress+286>    test   r8b, r8b
   0x7ffff7bc8151 <lzo1x_decompress+289>    je     lzo1x_decompress+272 <0x7ffff7bc8140>
    ↓
   0x7ffff7bc8140 <lzo1x_decompress+272>    add    r9, 1
 ► 0x7ffff7bc8144 <lzo1x_decompress+276>    movzx  r8d, byte ptr [r9]
   0x7ffff7bc8148 <lzo1x_decompress+280>    add    rax, 0xff
   0x7ffff7bc814e <lzo1x_decompress+286>    test   r8b, r8b
   0x7ffff7bc8151 <lzo1x_decompress+289>    je     lzo1x_decompress+272 <0x7ffff7bc8140>
    ↓
   0x7ffff7bc8140 <lzo1x_decompress+272>    add    r9, 1
 ► 0x7ffff7bc8144 <lzo1x_decompress+276>    movzx  r8d, byte ptr [r9]
───────────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp  0x7ffff6901e80 —▸ 0x65c130 —▸ 0x7ffff00008c0 ◂— 0xda5bd6f00000000
01:0008│      0x7ffff6901e88 —▸ 0x6449a0 (local_control) —▸ 0x7fffffffe166 ◂— '../id:000002,sig:06,src:000008,op:flip2,pos:35'
02:0010│      0x7ffff6901e90 ◂— 0x0
03:0018│      0x7ffff6901e98 —▸ 0x411bb2 (ucompthread+882) ◂— test   eax, eax
04:0020│      0x7ffff6901ea0 —▸ 0x7ffff6901ed0 ◂— 0x0
05:0028│      0x7ffff6901ea8 ◂— 0x0
06:0030│      0x7ffff6901eb0 —▸ 0x644a60 (local_control+192) ◂— 0x0
07:0038│      0x7ffff6901eb8 —▸ 0x7ffff6901ec8 ◂— 0x0
─────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────────
 ► f 0     7ffff7bc8144 lzo1x_decompress+276
   f 1           411bb2 ucompthread+882
   f 2           411bb2 ucompthread+882
   f 3     7ffff75756ba start_thread+202
Program received signal SIGSEGV (fault address 0x67c000)
pwndbg> vmmap 
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
          0x400000           0x444000 r-xp    44000 0      
          0x643000           0x644000 r--p     1000 43000  
          0x644000           0x645000 rw-p     1000 44000  
          0x645000           0x67c000 rw-p    37000 0      [heap]
N3vv commented 5 years ago

This was assigned CVE-2019-10654.

asarubbo commented 5 years ago

Hello N3vv,

based on the output I get, I think it is the same issue. However it is still not fixed, so basically this is an incomplete fix for CVE-2017-8845

buweilv commented 4 years ago

Hello N3vv,

this CVE-2019-10654 is a flaw in lrzip or lzo?

pete4abw commented 4 years ago

Wasn't this bug corrected? It's not an LZO bug. The POC file is corrupt. Did you manually edit the LRZ file in bytes 0x6-0xd? What was the original file you compressed? @N3vv will you provide that?

peter@tommyiv:~/Downloads$ lrzip -i POC Detected lrzip version 0.6 file. Rzip chunk 1: Chunk byte width: 1 Stream: 0 Block Comp Percent Size 1 lzo 240.0% 24 / 10 Stream: 1 Block Comp Percent Size 1 none 100.0% 2 / 2 Rzip compression: 0.0% 12 / 281474974679042 Back end compression: 216.7% 26 / 12 Overall compression: 0.0% 26 / 281474974679042 POC: l>rzip version: 0.6 file Compression: rzip + lzo Decompressed file size: 281474974679042 Compressed file size: 71 Compression ratio: 3964436263085.099 MD5 used for integrity testing MD5: 26ab0db90d72e28ad0ba1e22ee510510

peter@tommyiv:~/Downloads$ lrzip -t POC Using configuration file /home/peter/.lrzip/lrzip.conf The following options are in effect for this INTEGRITY TEST. Threading is ENABLED. Number of CPUs detected: 8 Detected 8341680128 bytes ram Nice Value: 19 Show Progress Verbose Test file integrity Temporary Directory set as: ./ Detected lrzip version 0.6 file. Inadequate free space to test file. Space needed: 281474974679042. Space available: >8194113536. Try setting TMP=dirname and select a larger volume. Fatal error - exiting

N3vv commented 4 years ago

Hello N3vv,

this CVE-2019-10654 is a flaw in lrzip or lzo?

I think it's in lzo

pete4abw commented 4 years ago

Hello N3vv, this CVE-2019-10654 is a flaw in lrzip or lzo?

I think it's in lzo

Without the source file you used to compress, it's not possible to tell. lrzip thinks the file is 281474974679042 bytes large. lrzip never starts to decompress (in the latest version I use which applies the test size patches).

N3vv commented 4 years ago

Wasn't this bug corrected? It's not an LZO bug. The POC file is corrupt. Did you manually edit the LRZ file in bytes 0x6-0xd? What was the original file you compressed? @N3vv will you provide that?

peter@tommyiv:~/Downloads$ lrzip -i POC Detected lrzip version 0.6 file. Rzip chunk 1: Chunk byte width: 1 Stream: 0 Block Comp Percent Size 1 lzo 240.0% 24 / 10 Stream: 1 Block Comp Percent Size 1 none 100.0% 2 / 2 Rzip compression: 0.0% 12 / 281474974679042 Back end compression: 216.7% 26 / 12 Overall compression: 0.0% 26 / 281474974679042 POC: l>rzip version: 0.6 file Compression: rzip + lzo Decompressed file size: 281474974679042 Compressed file size: 71 Compression ratio: 3964436263085.099 MD5 used for integrity testing MD5: 26ab0db90d72e28ad0ba1e22ee510510

peter@tommyiv:~/Downloads$ lrzip -t POC Using configuration file /home/peter/.lrzip/lrzip.conf The following options are in effect for this INTEGRITY TEST. Threading is ENABLED. Number of CPUs detected: 8 Detected 8341680128 bytes ram Nice Value: 19 Show Progress Verbose Test file integrity Temporary Directory set as: ./ Detected lrzip version 0.6 file. Inadequate free space to test file. Space needed: 281474974679042. Space available: >8194113536. Try setting TMP=dirname and select a larger volume. Fatal error - exiting

I found this issue by AFL. And I just tried and it seems that I uploaded the wrong POC file before.Unfortunately my virtual machine broke down and reinstalled, so the correct POC file was lost. This problem did exist and I'm trying to use the previous seed to reprodfuce this.

pete4abw commented 4 years ago

Well, you closed the issue, @N3vv . All I can see is the POC file is borked. Without further details and a source file (not lrzip file) to test, nothing more can be done. The source file that was compressed was 12 bytes long, yet lrzip thinks it is 281,474,974,679,042 bytes long. Try applying pull request #140 and try and reproduce the file you used to create the initial bug.

Block Comp Percent Size
1 lzo 240.0% 24 / 10
1 none 100.0% 2 / 2
N3vv commented 4 years ago

Well, you closed the issue, @N3vv . All I can see is the POC file is borked. Without further details and a source file (not lrzip file) to test, nothing more can be done. The source file that was compressed was 12 bytes long, yet lrzip thinks it is 281,474,974,679,042 bytes long. Try applying pull request #140 and try and reproduce the file you used to create the initial bug.

Block Comp Percent Size 1 lzo 240.0% 24 / 10 1 none 100.0% 2 / 2

I got a similar poc and I compress it with zip. You can reproduce this with argument lrzip -d -o 1234 -f poc.lrz

pwndbg> file lrzip
Reading symbols from lrzip...done.
pwndbg> set args -d -o 1234 -f poc.lrz 
pwndbg> r
Starting program: /home/ne vv/Desktop/pwn1/lrzip-0.631/lrzip -d -o 1234 -f poc.lrz 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Output filename is: 1234
Decompressing...
[New Thread 0x7faf62cad700 (LWP 48431)]

Thread 2 "lrzip" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7faf62cad700 (LWP 48431)]
0x00007fb009b6f144 in lzo1x_decompress () from /lib/x86_64-linux-gnu/liblzo2.so.2
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────[ REGISTERS ]────────────────────────────────────────────────────────────
 RAX  0xdbee35
 RBX  0x7faf5c001627 ◂— 0x0
 RCX  0x7faf62caceb0 ◂— 0x0
 RDX  0x7faf5c000b20 ◂— 0xdae1e80200000000
 RDI  0x558384779820 ◂— 0xe802000000000700
 RSI  0xa
 R8   0x0
 R9   0x558384788000
 R10  0x55838477a333 ◂— 0x0
 R11  0x55838477a331 ◂— 0x0
 R12  0x0
 R13  0x558382a64ba0 ◂— 0xfffd7490fffd73f0
 R14  0x7faf62caceb0 ◂— 0x0
 R15  0x558384779820 ◂— 0xe802000000000700
 RBP  0x7faf5c001627 ◂— 0x0
 RSP  0x7faf62cace60 —▸ 0x5583847795e0 —▸ 0x7faf5c000b20 ◂— 0xdae1e80200000000
 RIP  0x7fb009b6f144 (lzo1x_decompress+276) ◂— movzx  r8d, byte ptr [r9]
─────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────
 ► 0x7fb009b6f144 <lzo1x_decompress+276>    movzx  r8d, byte ptr [r9]
   0x7fb009b6f148 <lzo1x_decompress+280>    add    rax, 0xff
   0x7fb009b6f14e <lzo1x_decompress+286>    test   r8b, r8b
   0x7fb009b6f151 <lzo1x_decompress+289>    je     lzo1x_decompress+272 <0x7fb009b6f140>
    ↓
   0x7fb009b6f140 <lzo1x_decompress+272>    add    r9, 1
 ► 0x7fb009b6f144 <lzo1x_decompress+276>    movzx  r8d, byte ptr [r9]
   0x7fb009b6f148 <lzo1x_decompress+280>    add    rax, 0xff
   0x7fb009b6f14e <lzo1x_decompress+286>    test   r8b, r8b
   0x7fb009b6f151 <lzo1x_decompress+289>    je     lzo1x_decompress+272 <0x7fb009b6f140>
    ↓
   0x7fb009b6f140 <lzo1x_decompress+272>    add    r9, 1
 ► 0x7fb009b6f144 <lzo1x_decompress+276>    movzx  r8d, byte ptr [r9]
──────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────
00:0000│ rsp  0x7faf62cace60 —▸ 0x5583847795e0 —▸ 0x7faf5c000b20 ◂— 0xdae1e80200000000
01:0008│      0x7faf62cace68 —▸ 0x558382c6d5e0 (local_control) —▸ 0x7ffd43268173 ◂— 0x7a726c2e636f70 /* 'poc.lrz' */
02:0010│      0x7faf62cace70 —▸ 0x7faf62caceb0 ◂— 0x0
03:0018│      0x7faf62cace78 —▸ 0x558382a3c069 (ucompthread+905) ◂— test   eax, eax
04:0020│      0x7faf62cace80 ◂— 0x0
... ↓
06:0030│      0x7faf62cace90 —▸ 0x558382c6d6a0 (local_control+192) ◂— 0x0
07:0038│      0x7faf62cace98 —▸ 0x7faf62cacea8 ◂— 0x0
────────────────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────────────
 ► f 0     7fb009b6f144 lzo1x_decompress+276
   f 1     558382a3c069 ucompthread+905
   f 2     558382a3c069 ucompthread+905
   f 3     7fb0095176db start_thread+219
Program received signal SIGSEGV (fault address 0x558384788000)
pwndbg> Quit
pwndbg> bt
#0  0x00007fb009b6f144 in lzo1x_decompress () from /lib/x86_64-linux-gnu/liblzo2.so.2
#1  0x0000558382a3c069 in lzo_decompress_buf (ucthread=0x5583847795e0, control=0x558382c6d5e0 <local_control>) at stream.c:590
#2  ucompthread (data=0x0) at stream.c:1525
#3  0x00007fb0095176db in start_thread (arg=0x7faf62cad700) at pthread_create.c:463
#4  0x00007fb00890188f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

poc.lrz.zip

pete4abw commented 4 years ago

I see the segfault. But I still need to see the uncompressed file. It looks like it was only 7 bytes long. Without seeing the source file, it looks like the chunk is being read badly and maybe even passing a zero length chunk to the lzo decoder. My workaround would be to refuse to lrzip any file under 4K.

Seeing a chunk size of 0 is an issue. This should never happen. However, lrzip stands for LONG RANGE ZIP. This type of error for a 7 byte long file is not worth the effort to try and fix. Personally, I'm working with the SDK 19.00 of lzma (and a whole bunch of commits ahead of 0.631), not the current. Either reopen the issue and provide the uncompressed file, or not.

Reading chunk_bytes at 24 Expected size: 7 Chunk byte width: 1 Reading eof flag at 25 EOF: 1 Reading expected chunksize at 26 Chunk size: 0

peter@tommyiv:/share/docs/downloads$ lrzip -vi poc.lrz Using configuration file /home/peter/.lrzip/lrzip.conf Detected lrzip version 0.6 file. Rzip chunk 1: Chunk byte width: 1 (this means the chunk size is between 1 and 15 bytes long) Stream: 0 Offset: 27 Block Comp Percent Size 1 lzo 100.0% 10 / 10 Offset: 0 Head: 0 Stream: 1 Offset: 27 Block Comp Percent Size 1 none 100.0% 7 / 7 Offset: 0 Head: 0 Rzip compression: 242.9% 17 / 7 Back end compression: 100.0% 17 / 17 Overall compression: 242.9% 17 / 7 poc.lrz: lrzip version: 0.6 file Compression: rzip + lzo Decompressed file size: 7 Compressed file size: 76 (silly to compress small files) Compression ratio: 0.092 MD5 used for integrity testing MD5: d2fde576f44a6601b73201234b491904

N3vv commented 4 years ago

I see the segfault. But I still need to see the uncompressed file. It looks like it was only 7 bytes long. Without seeing the source file, it looks like the chunk is being read badly and maybe even passing a zero length chunk to the lzo decoder. My workaround would be to refuse to lrzip any file under 4K.

Seeing a chunk size of 0 is an issue. This should never happen. However, lrzip stands for LONG RANGE ZIP. This type of error for a 7 byte long file is not worth the effort to try and fix. Personally, I'm working with the SDK 19.00 of lzma (and a whole bunch of commits ahead of 0.631), not the current. Either reopen the issue and provide the uncompressed file, or not.

Reading chunk_bytes at 24 Expected size: 7 Chunk byte width: 1 Reading eof flag at 25 EOF: 1 Reading expected chunksize at 26 Chunk size: 0

peter@tommyiv:/share/docs/downloads$ lrzip -vi poc.lrz Using configuration file /home/peter/.lrzip/lrzip.conf Detected lrzip version 0.6 file. Rzip chunk 1: Chunk byte width: 1 (this means the chunk size is between 1 and 15 bytes long) Stream: 0 Offset: 27 Block Comp Percent Size 1 lzo 100.0% 10 / 10 Offset: 0 Head: 0 Stream: 1 Offset: 27 Block Comp Percent Size 1 none 100.0% 7 / 7 Offset: 0 Head: 0 Rzip compression: 242.9% 17 / 7 Back end compression: 100.0% 17 / 17 Overall compression: 242.9% 17 / 7 poc.lrz: lrzip version: 0.6 file Compression: rzip + lzo Decompressed file size: 7 Compressed file size: 76 (silly to compress small files) Compression ratio: 0.092 MD5 used for integrity testing MD5: d2fde576f44a6601b73201234b491904

There is no uncompressed file here. This test case is obtained by mutating some bytes with a valid compressed file. Because I want to use the fuzz(which is mainly providing unexpected input and monitoring for abnormal results) to find flaws or vulnerabilities.

pete4abw commented 4 years ago

Use PR #140. Should fix the issue before it gets too lzo. Messing with the magic header will of course cause problems. Most will be caught as each chunk is decompressed. This is a self inflicted wound. Unless you sign an archive after creation or generate a hash on the compressed archive, you have to protect your own assets against intrusion. Not a bug and has been resolved.