翻译:胖胖秦
预估稿费:130RMB
投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿
在12月,我们终于得到了Linux代理的工作原型。它已经制作了相当一段时间,现在,它处于alpha阶段,我们终于可以开始0patching Linux的用户空间代码。Linux代理仍然缺乏Windows代理支持的一些功能,但它已经准备好了。
超过65%的Web服务器运行着不同风格的Unix ,修补高可用性的Linux环境安全漏洞应该一直都不是问题。如果我们以Heartbleed漏洞为例,部署官方补丁所需的时间不仅包括供应商发布补丁所需的时间,还包括DevOps测试和部署它所需的时间。我们的目标是使补丁尽可能小,易于查看,甚至更容易部署,从而避免重新启动服务器的需要,从而大大缩短这一时间。
当在Ubuntu上开发和测试Linux代理时,我们已经为Heartbleed创建了一个补丁,虽然还有很多易受攻击的服务器,但是它们能马上能得修复。
这个漏洞在去年十一月发表了Chris的博客中。漏洞位于gstreamer的VMnc解码器,它处理VMware屏幕捕获格式。这是一个非常简单的整数溢出并且Chris提供了PoC。
我创建一个Fedora 25虚拟机,然后尝试使用totem,totem是一个原生于Gnome的视频播放器,它在未修补的Fedora 25上使用gstreamer编程框架。使用totem来播放PoC会导致崩溃。Chris对这个bug进行详细分析。他指出在vmncdec.c文件中的vmnc_handle_wmvi_rectangle方法发生了整数溢出,它是gstreamer-plugins-bad包的一部分。你可以在Gihub上查看其源码gstreamers github。Chris 解释发生溢出的原因是,因为用户提供的rect->width和rect->height会与bytes_per_pixel相乘,最终的结果会作为分配图像数据缓冲区的大小。这两个变量都是带符号的32位整数。如果提供足够高的值,则就会发生整数溢出。随后的内存分配(在下面的图像中标记为红色)会产生比图像数据小的缓冲区,这将导致缓冲区溢出。
我反汇编了libgstvmnc.so ,并定位vmnc_handle_wmvi_rectangle函数,在这个函数里高度和宽度相乘,缓冲器被分配(在下面的图像中标记为红色)。
当有效比特超过了结果的一半时,IMUL指令会设置进位和溢出标志,所以我的第一个想法是,如果这些标志设置,我们可以返回一个错误指令。补丁位置在上图中以绿色标记。这是我补丁的第一个版本,它应用于IMul的原位置上(绿色标记的上述图像上):
imul 0x30c(%rbx),%edi //Multiply width and height
jc _bad //If CF is set jump to return error
imul 0x314(%rbx),%edi //Multiply with bytes_per_pixel
jc _bad //If CF is set jump to return error
jmp _good //If no CF is set continue execution
_bad:
pop %rdi //Return error code:
add $0x28,%rsp
mov $0xffffffff,%eax //Set %eax to -1
pop %rbx
pop %rbp
pop %r12
pop %r13
pop %r14
pop %r15
retq //and return
_good:
正如你所看到的,我们在每一个imul指令后都进行检查,如果进位标志被设置,则返回一个错误。 然而,应用补丁后,totem仍然崩溃。在经过一些调试后,我发现,仅仅在vmnc_handle_wmvi_rectangle函数里返回错误是不够的。因此我看了下方的官方补丁 。
在vmnc_handle_packet函数中可以找到官方补丁 。你可以看到,如果width大于16386或者height大于0x4000,就会返回一个错误。我们的补丁应该和它一样。我反汇编了未修补和已修补的两个版本的 vmnc_handle_packet 函数, 并用Bindiff寻找一个合适的补丁位置。下面的图像代表两个代码的组合视图。绿色代码是由官方补丁添加的。
只有当数据包类型等于TYPE_WMVi 或0x574D5669时, 官方补丁代码才会被执行。在我选择的修补程序位置(红色标记-点击上面的图片可查看大图)的%EDI 寄存器保存数据包类型值,而 %r8w 和%CX 保存着宽度和高度。这是最终生成的补丁:
cmp $0x574d5669,%edi //If the packet type doesn't equal TYPE_WMVi,
jnz _end //continue execution
cmp $0x4000,%r8w //If width is greater than 0x4000,
ja _bad //jump to return error
cmp $0x4000,%cx //If height is smaller than 0x4000,
jbe _end //continue execution, else return error
_bad:
mov $0xffffffff,%eax //Set %eax to -1
add $0x48,%rsp
pop %rbx
pop %rbp
pop %r12
pop %r13
pop %r14
pop %r15
retq //and return
_end:
补丁可以成功地阻止整数溢出和后续的内存分配,使文件可以正常播放,正如官方补丁一样。这里是我们Linux 0patch代理和我们刚刚开发的补丁的短视频。
如你所见,totem在尝试打开PoC时崩溃 。将补丁文件复制到补丁文件夹内并启用补丁后,totem不再崩溃,视频可以正常播放。
开发这个补丁花了大约8小时。这包括反汇编libgstvmnc.so ,尝试了开发了一个错误的补丁,分析了官方补丁并打上正确的补丁。这是一个相对简单的补丁,但我的目的是想展示我们的Linux代理及其功能,这几乎与我们在Windows上正在做的一样。
我们正在不断努力扩展支持的操作系统平台,所以我们有一天可以为需要它的每个人带来0patch
发表评论
您还未登录,请先登录。
登录