As part of my internship with Security Innovation, I wanted to better understand security challenges in media players. With a user base in the hundreds of millions, and access to open source code, VLC was an ideal choice.
In my research, the first aspect of testing concentrated on fuzzing inputs. Driven by time constraints and following the recommendations of colleagues and other expert resources, AFL, an open source fuzzer, was the best choice for security-relevant fuzzing. After binary instrumentation, non-crashing inputs are manually provided as seed input to AFL. AFL then performed the actual fuzzing to discover any crashing input for the target binary. I chose the initial test cases find crashes and hangs within the VLC application with the goal of exposing vulnerabilities in VLC.
To get effective fuzzing results, optimization was needed. First, the VLC binary was instrumented with AFL using only necessary libraries and modules for specific input. Next, a dictionary file could be passed to AFL to generate crashing inputs properly. This helped in generating compatible small size inputs which enhanced fuzzing speed while maintaining certain information like headers, keywords, etc. Additionally, parallel fuzzing was used for efficiency, allowing multiple CPU cores to be utilized simultaneously. Finally, seeding AFL with relevant inputs like minimal size AVIs, different delimiters in string etc. was vital to ensure that early-stage fuzzing would generate reasonable test cases.
In addition to these optimizations, certain tweaks aided in streamlining the fuzzing environment. VLC streams were redirected to /dev/null in order to prevent the GUI from displaying. Next, a VLC command line argument vlc://quit was used to automatically close the VLC window once the file was played. For rendering fuzzed cases efficiently, a lightweight dummy interface was used.
afl-fuzz -t60000 -m2048 -i in_sub_1 -o out_sub -M fuzzer1 ./bin/vlc-static -q -I dummy @@--sout=’#transcode{venc={profile=baseline},vcodec=”h264”, vb=800,acodec=mpga, ab=128}:standard{access=”file”,mux=”mp4”,dst=/dev/null}’ vlc://quit
Prior to fuzzing activities, I identified key attack surfaces for fuzzing inputs. s. Primarily, the header sections of media files were found to be an ideal entry point for fuzzing. Secondarily, the online streaming URL input was found to be another avenue for attack. Another consideration for attack was VLC's configuration file. Additionally, since VLC allows for a command-line argument to supply a related subtitles file, this file was considered a promising attack vector as well.
After researching popular media file formats such as MP4 and AVI, I created seed files by malforming different permutations of their header and data fields. These seed were created with minimal size requirement and format acceptable in VLC. These inputs were used by AFL to generate closely related test cases. The header manipulation primarily focused on video framerates, durations, and frame sizes.
Having chosen handling of provided URLs as the next attack vector, I generated several fuzzing test cases to act as seeds for AFL to fuzz with. Below listed URLs hinted AFL to fuzz inputs to include certain delimiting characters which could identify parsing vulnerabilities, if any, in its module.
https://www.youtube.com/watch?v=awefdef
https://www.youtube.com\0/watch?v=awefdef
https://www.youtube.com/watch?
https://www.youtube\x89\x78.com/watch?v=awefdef
https://www.youtube.com/watch?v=awefdef
https://www\n][.youtube.com/watch?v=awefdef
The next attack vector focused on the VLC configuration file. This file is used to load various previously-stored user preferences into VLC upon program startup.
As mentioned, the final and most promising fuzzing input tested was the subtitles file. Research on known CVEs for VLC (CVE-2017-8311, CVE-2017-8312, and CVE-2017-8313), combined with static code analysis, indicated a high concentration of string-parsing logic. This in turn indicated increased opportunities for missing security checks or vulnerable logic. VLC uses around 21 different subtitle formats. Among those, JacoSub(JSS) was an interesting one. The recent CVEs listed above appeared in JSS parsing module of VLC. Additionally, it involved a lot of string parsing logic. AFL needed to be seeded with a dictionary for JSS files specifying formats and keywords.
Fuzzing JSS files gave better results than fuzzing MP4s, AVIs, configuration files or input URLs. It led to discovery of a dangling pointer dereferencing vulnerability. As shown below with the debug keyword "stuck," the VLC JSS parsing module attempted to read a module, "ItemPropertiesUpdated," outside of its data-space. However, this code appears to be fixed in the git repository for VLC, despite not being fixed in the latest vlc-2.2.6 source code.
stuck?I
stuck?t
stuck?e
stuck?m
stuck?P
stuck?r
stuck?o
stuck?p
stuck?e
stuck?r
stuck?t
..
I found a second vulnerability by fuzzing the JSS parsing module. In particular, certain input can trigger a floating point exception and cause VLC to crash.
Static code analysis flagged a potential integer-overflow in the transcode module of VLC, where an integer is processed after passing through a simple less-than operator. Although no security vulnerability was identified, its presence shed some light on some of the underlying implementation or a code flaw.
p_sys->i_vbitrate= var_GetInteger( p_stream, SOUT_CFG_PREFIX "vb" );
if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1
After running the tool for 24 hours using the configuration described above, AFL completed one fuzzing cycle and discovered more than 6000 paths, resulting in approximately 20 crashing inputs and 5 inputs reliably hanging the target. The crashes corresponded to Floating Point Exception (FPE) which didn’t pose a threat to VLC. However, more fuzzing cycles may be obtainable through favored fuzzing path customization, function-specific instrumentation, more CPU cores and the CPU time. It will be promising to explore more paths and different crashes apart from FPE as well. In addition, other tools may yield more useful results. Peach Fuzzer would be another opportunity to test fuzzed inputs. Pin is a tool that may be used for dynamic binary instrumentation. Finally, Klee, which uses symbolic execution, could be used to determine a path to a target location in code.
Written by Swati Laxmi, Security Innovation Intern