Exploit-DB #45443
Description: WebRTC - VP9 Processing Use-After-Free
Type: dos
Platform: multiple
Date: 2018-09-21
Author: Google Security Research

Exploit:
There is a use-after-free in VP9 processing in WebRTC. In the method RtpFrameReferenceFinder::ManageFrameVp9 the following code occurs:

 auto gof_info_it = gof_info_.find((codec_header.temporal_idx == 0)
                                          ? codec_header.tl0_pic_idx - 1
                                          : codec_header.tl0_pic_idx);

   ... // snip

    info = &gof_info_it->second;
  }

  // Clean up info for base layers that are too old.
  uint8_t old_tl0_pic_idx = codec_header.tl0_pic_idx - kMaxGofSaved;
  auto clean_gof_info_to = gof_info_.lower_bound(old_tl0_pic_idx);
  gof_info_.erase(gof_info_.begin(), clean_gof_info_to);

  FrameReceivedVp9(frame->id.picture_id, info);

tl0_pic_idx is extracted from the incoming packet, and it if is higher than any picture id that exists in gof_info_, the entire vector will be erased, and info will be used in the call FrameReceivedVp9 even though it has been freed.

ASAN output:

==163231==ERROR: AddressSanitizer: heap-use-after-free on address 0x[PII_REDACTED]d0 at pc 0x0000014b0e1e bp 0x7ffe607dfd30 sp 0x7ffe607dfd28
READ of size 2 at 0x[PII_REDACTED]d0 thread T0
    #0 0x14b0e1d in webrtc::video_coding::RtpFrameReferenceFinder::FrameReceivedVp9(unsigned short, webrtc::video_coding::RtpFrameReferenceFinder::GofInfo*) modules/video_coding/rtp_frame_reference_finder.cc:569:31
    #1 0x14ac2c5 in webrtc::video_coding::RtpFrameReferenceFinder::ManageFrameVp9(webrtc::video_coding::RtpFrameObject*) modules/video_coding/rtp_frame_reference_finder.cc:499:3
    #2 0x14a7849 in ManageFrameInternal modules/video_coding/rtp_frame_reference_finder.cc:89:14
    #3 0x14a7849 in webrtc::video_coding::RtpFrameReferenceFinder::ManageFrame(std::__1::unique_ptr<webrtc::video_coding::RtpFrameObject, std::__1::default_delete<webrtc::video_coding::RtpFrameObject> >) modules/video_coding/rtp_frame_reference_finder.cc:43
    #4 0x148a87e in non-virtual thunk to webrtc::RtpVideoStreamReceiver::OnReceivedFrame(std::__1::unique_ptr<webrtc::video_coding::RtpFrameObject, std::__1::default_delete<webrtc::video_coding::RtpFrameObject> >) video/rtp_video_stream_receiver.cc:336:22
    #5 0x1496f41 in webrtc::video_coding::PacketBuffer::InsertPacket(webrtc::VCMPacket*) modules/video_coding/packet_buffer.cc:130:31
    #6 0x1487e59 in webrtc::RtpVideoStreamReceiver::OnReceivedPayloadData(unsigned char const*, unsigned long, webrtc::WebRtcRTPHeader const*) video/rtp_video_stream_receiver.cc:231:19
    #7 0x12d9144 in webrtc::RTPReceiverVideo::ParseRtpPacket(webrtc::WebRtcRTPHeader*, webrtc::PayloadUnion const&, unsigned char const*, unsigned long, long) modules/rtp_rtcp/source/rtp_receiver_video.cc:109:26
    #8 0x12cc80d in webrtc::RtpReceiverImpl::IncomingRtpPacket(webrtc::RTPHeader const&, unsigned char const*, unsigned long, webrtc::PayloadUnion) modules/rtp_rtcp/source/rtp_receiver_impl.cc:181:42
    #9 0x1488e52 in webrtc::RtpVideoStreamReceiver::ReceivePacket(unsigned char const*, unsigned long, webrtc::RTPHeader const&) video/rtp_video_stream_receiver.cc:399:20
    #10 0x1488b03 in webrtc::RtpVideoStreamReceiver::OnRecoveredPacket(unsigned char const*, unsigned long) video/rtp_video_stream_receiver.cc:245:3
    #11 0x14b925c in webrtc::UlpfecReceiverImpl::ProcessReceivedFec() modules/rtp_rtcp/source/ulpfec_receiver_impl.cc:244:35
    #12 0x148bd42 in webrtc::RtpVideoStreamReceiver::ParseAndHandleEncapsulatingHeader(unsigned char const*, unsigned long, webrtc::RTPHeader const&) video/rtp_video_stream_receiver.cc:421:23
    #13 0x1488d51 in webrtc::RtpVideoStreamReceiver::ReceivePacket(unsigned char const*, unsigned long, webrtc::RTPHeader const&) video/rtp_video_stream_receiver.cc:390:5
    #14 0x14899f8 in webrtc::RtpVideoStreamReceiver::OnRtpPacket(webrtc::RtpPacketReceived const&) video/rtp_video_stream_receiver.cc:290:3
    #15 0x90c486 in webrtc::RtpDemuxer::OnRtpPacket(webrtc::RtpPacketReceived const&) call/rtp_demuxer.cc:157:11
    #16 0x9131bd in webrtc::RtpStreamReceiverController::OnRtpPacket(webrtc::RtpPacketReceived const&) call/rtp_stream_receiver_controller.cc:55:19
    #17 0x129940d in webrtc::internal::Call::DeliverRtp(webrtc::MediaType, rtc::CopyOnWriteBuffer, webrtc::PacketTime const&) call/call.cc:1321:36
    #18 0x129a8d5 in webrtc::internal::Call::DeliverPacket(webrtc::MediaType, rtc::CopyOnWriteBuffer, webrtc::PacketTime const&) call/call.cc:1361:10
    #19 0x61fe06 in webrtc::RtpReplay() video/replay.cc:279:31
    #20 0x62337d in main video/replay.cc:343:3
    #21 0x7f5ae03d82b0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202b0)

