- 福建榕基软件股份有限公司
- 电话:0591-87860988
- 传真:0591-87869595
- 地址:福建省福州市鼓楼区
- 软件大道89号
- A区15座
- 邮编:350003
CVE-2018-8476: Windows服务器部署服务漏洞
简介
许多企业都使用Windows Deployment Services(WDS,Windows部署服务在网络中的新机器上安装定制的操作系统。WDS其实可以由任意通过LAN端口链接的用户访问,并提供相关的软件。
那会不会有攻击者黑掉服务器,修改相关内容来控制每个新计算机的内容,并安装恶意软件呢?本文就对WDS基础设施以及相关的漏洞利用进行分析。
Windows Deployment Services
WDS是微软提供的基于网络的Windows操作系统安装解决方案。WDS使用的是磁盘镜像,主要是Windows Imaging Format (WIM)格式。Windows Server从2008年开始就将该服务包含在32位和64位版本中。WDS是个很复杂的系统,本文介绍WDS新安装的预认证协调过程及潜在攻击方式。
在分发完整的Windows镜像前,WDS必须提供完整的网络启动策略,因此使用了PXE (Preboot eXecution Environment,预启动执行环境)服务器。PXE是Intel创建的一个标准,工作于Client/Server的网络模式,支持工作站通过网络从远端服务器下载映像,并由此支持通过网络启动操作系统,在启动过程中,终端要求服务器分配IP地址,再用TFTP(trivial file transfer protocol)或MTFTP(multicast trivial file transfer protocol)协议下载一个启动软件包到本机内存中执行,由这个启动软件包完成终端(客户端)基本软件设置,从而引导预先安装在服务器中的终端操作系统。
模糊测试
研究人员首先用Boofuzz创建了一个TFTP dumb fuzzer。
Tftp.py 定义了要进行模糊测试时的协议语义和域。因为fuzzer是通用的,因此代码可以用来测试所有的TFTP实现和应用。在运行fuzzer时,研究人员手动逆向了wdstftp.dll中应用的服务器。
wdstftp.dll
研究人员逆向该dll时,首先检查了CTftp::ParseRequest应用的文件读取机制。CTftpPacket::ParseRequest中会处理TFTP Read Requests (RRQ)。在验证了PXE base目录中是否存在请求的文件后,就会被读入CTptReadFile::CacheBlock结构。
图1: CacheBlock Struct
这些CacheBlocks是在一个链接的列表中操作和管理的。
服务器会用分配做回调函数的CTptReadFile::_IOCompletionCallback异步执行ReadFiles 。
图2: ReadFile回调
然后研究人员发现一个非常奇怪的行为,就是CacheBlocks链接的列表的大小也是有限制的,最大是2。
图3: maxCacheBlocks = 2
如下图所示,当cache block的数量大于2时,位于尾部的就会被删除。
图4: free tail
根据对TFTP协议的了解以及blksize 和windowsize选项的使用,研究人员可以伪造一个请求来在接收ack包之前增加超过2个cache block。如果一切顺利,且计数正确,会有一个cache block在回调函数CTptReadFile::_IOCompletionCallback使用前被释放。
然后设置(page heap on)。
图5: windbg奔溃
可以看出RAX现在指向了释放的内存,这也说明Windows Deployment Services中存在UAF(Use-After-Free)漏洞。
这个bug看似很简单,为什么fuzzer没有发现呢?原因很简单,就是Sulley框架一次只测试一个域,研究人员测试中的请求读操作无法持续那么久。因此,未来在进行模糊时既要考虑包的有效性,也不能太有效。
利用方法
因为这是一个远程触发的、非认证的、高权限的Windows服务器漏洞,研究人员将其标记为高危(critical)漏洞。
在利用UAF漏洞时,研究人员一般会分配不同的对象或分配不同状态的相似对象,这会导致他们之间产生有些混淆。
在寻找允许研究人员分配与释放的区域匹配的对象的分配原语(allocation primitives)时,研究人员检查了进程heap。
事实证明,WDS其实使用了多个heap,研究人员发现的这个heap是wdstftp.dll, wdssrv.dll 和wdsmc.dll共享的。
虽然wdstftp.dll考虑了一些比较灵活的分配方式,比如TFTP错误包中就是被转换为Unicode编码的ASCII码。
图6: Unicode POC
对PoC来说这是一个很好的原语(primitiv),但是构造一个功能payload有点复杂。
下一个分配原语机制是wdssrv.dll。它暴露了一个WDS服务器提供的远程调用服务的RPC接口。
在寻找攻击者可以控制的分配时,研究人员发现了CRpcHandler::OnRecvRequest。该RPC handler在将自己插入到要处理的队列之前负责做一些RPC请求的初步语义分析。为了使用那些释放的内存,研究人员需要使用相同的Heap bucket (size 0x5c-0x78)。在handler中唯一可以控制大小的分配就是CMemoryBuffer::Initialize。
图7: RPC分配原语
下面的脚本可以执行与模板bucket匹配的分配。
图8: RPC POC
但是大多数的结构和CacheBlocks callbackCtx指针都没有接触到。
图9: 使用RPC POC的内存布局
如果修改RPC payload,因为CMemoryBuffer::Initialize执行的大小计算,就会被分配一个错误的bucket。
下一个想法是是否可以修改CacheBlocks域来进行权限提升。
研究人员逆向发现CTftpReader并不能使用它们。因此研究人员使用一种不同的方式来利用该漏洞,即尝试利用来bug来获取服务器的关键信息泄露。在标准场景下,IOCompletionCallback会在与文件内容匹配的CacheBlock上调用,然后发送内容给研究人员。
通过混淆服务器并植入新的没有文件内容的CacheBlock,研究人员希望该服务器可以发送新CacheBlock的未初始化的内存,造成关键信息泄露。在进行多次尝试后,研究人员接收到的不是未初始化的内存而是部分文件内容。研究人员怀疑要处理大量文件读写请求的繁忙的服务器在读取TFTP图片时会更慢,这也就增加了赢取竞争条件的可能性。
结论
WDS是一个用于镜像安装的被广泛使用的Windows服务器服务。其底层的PXE服务器有一个高危的远程释放UAF bug,可能会被未认证的攻击者所利用引发远程代码执行。研究人员将该漏洞报告给了微软,被分配的CVE编号为CVE-2018-8476,影响Windows server 2008 SP2之后版本。
由于时间关系,研究人员没有进一步寻找关于该漏洞的利用方法,但Check Point和微软研究人员都确认该漏洞是可以被利用的。