ESXi SLP漏洞复现

前 言

关于SLP几个漏洞的成因与利用,网上已经有彭博士非常精彩且详细的分享vSphere攻防技法分享,这里不会做过多的赘述,写这篇文章的意义是想记录一下针对特定低版本ESXi场景下32位SLP的利用心路。网上的一些公开利用,在低版本情况下皆无法成功。


安全研究人员在对某个目标进行研究时,经常会遇到一个场景,研究人员在一个正在开发的功能中发现漏洞,但因此功能未完善,无法进一步利用的遗憾。


笔者遇到的正是类似于此类场景,不过不是正在开发的功能场景,而是一个漏洞的触发路径上存在另一个漏洞,两个漏洞的相互影响下,导致利用无法完成的悲伤。


SLP历史漏洞

以下是SLP的历年漏洞:

CVE编号 漏洞类型

CVE-2019-5544

堆溢出

CVE-2020-3992

UAF

CVE-2021-21974

堆溢出

CVE-2022-31699

堆溢出


CVE-2021-21974漏洞利用

笔者最初选择的是CVE-2021-21974。


该漏洞存在于SLP的“目录代理通告”,目录代理 (DA) 是可选的 SLP 代理,用于存储和维护服务代理 (SA) 发送的服务广告的缓存。


ESXi SLP漏洞复现

SLPParseSrvUrl函数中,会解析“目录代理通告”中的URL字段,如下面代码所示。


ESXi SLP漏洞复现


问题出现slider2 = strstr(slider1, "://")

01

漏洞分析


要分析这个问题,先从wireshark的抓包看起,下图是发生“目录代理通告”时捕获的数据包。


ESXi SLP漏洞复现


重点关Scope List Length段,该字段的大小被定义为uint16,且紧跟在URL字段后面。


带着这些知识,来分析slider2 = strstr(slider1, "://")问题所在。


slider2 = strstr(slider1, "://")本意是解析URL字段,获://面的内容。


URL的正常构造示例:service:daytime://www.mtjones.com


此时假设一个情况,如果发包时URL字段不带有://,且Scope List Length字段的值小于0x100。slider2 = strstr(slider1, "://")遍历完URL后遇到Scope List Length的x00,将x00视为URL字段的终止符,strstr函数结束,未找到目标字符串,返回空。


如果Scope List Length字段的值大于0x100,strstr函数就会搜寻到Scope List Length字段甚至Scope List字段,在箭头所指的地方产生越界写。


ESXi SLP漏洞复现

02

悲剧的诞生


在走完有漏洞SLPParseSrvUrl函数后,紧跟着的是下面代码所示SLPNetResolveHostToAddr该函数大意是将”www.test.com“之类的转为IP,这个Host从上述URL段中获取。


ESXi SLP漏洞复现


正常URL如下:


ESXi SLP漏洞复现


很不幸,此时触发漏洞需要的URL不是正常的构造,要想触发漏洞且进行正常利用,需要满足以下几个条件:

1. Scope List Length需要大于等于0x100;

2. Scope List"://"现的位置不能过于后面,不然会导致越界写入过多的内存,破坏下一个堆的结构。


ESXi SLP漏洞复现


这就构成了一个悖论,要想利用,Scope List Length必须>=0x100,要想>=0x100,”://”后的数据要足够长,数据足够长又导致无法通过SLPNetResolveHostToAddr,导致程序执行流转入下面所示的LABEL_3中进行SLPBufferFree还有一种可能是申请一个足够长的域名,携带在”://”后进行解析,但是在实战中,有泄露信息的风险,这里不予考虑)。


ESXi SLP漏洞复现


接着又在下面进行了一SLPBufferFree构成了无法避免的,完美的Double Free。


ESXi SLP漏洞复现


在稍微高一点的版本中进行了内部修复,在进行第一次 SLPBufferFree 后对指针进行了置零操作。


CVE-2019-5544漏洞利用

这次笔者换个漏洞,开始第二次利用尝试,这次选择CVE-2019-5544。

01

漏洞分析


Service Registration报文

该报文旨在注册相应的服务。

