New issue
Advanced search Search tips

Issue 752075 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner:
Closed: Aug 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Task



Sign in to add a comment

The ff_amf_get_field_value function in libavformat/rtmppkt.c in FFmpeg 3.3.2 allows remote RTMP servers to cause a denial of service (Segmentation Violation and application crash) via a crafted stream.

Reported by codingma...@gmail.com, Aug 3 2017

Issue description

UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36

Steps to reproduce the problem:
I am attaching evil_ffmpeg_server.py and crash-9238fa9e8d4fde3beda1f279626f53812cb001cb-SEGV that reproduce the crash.

    $ python ./evil_ffmpeg_server.py crash-9238fa9e8d4fde3beda1f279626f53812cb001cb-SEGV 1935
    $ ./ffmpeg -v trace -i "rtmp://localhost/live/hks" 1.flv

What is the expected behavior?
The client receives a segmentation fault when parsing data which is received from the server and terminated.

What went wrong?
Below is the stack trace printed using ASAN(Address Sanitizer).

    INFO: Seed: 576883329
    INFO: Loaded 1 modules (234829 guards): [0x4c1bc80, 0x4d011b4),
    ./ffmpeg-3.3.2-rtmp-fuzzer: Running 1 inputs 1 time(s) each.
    Running: crash/crash-9238fa9e8d4fde3beda1f279626f53812cb001cb-SEGV
    =================================================================
    ==20014==ERROR: AddressSanitizer: SEGV on unknown address 0x60d06b66e43c (pc 0x000000e5dc59 bp 0x7fff99128ab0 sp 0x7fff99128740 T0)
    ==20014==The signal is caused by a READ memory access.
        #0 0xe5dc58 in ff_amf_get_field_value /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/rtmppkt.c:486:12
        #1 0xdeca73 in handle_invoke_status /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/rtmpproto.c:2156:9
        #2 0xde9818 in handle_invoke /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/rtmpproto.c:2191:20
        #3 0xde3506 in rtmp_parse_result /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/rtmpproto.c:2353:20
        #4 0xddb621 in get_packet /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/rtmpproto.c:2461:15
        #5 0xdced3a in rtmp_open /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/rtmpproto.c:2839:15
        #6 0xd8d355 in ffurl_connect /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/avio.c:206:31
        #7 0xd90dc9 in ffurl_open_whitelist /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/avio.c:347:11
        #8 0x5bc523 in ffio_open_whitelist /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/aviobuf.c:1066:11
        #9 0xa92208 in io_open_default /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/options.c:124:12
        #10 0xc67fe9 in init_input /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/utils.c:417:16
        #11 0xc6533c in avformat_open_input /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/utils.c:538:16
        #12 0x5133b4 in LLVMFuzzerTestOneInput /home/jundong/fuzzing_libs/ffmpeg-3.3.2/rtmp_fuzz/ffmpeg_rtmp_fuzzer.cpp:120:13
        #13 0x40a39e4 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/jundong/Fuzzer/FuzzerLoop.cpp:460:13
        #14 0x40a3c53 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long) /home/jundong/Fuzzer/FuzzerLoop.cpp:399:3
        #15 0x4098991 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /home/jundong/Fuzzer/FuzzerDriver.cpp:268:6
        #16 0x409c6a4 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/jundong/Fuzzer/FuzzerDriver.cpp:683:9
        #17 0x4098700 in main /home/jundong/Fuzzer/FuzzerMain.cpp:20:10
        #18 0x7f41f886b439 in __libc_start_main (/usr/lib/libc.so.6+0x20439)
        #19 0x41f859 in _start (/home/jundong/fuzzing_libs/ffmpeg-3.3.2/rtmp_fuzz/ffmpeg-3.3.2-rtmp-fuzzer+0x41f859)

    AddressSanitizer can not provide additional info.
    SUMMARY: AddressSanitizer: SEGV /home/jundong/fuzzing_libs/ffmpeg-3.3.2/BUILD/libavformat/rtmppkt.c:486:12 in ff_amf_get_field_value
    ==20014==ABORTING

The problem is inside the handle_invoke_status() function (libavformat/rtmpproto.c)

    		static int handle_invoke_status(URLContext *s, RTMPPacket *pkt) {
              //...
    2149	    for (i = 0; i < 2; i++) {
    2150	        t = ff_amf_tag_size(ptr, data_end);
    2151	        if (t < 0)
    2152	            return 1;
    2153	        ptr += t;
    2154	    }
               t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));

In the for loop, 'ptr' increases by 't' returned from ff_amf_tag_size() function, variable 't' can be an arbitrary value which is greater than or equal to zero. Before the loop, 'ptr' points to the middle of an RTMPPacket and varibale 'data_end' points to the end of an RTMPPacket. However, after the loop, 'ptr' may be go beyond the end of the RTMPPacket. Then 'ptr' is passed into the ff_amf_get_field_value() function directly without any check.

