WebRTC - VP8 Block Decoding Use-After-Free

EDB-ID:

45121

CVE:

N/A




Platform:

Multiple

Date:

2018-08-01


There is a use-after-free in VP8 block decoding in WebRTC. The contents of the freed block is then treated a pointer, leading to a crash in WebRTC.

==20098==ERROR: AddressSanitizer: heap-use-after-free on address 0x6330000a9491 at pc 0x0000014cde2f bp 0x7ff20616d7e0 sp 0x7ff20616d7d8
READ of size 1 at 0x6330000a9491 thread T5 (DecodingThread)
    #0 0x14cde2e in vp8_deblock third_party/libvpx/source/libvpx/vp8/common/postproc.c:85:37
    #1 0x14ce6b2 in vp8_post_proc_frame third_party/libvpx/source/libvpx/vp8/common/postproc.c:354:5
    #2 0x14963a4 in vp8dx_get_raw_frame third_party/libvpx/source/libvpx/vp8/decoder/onyxd_if.c:404:9
    #3 0x149221f in vp8_get_frame third_party/libvpx/source/libvpx/vp8/vp8_dx_iface.c:465:14
    #4 0x148c118 in webrtc::LibvpxVp8Decoder::Decode(webrtc::EncodedImage const&, bool, webrtc::RTPFragmentationHeader const*, webrtc::CodecSpecificInfo const*, long) modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc:254:9
    #5 0x1b930b4 in webrtc::VCMGenericDecoder::Decode(webrtc::VCMEncodedFrame const&, long) modules/video_coding/generic_decoder.cc:233:29
    #6 0x1b6fad3 in webrtc::vcm::VideoReceiver::Decode(webrtc::VCMEncodedFrame const&) modules/video_coding/video_receiver.cc:374:19
    #7 0x1b6ff19 in webrtc::vcm::VideoReceiver::Decode(webrtc::VCMEncodedFrame const*) modules/video_coding/video_receiver.cc:340:10
    #8 0x1af33e4 in webrtc::internal::VideoReceiveStream::Decode() video/video_receive_stream.cc:433:41
    #9 0x1aedc8f in webrtc::internal::VideoReceiveStream::DecodeThreadFunction(void*) video/video_receive_stream.cc:410:49
    #10 0x6544d3 in Run rtc_base/platform_thread.cc:163:5
    #11 0x6544d3 in rtc::PlatformThread::StartThread(void*) rtc_base/platform_thread.cc:81
    #12 0x7ff22125e493 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x7493)

0x6330000a9491 is located 3217 bytes inside of 96619-byte region [0x6330000a8800,0x6330000c016b)
freed by thread T5 (DecodingThread) here:
    #0 0x59e3e2 in __interceptor_free /b/build/slave/linux_upload_clang/build/src/third_party/llvm/compiler-rt/lib/asan/asan_malloc_linux.cc:68:3
    #1 0x1492a54 in vp8_de_alloc_frame_buffers third_party/libvpx/source/libvpx/vp8/common/alloccommon.c:41:3
    #2 0x1492b0c in vp8_alloc_frame_buffers third_party/libvpx/source/libvpx/vp8/common/alloccommon.c:54:3
    #3 0x149126c in vp8_decode third_party/libvpx/source/libvpx/vp8/vp8_dx_iface.c:374:13
    #4 0x14d42c5 in vpx_codec_decode third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c:116:11
    #5 0x148c0a1 in webrtc::LibvpxVp8Decoder::Decode(webrtc::EncodedImage const&, bool, webrtc::RTPFragmentationHeader const*, webrtc::CodecSpecificInfo const*, long) modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc:245:7
    #6 0x1b930b4 in webrtc::VCMGenericDecoder::Decode(webrtc::VCMEncodedFrame const&, long) modules/video_coding/generic_decoder.cc:233:29
    #7 0x1b6fad3 in webrtc::vcm::VideoReceiver::Decode(webrtc::VCMEncodedFrame const&) modules/video_coding/video_receiver.cc:374:19
    #8 0x1b6ff19 in webrtc::vcm::VideoReceiver::Decode(webrtc::VCMEncodedFrame const*) modules/video_coding/video_receiver.cc:340:10
    #9 0x1af33e4 in webrtc::internal::VideoReceiveStream::Decode() video/video_receive_stream.cc:433:41
    #10 0x1aedc8f in webrtc::internal::VideoReceiveStream::DecodeThreadFunction(void*) video/video_receive_stream.cc:410:49
    #11 0x6544d3 in Run rtc_base/platform_thread.cc:163:5
    #12 0x6544d3 in rtc::PlatformThread::StartThread(void*) rtc_base/platform_thread.cc:81
    #13 0x7ff22125e493 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x7493)

