玩转Fuzz之FFmpeg漏洞挖掘

2018-04-0708:21:53 发表评论

玩转Fuzz之FFmpeg漏洞挖掘

什么是 Fuzz (模糊测试)

一种软件测试技术

自动或半自动的生成随机的测试数据

监视程序异常(crash,oom,timeout等等)

 

传统 Fuzz 的特点

随机构造数据

对于大型、复杂程序需要预先准备大量用例 一些代码分支很难走到

靠运气

 

现代 Fuzz 的特点

在有源代码的前提下给代码插桩

基于代码覆盖率反馈的 Fuzz

把那些能产生新的覆盖路径的用例给保存下来

与各种 Sanitizer 相结合(如ASAN、UBSAN、MSAN、TSAN 等等) 知名的工具有 AFL、LibFuzzer、HongFuzz 等

 

进入正题:FFmpeg 介绍

FFmpeg是一套目前非常流行的的开源计算机程序。

它提供了录制、播放、转换以及流化音视频的完整解决方案。

目前有非常多的视音频软件或是视频网站、手机 APP 都采用了这个库,但

是这个库历史上曝出的漏洞也非常之多。

 

视音频技术主要包含以下几点:

封装技术,视频压缩编码技术以及音频压缩编码技术。如果考虑到网络传输的话,还包括流媒体协议技术。

 

Fuzz 准备

寻找合适的攻击层面

Codec

google 已经 Fuzz 过了,OSS-Fuzz 上也有 FFmpeg 的 project,里面的 fuzz target 就是针对的 codec Muxer and Demuxer Google 也有 Fuzz(通过查看 git log) Protocol Emil Lerner和Pavel Cheremushkin使用 AFL Fuzz,改用 libFuzzer。

 

LibFuzzer

Google 工程师2015年开发,基于 LLVM 的 clang 实现和需要被 Fuzz 的库链接在一起,通过一个特殊的 Fuzz 入口点将Fuzz 输入喂给 library 基于代码覆盖率的反馈来生成新的用例和丢弃无用的用例 In-process Fuzz, 速度最高能达到 AFL 的几十倍。

 

如何 Fuzz 网络协议?

libFuzzer 只能从 buffer 输入 重载所有的 socket 相关的操作 已有的轮子——preeny ( written by Shellphish ) LD_PRELOAD=/path/to/desock.so

 

Preeny中 desock.c实现原理

重载了socket,accept,accept4,bind,listen,connect 等函数。

通过 LD_PRELOAD 环境变量预先加载desock.so文件,覆 盖libc 中的同名函数。

Stdin写入 back socket

遇到 EOF终止

启动两个线程

返回 front socket

Back socket 写入stdout

遇到 EOF 终止

 

定制 preeny

libFuzzer 在fuzz target 启动之初就把所有的数据喂给 stdin, 在 desock.c 里面 socket 函数是启动一个线程,把所有数据从 stdin 写入了 back socket ,等这个线程结束了再往下运行。 针对 ftp 这种需要开启两个 socket 的连接的,原本的 preeny 代码不适用。如果 检测是第二次socket 连接(ftp data port)就往 stdin 里面喂一堆随机数据。

 

Fuzz目标

针对 rtmp 协议进行 Fuzz

编写一个客户端程序,接受从 rtmp 服务器传来的视频流

测试 avformat_open_input() 这个函数

 

收集样本

编写一个 FFmpeg 的程序,从 rtmp 服务器获取视频流,使用 wireshark 抓包 寻找不同的 rtmp 源,调整客户端程序的参数来获取不同的 corpus 样本自己写一个 rtmp 协议的字典。

 

参考资料

CVE: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11665

LibFuzzer: https://llvm.org/docs/LibFuzzer.html

Preeny: https://github.com/zardus/preeny

google OSS-Fuzz: https://github.com/google/oss-fuzz/

CE安全网
CE安全网广告位招租

发表评论

您必须登录才能发表评论!