Next, we have a look at into the ff_amf_get_field_value() function and see where the segmantation fault is triggered.

    480	int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end,
    481	                           const uint8_t *name, uint8_t *dst, int dst_size)
    482	{
    483	    int namelen = strlen(name);
    484	    int len;
    485	
    486	    while (*data != AMF_DATA_TYPE_OBJECT && data < data_end) {
    487	        len = ff_amf_tag_size(data, data_end);

In line 486, there is a while loop. Variable 'data' equals to the 'ptr' mentioned above. It is beyond the end of the RTMPPacket and may point to an unmapped memory address. When deferencing it, a segmentation fault is triggered.

Affects:

This vulnerability may affect lots of software(e.g, VLC Media Player) which uses FFmpeg library.

suggested patch method:

Add a check before calling ff_amf_get_field_value() function. Check that if 'ptr' is less than 'data_end'. At the same time, I suggest that line 486 of ff_amf_get_field_value() function is supposed to be modified. We should first check that 'data' is less than 'data_end', then deference the 'data' pointer.

Besides, there are also many out-of-bound reading errors due to lack of checking if the pointer is pointing inside the RTMPPacket and if there are enough bytes to read before reaching the end of the RTMPPacket.

There are four places in the code below which may produce an out-of-boud reading error.

    436	int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)
    437	{
    438	    const uint8_t *base = data;
    439	    AMFDataType type;
    440	    unsigned nb   = -1;
    441	    int parse_key = 1;
    442	
    443	    if (data >= data_end)
    444	        return -1;
    445	    switch ((type = *data++)) {
    446	    case AMF_DATA_TYPE_NUMBER:      return 9;
    447	    case AMF_DATA_TYPE_BOOL:        return 2;
    448	    case AMF_DATA_TYPE_STRING:      return 3 + AV_RB16(data);	//may produce an out-of-bound reading error here.
    449	    case AMF_DATA_TYPE_LONG_STRING: return 5 + AV_RB32(data);   //may produce an out-of-bound reading error here.

    450	    case AMF_DATA_TYPE_NULL:        return 1;
    451	    case AMF_DATA_TYPE_DATE:        return 11;
    452	    case AMF_DATA_TYPE_ARRAY:
    453	        parse_key = 0;
    454	    case AMF_DATA_TYPE_MIXEDARRAY:
    455	        nb = bytestream_get_be32(&data);//may produce an out-of-bound reading error here.
    456	    case AMF_DATA_TYPE_OBJECT:
    457	        while (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY) {
    458	            int t;
    459	            if (parse_key) {
    460	                int size = bytestream_get_be16(&data);//may produce an out-of-bound reading error here.

Did this work before? N/A 

Chrome version: 59.0.3071.115  Channel: stable
OS Version: OS X 10.12.5
Flash Version: Shockwave Flash 26.0 r0

The first attachment is the description of the detail of this vulnerability. The second is the reproducer testcase. Third is a script that emulates a malicious server.
 
info.txt
7.8 KB View Download
crash-9238fa9e8d4fde3beda1f279626f53812cb001cb-SEGV.bin
4.5 KB Download
evil_rtmp_server.py
1.2 KB View Download
Components: Internals>Media>FFmpeg
Labels: -Pri-2 Security_Impact-Stable M-61 Security_Severity-High Pri-1
Owner: xhw...@chromium.org
Status: Assigned (was: Unconfirmed)
xhwang, could you take a look at this and assign as appropriate? Thanks.
Cc: xhw...@chromium.org
Owner: chcunningham@chromium.org
Assign to chcunningham who is doing ffmpeg roll.
Project Member

Comment 4 by sheriffbot@chromium.org, Aug 17 2017

chcunningham: Uh oh! This issue still open and hasn't been updated in the last 14 days. This is a serious vulnerability, and we want to ensure that there's progress. Could you please leave an update with the current status and any potential blockers?

If you're not the right owner for this issue, could you please remove yourself as soon as possible or help us find the right one?

If the issue is fixed or you can't reproduce it, please close the bug. If you've started working on a fix, please set the status to Started.

Thanks for your time! To disable nags, add the Disable-Nags label.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
codingman05@gmail.com, thanks for reporting. 

Do you expect that this code path can be reached in Chrome media playback? I don't think this file is actually part of the Chrome build. We don't support FLV. 

See here for a list of files we build into chrome.
https://cs.chromium.org/chromium/src/third_party/ffmpeg/ffmpeg_generated.gni

Still, its for this to get fixed in FFmpeg - have you filed a bug with them?
Labels: -Pri-1 -Security_Impact-Stable -Security_Severity-High -M-61 -Via-Wizard-Security Pri-3
No effect on Chrome -> removing security labels and downgrading to P3. 

Leaving this open to track filing bug upstream (if not already done by codingman05).
Labels: -Type-Bug-Security -OS-Mac Type-Task
I have filed this bug to the FFmpeg.org. It seems like Chrome doesn't build this file into the itself. Thanks for your reply. 
Status: WontFix (was: Assigned)
Thanks! Closing since the ffmpeg bug is filed elsewhere.
Project Member

Comment 10 by sheriffbot@chromium.org, Nov 28 2017

Labels: -Restrict-View-SecurityTeam allpublic
This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot

Sign in to add a comment