Lucene search

K
zdtSivertPL1337DAY-ID-29940
HistoryMar 04, 2018 - 12:00 a.m.

VideoLAN VLC Media Player 2.2.5 EphemeralCockroach Heap Overflow Exploit

2018-03-0400:00:00
SivertPL
0day.today
51

0.102 Low

EPSS

Percentile

95.0%

Exploit for windows platform in category dos / poc

==================================================
Date: 02/28/2018
Title: VideoLAN VLC Media Player <= 2.2.5 'EphemeralCockroach' Heap Overflow
CVE: CVE-2017-8311
Exploit and Writeup: Patrick Z. (SivertPL) [[email protected]]
Vulnerability discovery: Yannay Livneh from CheckPoint Security (yannayl) [[email protected]]
Download VLC: https://www.videolan.org/vlc/releases/2.2.4.html (for example, any lower or equal to 2.2.5 will do)
CWE: CWE-199 (Heap-Based Buffer Overflow)
==================================================


This is the infamous EphemeralCockroach subtitle vulnerability in VLC Media Player which gained notoriety in mid-2017.
There were no public exploits / writeups on this one so I decided it was worth trying.

Media:
https://threatpost.com/subtitle-hack-leaves-200-million-vulnerable-to-remote-code-execution/125868/
http://www.bbc.com/news/technology-40058175

======

Writeup and details on the vulnerability

======

There is a heap buffer overflow in ParseJSS in modules/demux/subtitle.c.
This function is used in a loop for parsing JacoSUB subtitle format files.

This is a combined heap-overflow condition. Due to double-incrementing of psz_text pointer, the null-byte is skipped thus the program fails to stop the loop
which results in IMMEDIATE overflow of the heap buffer into psz_orig heap chunk.

======

VULNERABLE CODE SNIPPET FROM PATCH DIFF IN 2.2.5.1:

Function ParseJSS in modules/demux/subtitle.c.
This is just a snippet but you can find the vulnerable code near the end of the ParseJSS function.

======
/* All variables in the following code are named using the hungarian notation (type_name, ex. i_size stands for INT size, psz_text stands for a null-terminated string) */


for( ; *psz_text != '\0' && *psz_text != '\n' && *psz_text != '\r'; ) // If psz_text is not null byte, newline or carriage return then this loop will keep going (IMPORTANT, but keep reading)
{
    switch( *psz_text )
    {
    case '{':
        p_sys->jss.i_comment++;
        break;
    case '}':
        if( p_sys->jss.i_comment )
        {
            p_sys->jss.i_comment = 0;
            if( (*(psz_text + 1 ) ) == ' ' ) psz_text++;
        }
        break;
    case '~':
        if( !p_sys->jss.i_comment )
        {
            *psz_text2 = ' ';
            psz_text2++;
        }
        break;
    case ' ':
    case '\t':
        if( (*(psz_text + 1 ) ) == ' ' || (*(psz_text + 1 ) ) == '\t' )
            break;
        if( !p_sys->jss.i_comment )
        {
            *psz_text2 = ' ';
            psz_text2++;
        }
        break;
    case '\\':
        if( (*(psz_text + 1 ) ) == 'n' )
        {
            *psz_text2 = '\n';
            psz_text++;
            psz_text2++;
            break;
        }
        if( ( toupper((unsigned char)*(psz_text + 1 ) ) == 'C' ) ||
                ( toupper((unsigned char)*(psz_text + 1 ) ) == 'F' ) )
        {
            psz_text++;
            break;
        }
        if( (*(psz_text + 1 ) ) == 'B' || (*(psz_text + 1 ) ) == 'b' ||
            (*(psz_text + 1 ) ) == 'I' || (*(psz_text + 1 ) ) == 'i' ||
            (*(psz_text + 1 ) ) == 'U' || (*(psz_text + 1 ) ) == 'u' ||
            (*(psz_text + 1 ) ) == 'D' || (*(psz_text + 1 ) ) == 'N' )
        {
            psz_text++;
            break;
        }

        /* VULNERABLE CODE BELOW */
        if( (*(psz_text + 1 ) ) == '~' || (*(psz_text + 1 ) ) == '{' ||
            (*(psz_text + 1 ) ) == '\\' )
            psz_text++;
        else if( *(psz_text + 1 ) == '\r' ||  *(psz_text + 1 ) == '\n' || // If it ends with \r or \n, that's OK because there's still \0 afterwards.
                 *(psz_text + 1 ) == '\0' ) // but not in this case...
        {
            // We assume *(psz_text + 1) == '\0' at the moment
            psz_text++;
            /*
            * After incrementing the ptr, *psz_text == '\0' at the moment.
            * We have reached the end of the string
            * RIGHT NOW the code lands on the arrow-marked section.
            * FROM: -->
            */
        }
        break;
    default:
        if( !p_sys->jss.i_comment )
        {
            *psz_text2 = *psz_text;
            psz_text2++;
        }
    }
    /*
    * TO: <--
    * It DOESN'T matter what has happened before, it's still going to land in this section.
    * We assume *psz_text == '\0' atm, so we have reached the end of the string (and thus the end of the buffer !!)
    */

    psz_text++;

    /*
    * BOOM!
    * *(psz_text + 1) = 1 byte overflow into psz_orig (the buffer right after psz_text, look at the original code of the patch)
    * BUT The most important aspect of this overflow, is that
    * Right now, the check in the loop at the beginning will PASS, because we've skipped the null terminator and the loop will KEEP GOING !!!
    */

}

========

PoC

========

Successful exploitation leading to RCE is difficult, nevertheless possible.
The vulnerability poses a challenge because of:
- All mitigations are enabled (ASLR, DEP etc) and need to be bypassed
- The format is SCRIPTLESS
- Multi threading is implemented

For creating a PoC you need to create a JacoSUB subtitle file and load it in VLC. The specification for this ancient format is below:
http://unicorn.us.com/jacosub/jscripts.html

You need to overflow at least 32 bytes into the psz_orig buffer to crash the player.

======

About me

=======


My name is Patrick and I'm a 17 year old Polish-American wannabe hacker/security researcher.
I understand that I need a lot of patience and practice to master this field.

Therefore I'm looking for a security research team or someone EXPERIENCED in the field to help me out.
My dream is to join a good security-research / ethical hacker group with experienced people.

I've participated in NETGEAR Cash Rewards bug bounty at bugcrowd.com and submitted 8 valid vulnerabilities.

Some of my CVEs are:
- CVE-2017-6077
- CVE-2017-6334
- CVE-2017-6366
All of these are published on exploit-db and these are my first vulnerabilities EVER published (not including bug-bounty ones)

Contact me at [email protected], I really appreciate ANYONE who wishes to include me in their team!

Thank you, publishing my work on this website means A LOT to me.

=======



#  0day.today [2018-04-09]  #