Skip to content

Heap Use-After-Free vulnerability exists in the RAR Filter #32

@Nero22k

Description

@Nero22k

A heap use-after-free vulnerability exists in the unarr archive extraction library during RAR archive processing. The issue occurs due to improper lifecycle management of RAR filter structures, where freed filter objects may still be referenced and later dereferenced.

When compiled with memory sanitizers (e.g., AddressSanitizer), this results in a deterministic heap-use-after-free crash. In non-sanitized builds, the vulnerability leads to memory corruption and crash when lzss_copy_bytes_from_window is called by rar_run_filters.

Under ASan:

==16032==ERROR: AddressSanitizer: heap-use-after-free on address 0x12429ec202e0 at pc 0x7ff70edec41d bp 0x0061fa2fe840 sp 0x0061fa2fe888
READ of size 4 at 0x12429ec202e0 thread T0
    #0 0x7ff70edec41c in rar_run_filters C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\filter-rar.c:665
    #1 0x7ff70edde8ea in rar_uncompress_part C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\uncompress-rar.c:962
    #2 0x7ff70edcef87 in rar_uncompress C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\rar.c:183
    #3 0x7ff70edccffc in read_test C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\test\fuzzer.c:58
    #4 0x7ff70edcd160 in LLVMFuzzerTestOneInput C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\test\fuzzer.c:85
    #5 0x7ff70ed4c52f in fuzzer::Fuzzer::ExecuteCallback(unsigned char const *, unsigned __int64) C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerLoop.cpp:614
    #6 0x7ff70ed65bc6 in fuzzer::RunOneTest(class fuzzer::Fuzzer *, char const *, unsigned __int64) C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerDriver.cpp:328
    #7 0x7ff70ed6dce4 in fuzzer::FuzzerDriver(int *, char ***, int (__cdecl *)(unsigned char const *, unsigned __int64)) C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerDriver.cpp:863
    #8 0x7ff70ed21022 in main C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerMain.cpp:20
    #9 0x7ff70ee5076f in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #10 0x7ff70ee5076f in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #11 0x7ffeb3da1fd6  (C:\WINDOWS\System32\KERNEL32.DLL+0x180031fd6)
    #12 0x7ffeb4dfd7cf  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18006d7cf)

0x12429ec202e0 is located 64 bytes inside of 88-byte region [0x12429ec202a0,0x12429ec202f8)
freed by thread T0 here:
    #0 0x7ff70edac55d in free C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\asan\asan_malloc_win.cpp:82
    #1 0x7ff70ede9088 in rar_delete_filter C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\filter-rar.c:295
    #2 0x7ff70ede9088 in rar_parse_filter C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\filter-rar.c:524
    #3 0x7ff70edd6f55 in rar_read_filter C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\uncompress-rar.c:651
    #4 0x7ff70edd6f55 in rar_expand C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\uncompress-rar.c:815
    #5 0x7ff70edebf33 in rar_run_filters C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\filter-rar.c:654
    #6 0x7ff70edde8ea in rar_uncompress_part C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\uncompress-rar.c:962
    #7 0x7ff70edcef87 in rar_uncompress C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\rar.c:183
    #8 0x7ff70edccffc in read_test C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\test\fuzzer.c:58
    #9 0x7ff70edcd160 in LLVMFuzzerTestOneInput C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\test\fuzzer.c:85
    #10 0x7ff70ed4c52f in fuzzer::Fuzzer::ExecuteCallback(unsigned char const *, unsigned __int64) C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerLoop.cpp:614
    #11 0x7ff70ed65bc6 in fuzzer::RunOneTest(class fuzzer::Fuzzer *, char const *, unsigned __int64) C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerDriver.cpp:328
    #12 0x7ff70ed6dce4 in fuzzer::FuzzerDriver(int *, char ***, int (__cdecl *)(unsigned char const *, unsigned __int64)) C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerDriver.cpp:863
    #13 0x7ff70ed21022 in main C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerMain.cpp:20
    #14 0x7ff70ee5076f in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #15 0x7ff70ee5076f in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #16 0x7ffeb3da1fd6  (C:\WINDOWS\System32\KERNEL32.DLL+0x180031fd6)
    #17 0x7ffeb4dfd7cf  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18006d7cf)

