这次的漏洞实际上与之前曝出的一个 CVE 非常之类似,可以说是旧瓶装新酒,老树开新花。

之前漏洞的一篇分析文章:

SSRF 和本地文件泄露(CVE-2016-1897/8)http://static.hx99.net/static/drops/papers-15598.html

这个漏洞实际上也是利用了ffmpeg在处理 HLS 播放列表文件的过程中,由于支持非常多的协议,如http、file、concat等等,导致可以构造恶意的url造成 SSRF 攻击和本地文件泄露。下面这幅图介绍了整个的攻击流程。

官方对这个漏洞的修复是把concat协议加入了黑名单并在结构体中加入了protocol_blacklist和protocol_whitelist这两个域。但是这次的漏洞利用了内嵌在字幕块中的 m3u8文件成功绕过了ffmpeg的某些限制。

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/cabbage2008/article/details/50522190

针对ffmpeg 3.1.2版本的漏洞分析

先介绍一下ffmpeg是怎样把一个输入文件转码成另一种格式的视频文件,流程图如下:(图片引用自http://blog.csdn.net/leixiaohua1020/article/details/25422685

然后我们观察一下攻击者提供的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 的前几行是这样写的

#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

以#EXT开头的都是m3u8文件中的标签,其他以#开头的是注释,不以#开头的是一个url

介绍一下上面出现的标签的含义

#EXT-X-MEDIA-SEQUENCE:每一个media URI 在 PlayList中只有唯一的序号,相邻之间序号+1, 一个media URI并不是必须要包含的,如果没有,默认为0。

#EXTINF:  duration 指定每个媒体段(ts)的持续时间(秒),仅对其后面的URI有效。

#EXT-X-KEY表示怎么对mediasegments进行解码。其作用范围是下次该tag出现前的所有mediaURI,属性为NONE或者 AES-128。对于AES-128的情况,URI属性表示一个key文件,通过URI可以获得这个key,如果没有IV(Initialization Vector),则使用序列号作为IV进行编解码;如果有IV,则将改值当成16个字节的16进制数。

那么上面几行代码包括了两个segment,每一个 segment 都需要使用 AES-128进行解密,密文是从/dev/zero这个 url获取的16个字节,其实就是16个'\0', key 也是从/dev/zero这个url获取的16个字节,16个'\0',IV是自己指定的一串十六进制数。ffmpeg对第一个 segment 进行解密后的结果是b'XBIN\x1a \x00\x0f\x00\x10\x04\x01\x00\x00\x00\x00', 和漏洞作者在注释中给出的一样。前四个字节 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
#0  get_input_packet (f=0x6dfc00, pkt=0x7fffffffe460) at ffmpeg.c:3663
#1  0x000000000042d40c in process_input (file_index=0x0) at ffmpeg.c:3798
#2  0x000000000042eed2 in transcode_step () at ffmpeg.c:4108
#3  0x000000000042effc in transcode () at ffmpeg.c:4162
#4  0x000000000042f716 in main (argc=0x4, argv=0x7fffffffea48) at ffmpeg.c:4357
#5  0x00007ffff48a543a in __libc_start_main () from /usr/lib/libc.so.6
#6  0x0000000000407ada in _start ()

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/242831这个洞的 fix 又提出了另一种 bypass 方式https://hackerone.com/reports/243470。这个方式比起使用xbin的方法要来的更加简洁。

这次的 POC 生成的playlist长下面这样

#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:1.0
GOD.txt
#EXTINF:1.0
/etc/passwd
#EXT-X-ENDLIST

翻译一下作者在评论区的说明:

首先我们有几点需要了解关于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/FFmpeg/commit/189ff4219644532bdfa7bab28dfedaee4d6d4021

官方对这个漏洞的修复也很简单,只是对播放列表中 file 协议的文件扩展名使用了白名单进行过滤。一定程度上缓解了攻击,但是还是可以泄露出那些多媒体文件。

typedefstructHLSContext {
            //...省略了一下结构体的内容
 +    char *allowed_extensions; //增添一个字段,限制了允许的文件扩展名
  } HLSContext;
staticintopen_url(AVFormatContext *s, AVIOContext **pb, constchar *url,
AVDictionary *opts, AVDictionary *opts2, int *is_http)
 {
            //...
// only http(s) & file are allowed
 -    if (!av_strstart(proto_name, "http", NULL) && !av_strstart(proto_name, "file", NULL))
 +    if (av_strstart(proto_name, "file", NULL)) {
 +        if (strcmp(c->allowed_extensions, "ALL") && !av_match_ext(url, c->allowed_extensions)) {
 +            av_log(s, AV_LOG_ERROR,
 +                "Filename extension of \'%s\' is not a common multimedia extension, blocked for security reasons.\n"
 +                "If you wish to override this adjust allowed_extensions, you can set it to \'ALL\' to allow all\n",
 +                url);
 +            return AVERROR_INVALIDDATA;
 +        }
 +    } elseif (av_strstart(proto_name, "http", NULL)) {
 +        ;
 +    } else
return AVERROR_INVALIDDATA;
 +
//...
 }

总结

这个漏洞和以往的核心是m3u8文件可以根据指定url获取图片文字,而它里面的http协议和file协议没有过滤好,导致可以ssrf和读取任意文件,以前的漏洞是利用concat可以把泄露的信息传回给攻击者,这个是通过播放视频,可以把信息展示给攻击者。以后会有可能用别的方式触发ffmpeg的别的流程,绕过file协议的过滤。

参考资料

http://blogs.360.cn/blog/ffmpegs_security_discussion/

https://github.com/radman1/xbin

https://hackerone.com/reports/243470

http://static.hx99.net/static/drops/papers-15598.html

https://tools.ietf.org/html/draft-pantos-http-live-streaming-18#userconsent

http://blog.csdn.net/cabbage2008/article/details/50522190

http://blogs.360.cn/blog/ffmpegs_security_discussion/

XBIN 文件格式的详细介绍:https://en.wikipedia.org/wiki/XBin

--------------------------------------------------------

* 作者:栈长、胖苗、超六@蚂蚁金服,更多安全知识分享和热点信息,请关注阿里聚安全的官方博客

FFmpeg任意文件读取漏洞分析的更多相关文章

  1. 安全研究 | Jenkins 任意文件读取漏洞分析

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由云鼎实验室 发表于云+社区专栏 一.漏洞背景 漏洞编号:CVE-2018-1999002 漏洞等级:高危 Jenkins 7 月 18 ...

  2. 【代码审计】大米CMS_V5.5.3 任意文件读取漏洞分析

      0x00 环境准备 大米CMS官网:http://www.damicms.com 网站源码版本:大米CMS_V5.5.3试用版(更新时间:2017-04-15) 程序源码下载:http://www ...

  3. 【代码审计】XYHCMS V3.5任意文件读取漏洞分析

      0x00 环境准备 XYHCMS官网:http://www.xyhcms.com/ 网站源码版本:XYHCMS V3.5(2017-12-04 更新) 程序源码下载:http://www.xyhc ...

  4. 【代码审计】QYKCMS_v4.3.2 任意文件读取漏洞分析

      0x00 环境准备 QYKCMS官网:http://www.qykcms.com/ 网站源码版本:QYKCMS_v4.3.2(企业站主题) 程序源码下载:http://bbs.qingyunke. ...

  5. ffmpeg 任意文件读取漏洞/SSRF漏洞 (CVE-2016-1897/CVE-2016-1898)

    影响版本 在FFMpeg2.X poc http://192.168.49.2:8000/?name={%25%20for%20c%20in%20[].__class__.__base__.__sub ...

  6. PHPMailer命令执行及任意文件读取漏洞

    今天在thinkphp官网闲逛,无意下载了一套eduaskcms,查看了一下libs目录中居然存在PHPMailer-5.2.13,想起了之前看到的PHPMailer的漏洞,可惜这套CMS只提供了一个 ...

  7. 代码审计-MetInfo CMS任意文件读取漏洞

    0x01 代码分析 发现在app\system\include\module\old_thumb.class.php疑似有任意文件读取漏洞 public function doshow(){ glob ...

  8. 蓝凌OA前台任意文件读取漏洞利用

    近期CNVD爆出漏洞编号:CNVD-2021-28277,首次公开日期为2021-04-15,蓝凌oa存在多个漏洞,攻击者可利用该漏洞获取服务器控制权.今天挑选一个蓝凌OA前台任意文件读取漏洞进行分析 ...

  9. Atlassian Confluence任意文件读取漏洞

    Atlassian Confluence Atlassian Confluence是澳大利亚Atlassian公司的一套专业的企业知识管理与协同软件,也可以用于构建企业WiKi.该软件可实现团队成员之 ...

随机推荐

  1. Cordova各个插件使用介绍系列(一)—$cordovaSms发送短信

    详情链接地址:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/cordova-1-cordovasms/ 这是调用手机发送短信的插件 ...

  2. B. Karen and Coffee

    B. Karen and Coffee time limit per test 2.5 seconds memory limit per test 512 megabytes input standa ...

  3. IT学习网站

    网站 网站定位 http://www.51cto.com/ 中国领先的IT技术网站. http://www.iteye.com/ 内容齐全,功能丰富的中文IT技术门户和社区网站. http://www ...

  4. 通过 pxe(网络安装)完成centos 系统的网络安装

    首先交代环境.本地2台主机,一台windows主机,一台等待安装centos的主机.2台主机在同一个局域网.通过路由器自动获取ip上网. 网上大多数pxe安装方式都采用自己搭建dns服务器的方式来进行 ...

  5. 安装gcc提示no acceptable C compiler found in $PATH

    安装gcc提示no acceptable C compiler found in $PATH 从所报错可以看出是缺少了c编译器,因为gcc就是c编译器,所以没有安装gcc就没有c编译器. 之所以报这样 ...

  6. linux下vim 查找命令

    在命令模式下输入/word 这个是查找文件中“word”这个单词,是从文件上面到下面查找?word 这个是查找文件中“word”这个单词,是从文件下上面到面查找

  7. a链接返回上一页

    <a href="javascript:void(0);" onclick="javascript:history.go(-1);" style='mar ...

  8. php变量双击选择无法选择$符号

    创建/Data/Packages/User/PHP.sublime-settings文件,内容为 {     "word_separators": "./\\()\&qu ...

  9. Appcan开发笔记:结合JQuery的$.Deferred()完善批量异步发送

    appcan的 uexXmlHttpMgr.send 或者 appcan.ajax无法同步请求(没有找到这个属性),只能异步,造成循环多次提交时由于延迟或网络堵塞等原因无法同步响应,导致提交顺序混乱, ...

  10. [leetcode-515-Find Largest Value in Each Tree Row]

    You need to find the largest value in each row of a binary tree. Example: Input:    1   / \  3 2 / \ ...