0x[PII_REDACTED]d0 is located 48 bytes inside of 56-byte region [0x[PII_REDACTED]a0,0x[PII_REDACTED]d8)
freed by thread T0 here:
    #0 0x61bbb2 in operator delete(void*) /b/build/slave/linux_upload_clang/build/src/third_party/llvm/compiler-rt/lib/asan/asan_new_delete.cc:150:3
    #1 0x14ac26c in __libcpp_deallocate buildtools/third_party/libc++/trunk/include/new:279:10
    #2 0x14ac26c in deallocate buildtools/third_party/libc++/trunk/include/memory:1802
    #3 0x14ac26c in deallocate buildtools/third_party/libc++/trunk/include/memory:1556
    #4 0x14ac26c in erase buildtools/third_party/libc++/trunk/include/__tree:2370
    #5 0x14ac26c in erase buildtools/third_party/libc++/trunk/include/__tree:2379
    #6 0x14ac26c in erase buildtools/third_party/libc++/trunk/include/map:1200
    #7 0x14ac26c in webrtc::video_coding::RtpFrameReferenceFinder::ManageFrameVp9(webrtc::video_coding::RtpFrameObject*) modules/video_coding/rtp_frame_reference_finder.cc:497
    #8 0x14a7849 in ManageFrameInternal modules/video_coding/rtp_frame_reference_finder.cc:89:14
    #9 0x14a7849 in webrtc::video_coding::RtpFrameReferenceFinder::ManageFrame(std::__1::unique_ptr<webrtc::video_coding::RtpFrameObject, std::__1::default_delete<webrtc::video_coding::RtpFrameObject> >) modules/video_coding/rtp_frame_reference_finder.cc:43
    #10 0x148a87e in non-virtual thunk to webrtc::RtpVideoStreamR