Headline
CVE-2023-27103: A heap-buffer-overflow has occurred when running program dec265 in function derive_collocated_motion_vectors at motion.cc · Issue #394 · strukturag/libde265
Libde265 v1.0.11 was discovered to contain a heap buffer overflow via the function derive_collocated_motion_vectors at motion.cc.
Desctiption
A heap-buffer-overflow has occurred when running program dec265 in function derive_collocated_motion_vectors at motion.cc:1259:41
Version
dec265 v1.0.11
git log
commit fef32a7761993702c699dfbe3699e44374eb44b5 (HEAD -> master, origin/master, origin/HEAD)
Merge: 3aea5a45 c2b60f1c
Author: Dirk Farin <[email protected]>
Date: Thu Feb 9 11:13:24 2023 +0100
Steps to reproduce
git clone https://github.com/strukturag/libde265.git
cd libde265
./autogen.sh
export CFLAGS="-g -O0 -lpthread -fsanitize=address"
export CXXFLAGS="-g -O0 -lpthread -fsanitize=address"
export LDFLAGS="-fsanitize=address"
./configure --disable-shared
make -j
cd dec265
./dec265 Heap-overflow-POC1
WARNING: Bit-depth of current image does not match SPS
WARNING: Bit-depth of current image does not match SPS
WARNING: Too many warnings queued
=================================================================
==137060==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000000a8 at pc 0x0000006cc0b4 bp 0x7fff28554e90 sp 0x7fff28554e88
READ of size 8 at 0x6020000000a8 thread T0
#0 0x6cc0b3 in derive_collocated_motion_vectors(base_context*, de265_image*, slice_segment_header const*, int, int, int, int, int, int, int, MotionVector*, unsigned char*) /home/lzy/fuzz/oss/libde265/libde265/motion.cc:1259:41
#1 0x6cd4cf in derive_temporal_luma_vector_prediction(base_context*, de265_image*, slice_segment_header const*, int, int, int, int, int, int, MotionVector*, unsigned char*) /home/lzy/fuzz/oss/libde265/libde265/motion.cc:1388:5
#2 0x6cf16c in get_merge_candidate_list_without_step_9(base_context*, slice_segment_header const*, MotionVectorAccess const&, de265_image*, int, int, int, int, int, int, int, int, int, PBMotion*) /home/lzy/fuzz/oss/libde265/libde265/motion.cc:1523:5
#3 0x6d052b in derive_luma_motion_merge_mode(base_context*, slice_segment_header const*, de265_image*, int, int, int, int, int, int, int, int, int, PBMotion*) /home/lzy/fuzz/oss/libde265/libde265/motion.cc:1612:3
#4 0x6d80d6 in motion_vectors_and_ref_indices(base_context*, slice_segment_header const*, de265_image*, PBMotionCoding const&, int, int, int, int, int, int, int, int, PBMotion*) /home/lzy/fuzz/oss/libde265/libde265/motion.cc:2088:7
#5 0x6d9435 in decode_prediction_unit(base_context*, slice_segment_header const*, de265_image*, PBMotionCoding const&, int, int, int, int, int, int, int, int) /home/lzy/fuzz/oss/libde265/libde265/motion.cc:2171:3
#6 0x5bf634 in read_prediction_unit(thread_context*, int, int, int, int, int, int, int, int, int) /home/lzy/fuzz/oss/libde265/libde265/slice.cc:4136:3
#7 0x5c233c in read_coding_unit(thread_context*, int, int, int, int) /home/lzy/fuzz/oss/libde265/libde265/slice.cc:4504:9
#8 0x5b17db in read_coding_quadtree(thread_context*, int, int, int, int) /home/lzy/fuzz/oss/libde265/libde265/slice.cc:4652:5
#9 0x5b0887 in read_coding_tree_unit(thread_context*) /home/lzy/fuzz/oss/libde265/libde265/slice.cc:2861:3
#10 0x5c7fe8 in decode_substream(thread_context*, bool, bool) /home/lzy/fuzz/oss/libde265/libde265/slice.cc:4741:5
#11 0x5cb648 in read_slice_segment_data(thread_context*) /home/lzy/fuzz/oss/libde265/libde265/slice.cc:5054:14
#12 0x4e8254 in decoder_context::decode_slice_unit_sequential(image_unit*, slice_unit*) /home/lzy/fuzz/oss/libde265/libde265/decctx.cc:853:7
#13 0x4e614f in decoder_context::decode_slice_unit_parallel(image_unit*, slice_unit*) /home/lzy/fuzz/oss/libde265/libde265/decctx.cc:955:11 #14 0x4e4b1f in decoder_context::decode_some(bool*) /home/lzy/fuzz/oss/libde265/libde265/decctx.cc:740:13
#15 0x4e1a3f in decoder_context::read_slice_NAL(bitreader&, NAL_unit*, nal_header&) /home/lzy/fuzz/oss/libde265/libde265/decctx.cc:698:9
#16 0x4eb7f1 in decoder_context::decode_NAL(NAL_unit*) /home/lzy/fuzz/oss/libde265/libde265/decctx.cc:1240:11
#17 0x4ec6a1 in decoder_context::decode(int*) /home/lzy/fuzz/oss/libde265/libde265/decctx.cc:1328:16
#18 0x4d3645 in de265_decode /home/lzy/fuzz/oss/libde265/libde265/de265.cc:367:15
#19 0x4d0363 in main /home/lzy/fuzz/oss/libde265/dec265/dec265.cc:764:17
#20 0x7fccbc3e8082 in __libc_start_main /build/glibc-KZwQYS/glibc-2.31/csu/../csu/libc-start.c:308:16
#21 0x41e5bd in _start (/home/lzy/fuzz/oss/libde265/dec265/dec265+0x41e5bd)
0x6020000000a8 is located 16 bytes to the right of 8-byte region [0x602000000090,0x602000000098)
allocated by thread T0 here:
#0 0x4ca8dd in operator new(unsigned long) (/home/lzy/fuzz/oss/libde265/dec265/dec265+0x4ca8dd)
#1 0x500842 in __gnu_cxx::new_allocator<slice_segment_header*>::allocate(unsigned long, void const*) /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ext/new_allocator.h:114:27
#2 0x500751 in std::allocator_traits<std::allocator<slice_segment_header*> >::allocate(std::allocator<slice_segment_header*>&, unsigned long) /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/alloc_traits.h:443:20
#3 0x4ffef1 in std::_Vector_base<slice_segment_header*, std::allocator<slice_segment_header*> >::_M_allocate(unsigned long) /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:343:20
#4 0x4ff227 in void std::vector<slice_segment_header*, std::allocator<slice_segment_header*> >::_M_realloc_insert<slice_segment_header* const&>(__gnu_cxx::__normal_iterator<slice_segment_header**, std::vector<slice_segment_header*, std::allocator<slice_segment_header*> > >, slice_segment_header* const&) /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/vector.tcc:440:33
#5 0x4feea3 in std::vector<slice_segment_header*, std::allocator<slice_segment_header*> >::push_back(slice_segment_header* const&) /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1195:4
#6 0x4e4066 in de265_image::add_slice_segment_header(slice_segment_header*) /home/lzy/fuzz/oss/libde265/libde265/../libde265/image.h:326:12 #7 0x4e12ba in decoder_context::read_slice_NAL(bitreader&, NAL_unit*, nal_header&) /home/lzy/fuzz/oss/libde265/libde265/decctx.cc:657:14
#8 0x4eb7f1 in decoder_context::decode_NAL(NAL_unit*) /home/lzy/fuzz/oss/libde265/libde265/decctx.cc:1240:11
#9 0x4ec6a1 in decoder_context::decode(int*) /home/lzy/fuzz/oss/libde265/libde265/decctx.cc:1328:16
#10 0x4d3645 in de265_decode /home/lzy/fuzz/oss/libde265/libde265/de265.cc:367:15
#11 0x4d0363 in main /home/lzy/fuzz/oss/libde265/dec265/dec265.cc:764:17
#12 0x7fccbc3e8082 in __libc_start_main /build/glibc-KZwQYS/glibc-2.31/csu/../csu/libc-start.c:308:16
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/lzy/fuzz/oss/libde265/libde265/motion.cc:1259:41 in derive_collocated_motion_vectors(base_context*, de265_image*, slice_segment_header const*, int, int, int, int, int, int, int, MotionVector*, unsigned char*)
Shadow bytes around the buggy address:
0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff8000: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fa
=>0x0c047fff8010: fa fa 00 fa fa[fa]fd fa fa fa fd fa fa fa fd fa
0x0c047fff8020: fa fa fd fd fa fa fd fa fa fa fd fa fa fa fd fa
0x0c047fff8030: fa fa fd fd fa fa fd fa fa fa fd fd fa fa fd fa
0x0c047fff8040: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x0c047fff8050: fa fa 04 fa fa fa fd fa fa fa 00 00 fa fa fd fa
0x0c047fff8060: fa fa 00 fa fa fa 00 00 fa fa 00 00 fa fa 04 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
Shadow gap: cc
==137060==ABORTING
POC
https://github.com/blu3sh0rk/Fuzzing-crash/blob/main/Heap-overflow-POC1.zip
Code in function derive_collocated_motion_vectors at motion.cc:1259:41
if (allRefFramesBeforeCurrentFrame) {
mvCol = mvi.mv[X];
refIdxCol = mvi.refIdx[X];
listCol = X;
}
else {
int N = shdr->collocated_from_l0_flag;
mvCol = mvi.mv[N];
refIdxCol = mvi.refIdx[N];
listCol = N;
}
}
1259 const slice_segment_header* colShdr = colImg->slices[ colImg->get_SliceHeaderIndex(xColPb,yColPb) ];
Impact
Potentially causing DoS and RCE
Related news
Ubuntu Security Notice 6677-1 - It was discovered that libde265 could be made to dereference invalid memory. If a user or automated system were tricked into opening a specially crafted file, an attacker could possibly use this issue to cause a denial of service. This issue only affected Ubuntu 20.04 LTS and Ubuntu 22.04 LTS. It was discovered that libde265 could be made to write out of bounds. If a user or automated system were tricked into opening a specially crafted file, an attacker could possibly use this issue to cause a denial of service or execute arbitrary code. This issue only affected Ubuntu 16.04 LTS, Ubuntu 18.04 LTS, Ubuntu 20.04 LTS, and Ubuntu 22.04 LTS.