一、前 言
二、消息结构
三、消息发送脚本
四、漏洞分析
五、总 结
Avalanche Web 应用程序无法独立执行任务,但是它可以自由地使用不同的服务来执行任务。信息路由(也称为 InfoRail 服务)位于两者之间,负责在服务之间分发消息。Web创建一条消息并将其发送到 InfoRail 服务,后者将其转发到适当的目标服务。目标服务处理该消息并再次通过 InfoRail 服务将响应返回给 WebWLAvanacheServer是其中的移动设备服务,默认开启在1777端口上。WLAvanacheServer这个组件首次漏洞公开时间是2023年,成为了Avalanche的新攻击面,本文主要对WLAvanacheServer这个组件进行漏洞分析。
这里是在6.4.0这个版本上分析消息结构,整个消息结构由三个主要部分组成:
-
preamble
-
header
-
payload
下面是一个详细的消息内存结构:
preamble
它的长度为16字节,主要由以下部分组成:
-
MsgSize:整个消息的长度
-
HdrSize:消息头的长度
-
PayloadSize:消息的payload长度
-
unk:这里目前不知道是做什么的,应该是某个标志,不影响分析
header
消息头由操作类型、名字和数据组成:
-
type:消息的数据类型操作
-
name_size:消息头的名字长度
-
value_size:消息头的数据长度
-
name:消息头的名字
-
value:消息头的数据
payload
消息的payload也是由操作类型、名字和数据组成:
-
type:消息的数据类型操作
-
name_size:消息头的名字长度
-
value_size:消息头的数据长度
-
name:消息头的名字
-
value:消息头的数据
在消息结尾需要对齐字节,并且有12个字节的补充,完整结构体如下:
下面这个是发送消息的脚本,将用户的数据以字节形式传入WLAvanacheServer去处理:
基本所有的历史漏洞都是缓冲区溢出,并且程序保护基本没开(从6.4.0到最新版本),导致溢出洞的利用非常简单。
6.4.0
WLAvanacheServer会循环处理消息,处理顺序是先处理header再处理payload,处理消息的时候会检查消息格式是否正确:
-
在check_message函数中可以看出header和payload的size都需要>=0
-
允许的数据操作类型不超过0x66
-
NameSize有长度限制
-
ValueSize只需要>=0
这里有个很明显的缺陷,ValueSize并没有去限制最长的长度,导致后续产生了一些相关漏洞:
CVE-2023-32560(堆栈溢出)
在handle_message中,当type类型为3的时候会利用hexstr2bin函数将输入的十六进制字符串转换为二进制数据(type类型为5的时候也是同样的情况)
hexstr2bin函数最后的转换结果会存放到一个固定大小的缓冲区里(&p_Out→Value_ptr)
hexstr2bin函数的具体实现如下,在转换成二进制数据的时候,ValueSize值由用户控制,在check_message的时候没有限制最长长度
对Value_ptr不断赋值之后,形成一个缓冲区溢出漏洞
控制成如下的buf,可以使程序崩溃。对应的利用也非常简单,只需要将shellcode写入buf中,劫持jmp esp即可
这个CVE里还存在另外一个漏洞。
在type类型为9的处理中,程序流会走到sub_429600函数,这个函数是从数据中提取出以分号分隔的子字符串,并返回该子字符串的长度和下一个子字符串的起始位置。
接着会把函数返回的结果放入TokenSize,利用qmemcpy函数将当前子字符串复制到String缓冲区中,并使用atol函数将每个子字符串转换为长整型数。在qmemcpy时,由于TokenSize可控,发生缓冲区溢出漏洞。
6.4.1
6.4.0的fix:
check_message函数这里依旧没有对ValueSize进行修复,在6.4.1中出的漏洞还是与ValueSize相关
数据类型操作3这里添加了对ValueSize的check,限制了长度小于255数据类型操作9这里只对Token_size这里进行了check,长度需要小于127
CVE-2023-41727/CVE-2023-46216/CVE-2023-46217(堆栈溢出)
这三个漏洞发生在处理数据类型100/101/102的时候,和上面的CVE-2023-32560一样把函数返回的结果放入TokenSize,利用qmemcpy函数将当前子字符串复制到String缓冲区中在Token_size这里没有长度限制,发生缓冲区溢出漏洞。
CVE-2024-29204(堆栈溢出)
这个漏洞发生在处理RSP_FILE_UPLOAD消息,用户可以发送多个RSP_FILE_UPLOAD消息首先会将解压缩大小相加起来计算所有文件的块的解压缩大小,如果指定较大的解压缩大小,会导致TotalDecompressedSize发生整型溢出,TotalDecompressedSize的值会变小以TotalDecompressedSize创建堆块,在第23行这里会将完整的解压缩数据copy到创建的堆块中,但是这个堆块的大小是小于完整数据的,发生堆溢出漏洞。
6.4.3
6.4.2的fix:
这个版本添加了长度判断,在handle_message中的越界已经失效
对copy的数据长度进行了判断,每轮copy前判断到这次为止的压缩块大小是否大于总大于,大于则退出
这里没有仔细的去分析其他相关点,可能在新版上有相似的问题
6.4.4
在这篇文章初次写完之后新版本还停留在6.4.4,当时在6.4.4发现了多个0day。在第二次补充的时候突然发现在10.8号更新了6.4.5,而本次更新就修复了其中一个漏洞(撞洞)
CVE-2024-47007(空指针引用DOS)
在处理type类型为101时,将一个名为 Value 的指针指向 a1→Value 数组的起始位置,进入循环后检查Value 指针是否已经指向 a1→Value 数组的结尾。调用sub_429820函数去提取出以分号分隔的子字符串,获取大小后判断是否小于0xFF,如果小于则利用qmemcpy函数进行拷贝,接着继续循环截取下一段
漏洞点发生在sub_429820函数中,如果仅包含空格,第一次调用函数会反回0作为Token_Size,并且a1这里的值会变成NULL指针,下一次循环时Value还是小于&a1→Value[a1→ValueSize],继续进入sub_429820函数中,在*i == ‘ ‘这里发生空指针引用
*i == ‘ ‘的汇编代码如下,eax为NULL
case 102的代码与101基本相似,漏洞原理也是一样的,不详细展开了
本文首先介绍了WLAvanacheServer的消息结构,然后借助消息发送脚本进行调试分析,主要分析漏洞的形成原因。总体来说,这些漏洞比较简单,之前没有被发现的原因是lvanti Avalanche的大部分漏洞挖掘都集中在web端,而忽视了 WLAvanacheServer这一新的攻击面。将注意力转移到 WLAvanacheServer之后,就发现了其中存在大量漏洞。还有一个严重问题是针对 WLAvanacheServer 组件的漏洞修复工作非常不彻底,每个版本的修补都存在不足,导致仍留有可被攻击的漏洞。
【版权说明】
本作品著作权归z1r0所有
未经作者同意,不得转载
天工实验室安全研究员
研究领域:二进制漏洞挖掘
原文始发于微信公众号(奇安信天工实验室):Ivanti Avalanche WLAvanacheServer组件漏洞分析