6月24號的時候hackerone網站上公佈了一個ffmpeg的本地文件泄露的漏洞,能夠影響ffmpeg不少版本,包括3.2.二、3.2.五、3.1.二、2.6.8等等。html
hackerone網站上的漏洞介紹: https://hackerone.com/reports...。與之相關聯的還有其餘幾篇hackerone上的漏洞報告:https://hackerone.com/reports...、https://hackerone.com/reports...python
實際上這個漏洞@EmilLerner和@PavelCheremushkin最先在今年的phdays大會上就已經披露了,視頻能夠在https://www.phdays.com/broadc...搜索Attacks on video converter獲得,不過是全俄語的,暫時沒有英文字母。也能夠參考漏洞做者在phday大會上的pptgit
做者實際上在5月份的時候就發現了該漏洞並提交,6月26號的時候公佈出來,最新的ffmpeg版本3.3.2中已經修復了,可是舊的版本不保證。github
背景介紹
FFmpeg是一套目前很是流行的能夠用來記錄、轉換數字音頻、視頻,並能將其轉化爲流的開源計算機程序。它提供了錄製、轉換以及流化音視頻的完整解決方案。目前有很是多的視音頻軟件或是視頻網站、手機 APP 都採用了這個庫,可是這個庫歷史上曝出的漏洞也很是之多。此次的漏洞是利用了ffmpeg能夠處理 HLS 播放列表的功能,在 AVI 文件中的 GAB2字幕塊中嵌入了一個 HLS 文件,而後提供給ffmpeg進行轉碼,在解析的過程當中把它當作一個 XBIN 的視頻流來處理,再經過 XBIN 的編解碼器把本地的文件包含進來,最後放在轉碼後的視頻文件當中。安全
漏洞重現方法
1) 下載腳本 https://github.com/neex/ffmpe...
2) 運行腳本:python3 gen_xbin_avi.py file:///etc/passwd sxcurity.avi
3) 訪問https://arxius.io,上傳sxcurity.avi
4) 等待上傳處理視頻
5) 錄像處理完成後,點擊播放就能夠看到/etc/passwd的內容服務器
溫故而知新
此次的漏洞實際上與以前曝出的一個 CVE 很是之相似,能夠說是舊瓶裝新酒,老樹開新花。ide
以前漏洞的一篇分析文章:
SSRF 和本地文件泄露(CVE-2016-1897/8)http://static.hx99.net/static...函數
這個漏洞實際上也是利用了ffmpeg在處理 HLS 播放列表文件的過程當中,因爲支持很是多的協議,如http、file、concat等等,致使能夠構造惡意的url形成 SSRF 攻擊和本地文件泄露。下面這幅圖介紹了整個的攻擊流程。
網站
官方對這個漏洞的修復是把concat協議加入了黑名單並在結構體中加入了protocol_blacklist和protocol_whitelist這兩個域。可是此次的漏洞利用了內嵌在字幕塊中的 m3u8文件成功繞過了ffmpeg的某些限制。this
HLS 協議簡單介紹
HLS(HTTP Live Streaming)是蘋果公司針對iPhone、iPod、iTouch和iPad等移動設備而開發的基於HTTP協議的流媒體解決方案。在 HLS 技術中 Web 服務器向客戶端提供接近實時的音視頻流。但在使用的過程當中是使用的標準的 HTTP 協議,因此這時,只要使用 HLS 的技術,就能在普通的 HTTP 的應用上直接提供點播和直播。該技術基本原理是將視頻文件或視頻流切分紅小片(ts)並創建索引文件(m3u8)。客戶端會先向服務器請求 m3u8索引文件,而後根據索引文件裏面的url去請求真正的ts視頻文件。若是是多級的m3u8索引的話,那就會從根索引文件開始,一層一層的往下去請求子的索引文件,獲取最終的TS流文件的http請求地址與時間段。
M3U8文件中有不少TAG,每個 TAG 的詳細的做用能夠參考這篇文章:http://blog.csdn.net/cabbage2...
針對ffmpeg 3.1.2版本的漏洞分析
先介紹一下ffmpeg是怎樣把一個輸入文件轉碼成另外一種格式的視頻文件,流程圖以下:(圖片引用自http://blog.csdn.net/leixiaoh...)
而後咱們觀察一下攻擊者提供的poc生成的sxcurity.avi文件的結構
最開始是 AVI 文件的文件頭,而後中間有一個 GAB2字幕的文件頭「GAB2」,在 GAB2的文件頭後面還有 HLS 播放列表的文件頭"#EXTM3U",在文件頭後面就是 HLS 的文件內容了。
此次的漏洞主要是利用了ffmpeg處理 GAB2字幕塊的時候的邏輯錯誤,因此咱們重點從ffmpeg打開輸入文件時調用 read_gab2sub()這個函數開始分析,read_gab2sub() 函數是被avformat_find_stream_info() 這個函數調用的。整個函數調用流程圖以下:
咱們能夠看到在爲播放列表肯定demuxer的時候探測出格式爲XBIN,可是單看sxcurity.avi文件中並無 XBIN 的文件頭,那麼ffmpeg是怎麼肯定格式是 XBIN 的呢。這就與 HLS 的解析過程密切相關了。在判斷一個播放列表的格式時候,ffmpeg會讀取播放列表的第一個segment,而後根據這個 segment 的url去請求文件內容,而後根據讀取到的文件內容來判斷格式。
咱們能夠看到sxcurity.avi裏面內嵌的 playlist 的前幾行是這樣寫的
/dev/zero
以#EXT開頭的都是m3u8文件中的標籤,其餘以#開頭的是註釋,不以#開頭的是一個url
介紹一下上面出現的標籤的含義
那麼上面幾行代碼包括了兩個segment,每個 segment 都須要使用 AES-128進行解密,密文是從/dev/zero這個 url獲取的16個字節,其實就是16個'0', key 也是從/dev/zero這個url獲取的16個字節,16個'0',IV是本身指定的一串十六進制數。ffmpeg對第一個 segment 進行解密後的結果是b'XBINx1a x00x0fx00x10x04x01x00x00x00x00', 和漏洞做者在註釋中給出的同樣。前四個字節 XBIN 就是 XBIN 的文件頭。從而使得ffmpeg斷定這個播放列表的格式是 XBIN。
在open_input_file的函數結尾,程序會調用av_dump_format函數打印格式信息,打印結果以下
Input #0, avi, from '../sxcurity.avi':
Duration: 00:00:05.00, start: 0.000000, bitrate: 547 kb/s
Stream #0:0: Video: xbin, pal8, 256x240, 25 tbr, 25 tbn, 25 tbc
能夠看到文件中只有一個視頻流,視頻流的格式編碼格式被識別成了xbin
在打開輸入文件和打開輸出文件以後,程序就要開始進行轉碼工做了
在進行轉碼的過程當中,咱們能夠在get_input_packet函數上下斷點,該函數的做用是獲取輸入的一幀壓縮的視頻數據放在AVPacket中。
gdb-peda$ bt
get_input_packet() 調用結束以後打印pkt的內容,能夠看到裏面已經有了/etc/passwd文件的開頭的部分信息。
而後 ffmpeg會轉碼成mpeg2的編碼格式,最後封裝成一個 mp4文件。打開 MP4文件,咱們就能看到泄露出的文件內容了。
不轉碼的avi文件也是能夠播放的,只是他播放的文件是當前調用ffmpeg的應用,例如你用愛奇藝打開就是調用愛奇藝的播放器,而愛奇藝是用了ffmpeg代碼,就能夠讀到愛奇藝應用的的內部文件,就形成信息泄露,由於這些文件是沒有權限讀取的。
例如能夠讀到data/data/com.qiyi.video/shared_prefs/cn.com.mma.mobile.tracking.sdkconfig.xml
而轉碼的目的就是把你上傳視頻的服務器文件寫死在轉碼後的文件,就是你不管轉成.mp4,flv均可以播放的。
另外一種攻擊方式
攻擊者針對https://hackerone.com/reports...這個洞的 fix 又提出了另外一種 bypass 方式https://hackerone.com/reports...。這個方式比起使用xbin的方法要來的更加簡潔。
此次的 POC 生成的playlist長下面這樣
GOD.txt
/etc/passwd
翻譯一下做者在評論區的說明:
首先咱們有幾點須要瞭解關於HLS playlist 是怎麼被處理的:
1.處理一個 playlist 的時候ffmpeg把全部 segment 的內容鏈接在一塊兒而後當作一個單獨的文件來處理
2.ffmpeg會使用 playlist 第一個 segment 來決定文件的類型
3.ffmpeg用一種特殊的方式來處理.txt後綴的文件,它會嘗試將文件的內容以終端的方式打印在屏幕上
因此上面的 playlist 的處理流程是這樣的:
1.ffmpeg在 GAB2字幕塊裏面看到了#EXTM3U標籤,認定文件類型是 HLS playlist。
2.GOD.txt這個文件甚至不須要存在,可是它的名字足夠ffmpeg把文件類型檢測成txt類型了
3.ffmpeg把 playlist 的全部 segment 的內容鏈接在一塊兒,由於只有/etc/passwd這個文件是實際存在的,因此最後的內容就是/etc/passwd文件的內容
4.由於這個文件的類型是 txt 類型,因此ffmpeg繪製一個終端來打印這個文件。
須要注意的是在解析 playlist 文件的時候,每個 segment 的url協議d的白名單爲'file, crypto',因此這裏直接把/etc/passwd改爲http://vul.com:21進行ssrf攻擊是行不通的。
對官方補丁的分析
補丁連接:https://github.com/FFmpeg/FFm...
官方對這個漏洞的修復也很簡單,只是對播放列表中 file 協議的文件擴展名使用了白名單進行過濾。必定程度上緩解了攻擊,可是仍是能夠泄露出那些多媒體文件。
typedefstructHLSContext {
//...省略了一下結構體的內容
staticintopen_url(AVFormatContext s, AVIOContext pb, constchar url,
AVDictionary opts, AVDictionary opts2, int *is_http)
{
//...
// only http(s) & file are allowed
+
//...
}
總結
這個漏洞和以往的核心是m3u8文件能夠根據指定url獲取圖片文字,而它裏面的http協議和file協議沒有過濾好,致使能夠ssrf和讀取任意文件,之前的漏洞是利用concat能夠把泄露的信息傳回給攻擊者,這個是經過播放視頻,能夠把信息展現給攻擊者。之後會有可能用別的方式觸發ffmpeg的別的流程,繞過file協議的過濾。
參考資料
http://blogs.360.cn/blog/ffmp...
https://github.com/radman1/xbin
https://hackerone.com/reports...
http://static.hx99.net/static...
https://tools.ietf.org/html/d...
http://blog.csdn.net/cabbage2...
http://blogs.360.cn/blog/ffmp...
XBIN 文件格式的詳細介紹:https://en.wikipedia.org/wiki...