Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

heap-use-after-free in read_stream (stream.c:1756) #96

Closed
Twi1ight opened this issue May 25, 2018 · 3 comments
Closed

heap-use-after-free in read_stream (stream.c:1756) #96

Twi1ight opened this issue May 25, 2018 · 3 comments

Comments

@Twi1ight
Copy link

In the latest commit master-ed51e1, there is a heap-use-after-free in read_stream function (stream.c:1756).
With ASAN cflags "-fsanitize=address", use the POC attached will trigger the vulnerability.
Command to reproduce: ./lrzip -t lrzip-uaf-read_stream.lrz
The ASAN backtrace info:

READ of size 1 at 0x60200000eef0 thread T0
    #0 0x7f5752d26934 in __asan_memcpy (/usr/lib/gcc/x86_64-linux-gnu/5/libasan.so+0x8c934)
    #1 0x414655 in memcpy /usr/include/x86_64-linux-gnu/bits/string3.h:53
    #2 0x414655 in read_stream /opt/csn/lrzip/stream.c:1756
    #3 0x40ee8c in read_vchars /opt/csn/lrzip/runzip.c:79
    #4 0x40ee8c in read_header /opt/csn/lrzip/runzip.c:147
    #5 0x40ee8c in runzip_chunk /opt/csn/lrzip/runzip.c:316
    #6 0x40ee8c in runzip_fd /opt/csn/lrzip/runzip.c:384
    #7 0x407db9 in decompress_file /opt/csn/lrzip/lrzip.c:838
    #8 0x403a74 in main /opt/csn/lrzip/main.c:675
    #9 0x7f57515e082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #10 0x404888 in _start (/opt/csn/lrzip/lrzip+0x404888)

0x60200000eef0 is located 0 bytes inside of 10-byte region [0x60200000eef0,0x60200000eefa)
freed by thread T0 here:
    #0 0x7f5752d322ca in __interceptor_free (/usr/lib/gcc/x86_64-linux-gnu/5/libasan.so+0x982ca)
    #1 0x4146d0 in fill_buffer /opt/csn/lrzip/stream.c:1573
    #2 0x4146d0 in read_stream /opt/csn/lrzip/stream.c:1764

previously allocated by thread T0 here:
    #0 0x7f5752d32602 in malloc (/usr/lib/gcc/x86_64-linux-gnu/5/libasan.so+0x98602)
    #1 0x414937 in fill_buffer /opt/csn/lrzip/stream.c:1651
    #2 0x414937 in read_stream /opt/csn/lrzip/stream.c:1764

SUMMARY: AddressSanitizer: heap-use-after-free ??:0 __asan_memcpy
Shadow bytes around the buggy address:
  0x0c047fff9d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9d90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa fd fd fa fa[fd]fd
  0x0c047fff9de0: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
  0x0c047fff9df0: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 04 fa
  0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==85575==ABORTING

when compile without ASAN flags, lrzip will crash because of double free

Decompressing...
*** Error in `./lrzip': double free or corruption (fasttop): 0x0000000000ba9b60 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f6191e817e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f6191e8a37a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f6191e8e53c]
./lrzip[0x4146d1]
./lrzip[0x40ef03]
./lrzip[0x407dba]
./lrzip[0x403a75]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f6191e2a830]
./lrzip[0x404889]
======= Memory map: ========
00400000-00443000 r-xp 00000000 ca:02 655162                             /opt/csn/lrzip/lrzip
00642000-00643000 r--p 00042000 ca:02 655162                             /opt/csn/lrzip/lrzip
00643000-00644000 rw-p 00043000 ca:02 655162                             /opt/csn/lrzip/lrzip

s->buf was freed in fill_buffer in stream.c:1573

1564 /* fill a buffer from a stream - return -1 on failure */
1565 static int fill_buffer(rzip_control *control, struct stream_info *sinfo, struct stream *s, int streamno)
1566 {
1567         i64 u_len, c_len, last_head, padded_len, header_length, max_len;
1568         uchar enc_head[25 + SALT_LEN], blocksalt[SALT_LEN];
1569         stream_thread_struct *st;
1570         bool new_thread = false;
1571         uchar c_type, *s_buf;
1572 
1573         dealloc(s->buf);

in the below code, the s->buf may be freed in fill_buffer, but with while the s->buf will be used again in memcpy in line 1756, and may be free again in fill_buffer in 1764. which caused heap use after free and double free.

1750         while (len) {
1751                 i64 n;
1752 
1753                 n = MIN(s->buflen - s->bufp, len);
1754 
1755                 if (n > 0) {
1756                         memcpy(p, s->buf + s->bufp, n);
1757                         s->bufp += n;
1758                         p += n;
1759                         len -= n;
1760                         ret += n;
1761                 }
1762 
1763                 if (len && s->bufp == s->buflen) {
1764                         if (unlikely(fill_buffer(control, sinfo, s, streamno)))
1765                                 return -1;
1766                         if (s->bufp == s->buflen)
1767                                 break;
1768                 }
1769         }

lrzip-uaf-read_stream.lrz.zip

@ckolivas
Copy link
Owner

907b66b

@Twi1ight
Copy link
Author

Twi1ight commented May 28, 2018

@ckolivas With the attached file, the double free issue still exists.
lrzip-double-free.lrz.zip

@ckolivas
Copy link
Owner

Thanks a81248e

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants