ckolivas / lrzip

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

Infinite Loop Vulnerability in get_fileinfo (src/lrzip.c) #91

Closed ProbeFuzzer closed 2 years ago

ProbeFuzzer commented 6 years ago

On latest version (0.631) and the master branch, there is an infinite loop and application hang in the get_fileinfo function (src/lrzip.c), which can be triggered by the POC with command: lrzip -i $POC

Looking into the get_fileinfo function (src/lrzip.c), we found that: in the "do {} while(last_head)" loop, the "last_head" variable is affected by the POC file and always non-zero, and "lseek" in line 1041 continuously moves file cursor to the same position. That means, "last_head" is always assigned the value from the same file position, resulting in infinite loop.

934 bool get_fileinfo(rzip_control *control)
...
   1036                 do {
    ...
      1041                         if (unlikely(head_off = lseek(fd_in, last_head + ofs, SEEK_SET) == -1))
      1042                                 fatal_goto(("Failed to seek to header data in get_fileinfo\n"), error);
      1043                         if (unlikely(!get_header_info(control, fd_in, &ctype, &c_len, &u_len,
      1044                                         &last_head, chunk_byte)))
      1045                                 return false;
      ...
      1069                 } while (last_head);

POC: https://github.com/ProbeFuzzer/poc/blob/master/lrzip/lrzip_0-631_lrzip_infinite-loop_get_fileinfo.lrz

carnil commented 6 years ago

This was assigned CVE-2018-5786

ckolivas commented 6 years ago

Fixed generically with other safeguards.

Beuc commented 2 years ago

Hi,

Sorry to dig old bugs, I'm part of Debian LTS (Long Term Support) and while looking at this issue, it seems it never got fixed, despite safeguards such as 399336eba.

During my tests I couldn't find a lrzip version that avoids the infinite loop. Note: unlike all other CVEs fixes surrounding this one, this CVE is triggered with the -i flag (not -t).

Current master (e5e9a61f) debug log:

# gdb --args ../master/lrzip/lrzip -i lrzip_0-631_lrzip_infinite-loop_get_fileinfo.lrz
(gdb) run
Starting program: /usr/src/lrzip/master/lrzip/lrzip -i lrzip_0-631_lrzip_infinite-loop_get_fileinfo
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
^C
Program received signal SIGINT, Interrupt.
0x00007ffff736e210 in __read_nocancel () from /lib/x86_64-linux-gnu/libpthread.so.0
(gdb) bt
#0  0x00007ffff736e210 in __read_nocancel () from /lib/x86_64-linux-gnu/libpthread.so.0
#1  0x000055555555d74a in get_header_info (control=control@entry=0x5555557989c0 <local_control>, fd_in=fd_in@entry=3, ctype=ctype@entry=0x7fffffffe1e7 "\003\032", 
    c_len=c_len@entry=0x7fffffffe1f0, u_len=u_len@entry=0x7fffffffe1e8, last_head=last_head@entry=0x7fffffffe1f8, chunk_bytes=2) at lrzip.c:956
#2  0x000055555555df72 in get_fileinfo (control=0x5555557989c0 <local_control>) at lrzip.c:1103
#3  0x0000555555558147 in main (argc=<optimized out>, argv=<optimized out>) at main.c:722
(gdb) frame 2
#2  0x000055555555df72 in get_fileinfo (control=0x5555557989c0 <local_control>) at lrzip.c:1103
1103                if (unlikely(!get_header_info(control, fd_in, &ctype, &c_len, &u_len,
(gdb) list
1098                second_last = last_head;
1099                if (unlikely(last_head + ofs > infile_size))
1100                    failure_goto(("Offset greater than archive size, likely corrupted/truncated archive.\n"), error);
1101                if (unlikely((head_off = lseek(fd_in, last_head + ofs, SEEK_SET)) == -1))
1102                    fatal_goto(("Failed to seek to header data in get_fileinfo\n"), error);
1103                if (unlikely(!get_header_info(control, fd_in, &ctype, &c_len, &u_len,
1104                        &last_head, chunk_byte)))
1105                    return false;
1106                if (unlikely(last_head < 0 || c_len < 0 || u_len < 0))
1107                    failure_goto(("Entry negative, likely corrupted archive.\n"), error);

Can you confirm?

ckolivas commented 2 years ago

Thanks. The check looks incomplete in the info version. Will check again shortly.

ckolivas commented 2 years ago

Fixed in https://github.com/ckolivas/lrzip/commit/3495188cd8f2215a9feea201f3e05c1341ed95fb

Beuc commented 2 years ago

This works for me. Thank you.