previously allocated by thread T5 (DecodingThread) here:
    #0 0x59e723 in __interceptor_malloc /b/build/slave/linux_upload_clang/build/src/third_party/llvm/compiler-rt/lib/asan/asan_malloc_linux.cc:88:3
    #1 0x1530d92 in vpx_calloc third_party/libvpx/source/libvpx/vpx_mem/vpx_mem.c:60:10
    #2 0x1492e12 in vp8_alloc_frame_buffers third_party/libvpx/source/libvpx/vp8/common/alloccommon.c:90:7
    #3 0x149126c in vp8_decode third_party/libvpx/source/libvpx/vp8/vp8_dx_iface.c:374:13
    #4 0x14d42c5 in vpx_codec_decode third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c:116:11
    #5 0x148c0a1 in webrtc::LibvpxVp8Decoder::Decode(webrtc::EncodedImage const&, bool, webrtc::RTPFragmentationHeader const*, webrtc::CodecSpecificInfo const*, long) modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc:245:7
    #6 0x1b930b4 in webrtc::VCMGenericDecoder::Decode(webrtc::VCMEncodedFrame const&, long) modules/video_coding/generic_decoder.cc:233:29
    #7 0x1b6fad3 in webrtc::vcm::VideoReceiver::Decode(webrtc::VCMEncodedFrame const&) modules/video_coding/video_receiver.cc:374:19
    #8 0x1b6ff19 in webrtc::vcm::VideoReceiver::Decode(webrtc::VCMEncodedFrame const*) modules/video_coding/video_receiver.cc:340:10
    #9 0x1af33e4 in webrtc::internal::VideoReceiveStream::Decode() video/video_receive_stream.cc:433:41
    #10 0x1aedc8f in webrtc::internal::VideoReceiveStream::DecodeThreadFunction(void*) video/video_receive_stream.cc:410:49
    #11 0x6544d3 in Run rtc_base/platform_thread.cc:163:5
    #12 0x6544d3 in rtc::PlatformThread::StartThread(void*) rtc_base/platform_thread.cc:81
    #13 0x7ff22125e493 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x7493)

Thread T5 (DecodingThread) created by T0 here:
    #0 0x5871ed in __interceptor_pthread_create /b/build/slave/linux_upload_clang/build/src/third_party/llvm/compiler-rt/lib/asan/asan_interceptors.cc:210:3
    #1 0x654760 in rtc::PlatformThread::Start() rtc_base/platform_thread.cc:103:3
    #2 0x1af010e in webrtc::internal::VideoReceiveStream::Start() video/video_receive_stream.cc:227:18
    #3 0x5d9f4d in webrtc::RtpReplay() video/replay.cc:614:19
    #4 0x5dd5fe in main video/replay.cc:700:3
    #5 0x7ff21f8f92b0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202b0)

SUMMARY: AddressSanitizer: heap-use-after-free third_party/libvpx/source/libvpx/vp8/common/postproc.c:85:37 in vp8_deblock
Shadow bytes around the buggy address:
  0x0c668000d240: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c668000d250: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c668000d260: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c668000d270: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c668000d280: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c668000d290: fd fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c668000d2a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c668000d2b0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c668000d2c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c668000d2d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c668000d2e0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
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
==20098==ABORTING

To reproduce this issue:

1) replace video/replay.cc with the attached version, and build it with asan (ninja -C out/asan video_replay). Note that this file adds the ability to load a full receiver config to the video replay tool, I'm hoping to eventually get this change committed to WebRTC.

2) Download the attached files config3.txt and heapuaf

3) run video_replay --input_file  heapuaf  --config_file config3.txt

This issue affects any browser that supports VP8, and can be reached by loading a single webpage (though some browsers will prompt for permissions). It also affects native clients (such as mobile applications) that use webrtc and support VP8, though the user has to place or answer a video call for their client to be in the state where this issue is reachable.  


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/45121.zip