RCE部分
在渲染进程通过一个JS脚本利用XSL对象解析的UAF漏洞执行远程ShellCode。
漏洞原理
利用程序首先定义一些XML,内部包含多个XSL对象。
随后调用transformToDocument方法导致Convert函数被调用。
Convert函数的调用堆栈如下,txMozillaXSLTProcessor::TransformToDocument经过多层调用执行了Convert函数。
Convert函数取参数时使用了JS::ToString,导致用户自定义的回调函数调用。
用户回调函数中,攻击者调用removeParameter释放了参数本身导致UAF。
漏洞利用
通过XSL对象的UAF漏洞,攻击者构造2个数组对象用于实现任意内存读写。
借助这2个数组对象分别实现任意内存地址读写原语和JS对象地址函数。
接着通过一个函数对象获取JIT代码的地址,通过多次调用该函数使其转变为编译热代码,并通过内存读写原语获取其引用位置。
待执行的ShellCode事先通过一个DataView对象存储,来源为远程的二进制资源 “s97.bin”。
最终通过构造一段ROP代码调用VirtualProtect函数修改ShellCode的内存属性并成功执行,调用的方式是通过修改JIT代码引用指针进行代码劫持。
EOP部分
通过RCE部分的ShellCode二进制代码“s97.bin”进行提权,最终由低权限的渲染进程向中权限的WebGPU进程实施代码劫持,利用的是WebGPU由于某RPC接口函数暴露问题引起的UAF漏洞。
漏洞原理
FireFox的WebGPU对象有父端和子端的角色区分,通常父端进程位于一个专门的WebGPU进程,具有较高的权限。漏洞发生位置是WebGPU对象定义的Shutdown接口函数,该函数用于相关对象的关闭和清理工作,但是由于定义此接口时使用父子端IPDL通信协议,故存在配套的SendShutdown函数和RecvShutdown函数。以下为PWebGPUChild子端对象的SendShutdown函数,该函数发送一个IPDL消息“PWebGPU::Msg_Shutdown”请求父端对象进行关闭操作,此操作通常仅在渲染进程清理时由内部CompositorBridgeChild对象的Destroy函数进行调用。
父端对象WebGPUParent对应的接收处理函数RecvShutdown如下,其内部调用wgpu_server_delete函数直接释放一个WGPUGlobal类型的对象mContext。
漏洞产生的根源在于SendShutdown函数接口的意外暴露导致攻击者可以直接调用该函数释放WGPUGlobal对象,形成UAF漏洞。如下是利用程序创建一个webgpu实例对象后直接调用PWebGPUChild::SendShutdown接口来形成UAF的方式。
漏洞利用
利用该UAF漏洞攻击者通过向WebGPU父端进程发送一些显示数据进行占位,此数据为经过特殊构造的ROP_GADGET片段,同时将最终待执行的payload也一起发送给父端进程。
构造的ROP_GADGET片段如下,主要包含对占位对象内部字段的劫持指针和用于payload调用任务ROP代码。
占位成功后,调用2次SendShaderModuleDestroy函数触发代码劫持,第一次调用利用GetClientSetRequestHeaders函数实现一个任意地址写的功能,用于修改第二次调用时利用_cairo_win32_device_flush函数内部的GdiFlush函数指针。
接着由劫持的GdiFlush函数指针调用ROP代码,该代码主要功能即调用VirtualProtect修改一段ShellCode的内存属性并执行。
该ShellCode的代码主要负责查找位于显示数据区域的payload并调用VirtualProtect修改其内存属性和最终执行,而payload代码则是一段简单的downloader,负责从hxxps://xxx.xxx.xxx.xxx/public_api/get64下载远程msf恶意模块。
原文始发于维先生:Firefox在野0day分析