ESXi SLP漏洞复现


Service Request报文

该报文旨在定位服务并查询他们的信息。

ESXi SLP漏洞复现


正常交互逻辑是,先向SLP发送Service Registration报文,在SLP中注册某类服务。后续如果有用户想要查询该服务信息,就向SLP发送Service Request报文进行查询。而漏洞就诞生在向SLP进行查询时候的处理。


SLP会重新定义返回的信息包大小,该大小由你发送Service Request报文的langtaglen字段决定。


ESXi SLP漏洞复现


接着根据Service Request报文中请求的服务在SLPDataBase中查找,看该服务是否已经被注册,如果被注册就取出、读取服务信息到返回包中。


但很不幸,读取服务信息这一操作的读取大小,是由注册时服务的urllen决定的,其没有校验服务的urllen大小与返回包大小之间的差异。


ESXi SLP漏洞复现
02

漏洞利用


此部分很大程度上参考彭博士的利用手法,但不完全相同。


思路:

1. 泄露libc

2. 布局出任意写

3. 通过任意写覆写free_hook


清理内存碎片:

发送大量SLP的Service Request报文清理碎片。


泄露libc:

和彭博士的手法一样,要注意的是,在布局SLP SendBuffer和RecvBuffer的同时,也要一并布局SLPSocket结构体,在目标堆被放入LargeBin时立马修改对应SLPSocket的状态,将其转变为STREAM_WRITE_FIRST,读回glibc地址。


ESXi SLP漏洞复现


ESXi SLP漏洞复现


在泄露libc时,涉及到修改SLPSocket,这是一个需要关注的点,修改操作破坏了SLPSocket链表的完整性,导致链表被断链,一些Socket连接无法被搜寻到,且无法产生新的Socket连接。


所以在任意写操作进行前,需要修复SLPSocket链表,使其恢复正常。


以下是SLPSocket链表结构、插入、使用代码:


ESXi SLP漏洞复现


SLPSocket链表插入是头插法,使用时从头部开始获取。


假设一共有30个SLPSocket连接,第十五号SLPSocket连接被修改,产生了断链,1号-14号连接就无法被搜寻到。很不幸的是,SLP连接的监听描述符是8,一旦断链,就无法再被寻找到,新连接也就无法接入。需要人为进行伪造,恢复功能,在设计利用时需要特别注意这一点。


布局任意写:

CVE-2019-5544的任意写手法与彭博士介绍的手法稍有不同,该CVE的触发路径上有大量堆块的申请操作,其中包含一些大堆块的申请,要想再次保证目标堆块在unsorted bin中,需新创建大量连接进行布局。


ESXi SLP漏洞复现


彭博士的手法更倾向实战,构造一个永久性的任意写,能多次使用。但理论上不考虑其他因素的话,只复现,拿shell,进行一次任意写即可完成。故笔者转变思路,使用堆溢出修改RecvBuf的start、curpos、end指向目标内存。


ESXi SLP漏洞复现


然后通过堆溢出修改该RecvBuf的SLPSocket,使其转为”STREAM_READ”状态,也就是等待用户的数据输入。此时用户往连接中发送payload即可在目标内存里修改。


最后通过SLP连接,构造一个带有shellcode的堆,将其释放即可完成利用。


总 结

本文解析了CVE-2021-21974和CVE-2019-5544,并尝试在低版本ESXi上进行漏洞利用,利用本身并不复杂。在之后的版本中,VMware将ESXi中的SLP设置为默认关闭,使得SLP不再是一个研究优先度高的攻击面。







【版权说明】

本作品著作权归S1duku所有

未经作者同意,不得转载


ESXi SLP漏洞复现
S1duku

天工实验室安全研究员

GeekCon2023 参赛选手;专注于代码审计、虚拟化安全


ESXi SLP漏洞复现
每周三更新一篇技术文章  点击关注我们吧!


原文始发于微信公众号(破壳平台):ESXi SLP漏洞复现

版权声明:admin 发表于 2024年1月3日 上午11:31。
转载请注明:ESXi SLP漏洞复现 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...