欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

FFmpeg破绽漏洞bug研究及运用,漏洞编号:CVE-2016-10191

来源:本站整理 作者:佚名 时间:2017-09-21 TAG: 我要投稿

一、媒介
FFmpeg是一个闻名的处置音视频的开源名目,应用者浩繁。2016年末paulcher发明FFmpeg三个堆溢出漏洞破绽bug分别为CVE-2016-10190、CVE-2016-10191和CVE-2016-10192。网上对CVE-2016-10190曾经有了许多阐发文章,然则CVE-2016-10191尚未有其他人阐发过。本文具体阐发了CVE-2016-10191,是进修漏洞破绽bug发掘和应用的一个异常不错的案例。
二、漏洞破绽bug成因阐发
在 RTMP协定中,最小的发送数据包的单元是一个 chunk。客户端和办事器会相互协商好发送给对方的 chunk 的最大巨细,初始为 0×80 个字节。一个 RTMP Message 假如超出了Max chunk size, 就必要被拆分红多个 chunk 来发送。在 chunk 的 header 中会带有 Chunk Stream ID 字段(前面简称 CSID),用于平等端在收到 chunk 的时刻从新组装成一个 Message,雷同的CSID 的 chunk 是属于同一个 Message 的。
在每个 Chunk 的 Message Header 部门都邑有一个 Size 字段存储该 chunk 所属的 Message 的巨细,按事理假如是同一个 Message 的 chunk 的话,那末 size 字段都应该是雷同的。此次漏洞破绽bug的原由是对付属于同一个 Message 的 Chunk的 size 字段没有校验先后能否同等,招致写入堆的时刻缓冲区溢出。
漏洞破绽bug发生在rtmppkt.c文件中的rtmp_packet_read_one_chunk函数中,漏洞破绽bug相干部门的源代码以下
size = size – p->offset; //size 为 chunk 中提取的 size 字段
//没有反省先后 size 能否同等
toread = FFMIN(size, chunk_size);//节制toread的值
if (ffurl_read_complete(h, p->data + p->offset, toread) != toread) {
ff_rtmp_packet_destroy(p);
return AVERROR(EIO);
    }
在 max chunk size 为0×80的前提下,假如前一个 chunk 的 size 为一个比拟下的数值,如0xa0,尔后一个 chunk 的 size 为一个异常大的数值,如0×2000, 那末程式会分派一个0xa0巨细的缓冲区用来存储全部 Message,第一次挪用ffurlreadcomplete函数会读取0×80个字节,放到缓冲区中,而第二次挪用的时刻也是读取0×80个字节,这就造成了缓冲区的溢出。
民间修补计划
异常简略,只需参加对先后两个 chunk 的 size 巨细能否同等的断定就行了,假如不同等的话就报错,并且间接把前一个 chunk 给销毁掉。
+    if (prev_pkt[channel_id].read && size != prev_pkt[channel_id].size) {
 +        av_log(NULL, AV_LOG_ERROR, "RTMP packet size mismatch %d != %d\n",
 +                size,
 +                prev_pkt[channel_id].size);
 +        ff_rtmp_packet_destroy(&prev_pkt[channel_id]);
 +        prev_pkt[channel_id].read = 0;
+    }
 +
三、漏洞破绽bug应用情况的搭建
漏洞破绽bug应用的靶机情况
操作系统:Ubuntu 16.04 x64
FFmpeg版本:3.2.1 (参照https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu编译,必要把民间教程中说起的一切 encoder编译出来。)
民间的编译进程由于许多都是动态编译,在一定程度上降低了应用难度。
四、漏洞破绽bug应用剧本的编写
首先要肯定大抵的应用思绪,由因而堆溢出,并且是随便率性多个字节的,以是第一步是察看一下堆上有甚么比拟风趣的数据结构能够笼罩。堆上重要有一个RTMPPacket结构体的数组,每个RTMPPakcet就对应一个 RTMP Message,RTMPPacket的结构体界说是如许的:
/**
 * structure for holding RTMP packets
 */
typedefstructRTMPPacket {
intchannel_id; ///do with audio/video channels though)
RTMPPacketType type;       ///
uint32_t       timestamp;  ///
uint32_t       ts_field;   ///
    uint32_t       extra;      ////这个是 Message Stream ID?
uint8_t        *data;      ///
int            size;       ///
int            offset;     ///
int            read;       ///
} RTMPPacket;
此中有一个很重要的 data 字段就指向这个 Message 的 data buffer,也是分派在堆上。客户端在收到办事器发来的 RTMP 包的时刻会把包的内容存储在 data buffer 上,以是假如咱们节制了RTMPPacket中的 data 指针,就可以够做到随便率性地点写了。
咱们的最终目的是要履行一段shellcode,反弹一个 shell 到咱们的恶意病毒木马办事器上。而要履行shellcode,能够经由进程mprotect函数将一段内存地区的权限改动为rwx,尔后将shellcode安排到这段内存地区内,尔后跳转曩昔履行。那末怎样才能去履行mprotect呢,固然是经由进程 ROP 了。ROP 能够安排在堆上,尔后在程式中探求适合的 gadget 把栈指针迁徙到堆上就行了。
那末第一步便是若何节制RTMPPacket中的 data 指针了,咱们先发一个 chunk 给客户端,CSID为0×4,程式为挪用上面这个函数在堆上分派一个RTMPPacket[20] 的数组,尔后在数组上面开拓一段buffer存储Message的 data。

[1] [2] [3]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载