previously allocated by thread T0 here:
    #0 0x7ff70edac784 in calloc C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\asan\asan_malloc_win.cpp:114
    #1 0x7ff70ede93fd in rar_create_filter C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\filter-rar.c:270
    #2 0x7ff70ede93fd in rar_parse_filter C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\filter-rar.c:621
    #3 0x7ff70edd6f55 in rar_read_filter C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\uncompress-rar.c:651
    #4 0x7ff70edd6f55 in rar_expand C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\uncompress-rar.c:815
    #5 0x7ff70edde9a6 in rar_uncompress_part C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\uncompress-rar.c:974
    #6 0x7ff70edcef87 in rar_uncompress C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\rar.c:183
    #7 0x7ff70edccffc in read_test C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\test\fuzzer.c:58
    #8 0x7ff70edcd160 in LLVMFuzzerTestOneInput C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\test\fuzzer.c:85
    #9 0x7ff70ed4c52f in fuzzer::Fuzzer::ExecuteCallback(unsigned char const *, unsigned __int64) C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerLoop.cpp:614
    #10 0x7ff70ed65bc6 in fuzzer::RunOneTest(class fuzzer::Fuzzer *, char const *, unsigned __int64) C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerDriver.cpp:328
    #11 0x7ff70ed6dce4 in fuzzer::FuzzerDriver(int *, char ***, int (__cdecl *)(unsigned char const *, unsigned __int64)) C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerDriver.cpp:863
    #12 0x7ff70ed21022 in main C:\src\llvm_package_19.1.5\llvm-project\compiler-rt\lib\fuzzer\FuzzerMain.cpp:20
    #13 0x7ff70ee5076f in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #14 0x7ff70ee5076f in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #15 0x7ffeb3da1fd6  (C:\WINDOWS\System32\KERNEL32.DLL+0x180031fd6)
    #16 0x7ffeb4dfd7cf  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18006d7cf)

SUMMARY: AddressSanitizer: heap-use-after-free C:\Users\Vexer\Desktop\Work\Fuzzing\Libfuzzer\unarr\rar\filter-rar.c:665 in rar_run_filters
Shadow bytes around the buggy address:
  0x12429ec20000: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 02 fa
  0x12429ec20080: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 04 fa
  0x12429ec20100: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 03
  0x12429ec20180: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 01
  0x12429ec20200: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
=>0x12429ec20280: fa fa fa fa fd fd fd fd fd fd fd fd[fd]fd fd fa
  0x12429ec20300: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
  0x12429ec20380: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
  0x12429ec20400: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
  0x12429ec20480: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
  0x12429ec20500: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==16032==ABORTING

Without ASan:

RAX: 000002B8041E3310   RBX: 000002B8041CCE20   RCX: 000002B8041E3310   
RDX: 000002B804399040   RSI: 000002B8041D0030   RDI: 0000000000010000   
RIP: 00007FF818ED2251   RSP: 000000D1192FF1E8   RBP: 0000000000400000   
R8:  FFFFFFFFFFFFFFD0   R9:  000002B8041E3310   R10: 00007FF818EC0000   
R11: 000000D1192FEDF8   R12: 000002B8041E3310   R13: 0000000000000000   
R14: FFFFFFFFFFFFFFD0   R15: 0000000000000000   
EFLAGS: 00010282 CF=0 PF=0 AF=0 ZF=0 SF=1 TF=0 IF=1 DF=0 OF=0
LastErrorValue: 0x00000000
LastStatusValue: 0x00000000
0:000> g
(5294.2520): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
VCRUNTIME140!memcpy+0x181:
00007ff8`18ed2251 c4a17e6f6c02e0  vmovdqu ymm5,ymmword ptr [rdx+r8-20h] ds:000002b8`04398ff0=??
0:000> k
 # Child-SP          RetAddr               Call Site
00 000000d1`192ff1e8 00007ff7`53a923af     VCRUNTIME140!memcpy+0x181 
01 000000d1`192ff1f0 00007ff7`53a8b91b     unarr_test!rar_run_filters+0xdf [...\unarr\rar\filter-rar.c @ 666] 
02 000000d1`192ff250 00007ff7`53a82443     unarr_test!rar_uncompress_part+0x23b [...\unarr\rar\uncompress-rar.c @ 962] 
03 000000d1`192ff2d0 00007ff7`53a811d4     unarr_test!rar_uncompress+0x1c3 [...\unarr\rar\rar.c @ 183] 
04 000000d1`192ff740 00007ff7`53aa1560     unarr_test!main+0x154 [...\unarr\test\main.c @ 65] 
05 (Inline Function) --------`--------     unarr_test!invoke_main+0x22
06 000000d1`192ffbb0 00007ff8`28bf7374     unarr_test!__scrt_common_main_seh+0x10c 
07 000000d1`192ffbf0 00007ff8`2a73cc91     KERNEL32!BaseThreadInitThunk+0x14
08 000000d1`192ffc20 00000000`00000000     ntdll!RtlUserThreadStart+0x21
0:000> dq rbx
000002b8`041cce20  000002b8`041c6c10 00000000`00000000
000002b8`041cce30  000000a1`00000000 00008686`ffffffd0
000002b8`041cce40  00040000`00001a1a 000002b8`041dfec0
000002b8`041cce50  00000000`00000040 00000000`43434445
000002b8`041cce60  00000000`ffffffd0 00000000`00000000
000002b8`041cce70  000002b8`041e20c0 abababab`abababab
000002b8`041cce80  abababab`abababab 00000000`00000000
000002b8`041cce90  00000000`00000000 00000000`00000000
0:000> ? ffffffd0
Evaluate expression: 4294967248 = 00000000`ffffffd0
0:000> ? r8
Evaluate expression: -48 = ffffffff`ffffffd0

PoC

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions