27 June 2017

FFmpeg是一个广泛使用的多媒体处理框架。这次为它的一个漏洞折腾了半天。

这个漏洞是这两天才广为人知,不过其实它已经存在很久了。网上资料显示, 今年五月初的时候,漏洞的发现者neex就向大公司内部报告了这个漏洞,FFmpeg也已经在一个月前做了修复, 只是没有公开挑明罢了(我猜是为了给公司预留时间防备)。

这个漏洞主要是利用了HLS允许从外部文件读取数据的特性。攻击者可以制作一个AVI格式的容器文件,其中包含GAP2格式的字幕和HLS播放列表, 列表中的外部文件特意写成/etc/passwd等希望读取内容的敏感文件。 ffmpeg转码这样的AVI文件时,就会将其中的GAP2内容与/etc/passwd文件中的内容拼接为最终的字幕文本。这些文本以xbin编码,最终会被ffmpeg转为视频帧。 于是,/etc/passwd中的敏感内容就出现在了攻击者可以观看的视频图像里。

更详细的介绍可以参见漏洞发现者的一个报告。 报告人Emil Lerner和Pavel Cheremushkin的名字也出现在了ffmpeg修复的提交信息里的“Found-by”这一行:

Shengbins-Mac-mini:FFmpeg shengbin$ git show 1998147f2ebcb0eff33438339b2051d159edb688
commit 1998147f2ebcb0eff33438339b2051d159edb688
Author: Michael Niedermayer <michael@niedermayer.cc>
Date:   Tue May 30 21:29:20 2017 +0200

	avformat/avidec: Limit formats in gab2 to srt and ass/ssa

	This prevents part of one exploit leading to an information leak

	Found-by: Emil Lerner and Pavel Cheremushkin
	Reported-by: Thierry Foucu <tfoucu@google.com>

	Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
	(cherry picked from commit a5d849b149ca67ced2d271dc84db0bc95a548abb)
	Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>

diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 4e694fe447..ed043470f0 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -1098,6 +1098,9 @@ static int read_gab2_sub(AVFormatContext *s, AVStream *st, AVPacket *pkt)
		 if (!sub_demuxer)
			 goto error;
 
+        if (strcmp(sub_demuxer->name, "srt") && strcmp(sub_demuxer->name, "ass"))
+            goto error;
+
		 if (!(ast->sub_ctx = avformat_alloc_context()))
			 goto error;

可以看到,所做的修复就是在解析AVI时把GAB2字幕限制为常见的srt和ass格式,对于其它的内容直接报错。

这个修复提交出现在FFmpeg 3.3.1之后,因此3.3.1及之前的版本都存在被攻击的风险。我们可以通过升级到最新的3.3.2来解决这一漏洞。 从3.3.1到3.3.2还包括其它一些同样性质的修复,例如https://git.ffmpeg.org/gitweb/ffmpeg.git/commit/3dd1f38329e7bd7225445c92fc0019adc43899f4, 其中仍然有“Found-by: Emil Lerner and Pavel Cheremushkin”的字样。