FortiGate多个堆溢出漏洞分析

渗透技巧 9个月前 admin
455 0 0

更多安全资讯和分析文章请关注启明星辰ADLab微信公众号及官方网站(adlab.venustech.com.cn)











1
概 述

2022年12月,Fortinet官方发布了一个FortiGate sslvpnd中的基于堆溢出的远程代码执行漏洞(CVE-2022-42475),CVSS评分高达9.8。今年3月和6月又分别发布了影响FortiOS和FortiProxy管理界面的缓冲区下溢漏洞(CVE-2023-25610),以及FortiOS sslvpnd中的另一个堆溢出漏洞(CVE-2023-27997)。Fortinet虽然及时发布了更新,修补了漏洞,但仍有数十万设备容易受到该类漏洞影响。由于该类漏洞都是对输入长度处理不当导致堆的缓冲区溢出,利用方式也极其相似,本文将重点对今年发布的两个漏洞进行分析。


2
漏洞原理分析
2.1 CVE-2023-25610

CVE-2023-25610是web管理页面的漏洞,根据官方通报该漏洞影响FortiOS 7.2.0-7.2.3版本,本文使用7.2.2进行分析。

使用gdbserver远程挂载httpsd进程,运行poc验证代码,程序崩溃,根据程序中部分字符猜测应该是内存分配的时候发生错误。

FortiGate多个堆溢出漏洞分析

通过栈回溯,找到出错的位置在init文件中的0x0000000000c57ba9处,这里调用了apr_palloc函数。

FortiGate多个堆溢出漏洞分析

在调用apr_palloc函数之前下断点,看到了传入的Content-Length值,继续运行程序发生崩溃。

FortiGate多个堆溢出漏洞分析

出错的位置在call apr_palloc,原因是分配空间太大,造成程序崩溃,反编译对代码逻辑进行分析。

FortiGate多个堆溢出漏洞分析

函数中v5保存Content-Length的值,apr_palloc分配大小为v5+1的内存以供使用。在后面的循环中,每次拷贝0x2000大小的数据块到分配的缓冲区。在判断边界的过程中使用了一个int类型的变量v3,大小为32字节,每次循环对其进行累加。进行边界判断的原始变量v5为int64类型,大小为64字节。当足够多的数据进行累加过后,v3会变成负数,在调用memcpy的时候,dst目的地址从a2+v3变成a2+(-v3),导致堆下溢。要利用该漏洞,必须要使传入的数据超过0x7FFFFFFF,由于数据量过大,利用难度较高。

除此之外,该漏洞在6.0.x版本的固件中有不同的表现形式。

FortiGate多个堆溢出漏洞分析

代码获取Content-Length的值保存到变量v11,v11为64位。在分配v11+1大小内存的时候,进行了一次强制类型转换,int64类型的值转换成了int类型,变成32位。举例说明,当传入0x1 0000 1000,经过强制转换会变成0x1001。后面在边界判断的时候,又使用了64位的原始值进行判断,造成明显的堆上溢。

2.2 CVE-2023-27997

该漏洞位于允许用户对VPN进行身份验证的web页面上。攻击者通过GET或者POST向/remote/hostcheck_validate发送一个名为enc的http参数,可进行远程命令执行。

这里的enc参数是一个包含种子(4字节)、大小(2 字节)和数据的结构,其中大小size和数据均进行加密,该字段在新版本中是没有使用的。

FortiGate多个堆溢出漏洞分析
SEED种子存储为 8 个十六进制字符,用于计算 XOR 密钥流的第一个状态,也是我们可以控制的数据。
FortiGate多个堆溢出漏洞分析

salt是服务器创建的随机值,可以通过向/remote/info发出 GET 请求来检索该值。密钥流的计算方式如下(图片来源于网络):将计算得到md5值再次进行md5运算得到下一个md5值。

FortiGate多个堆溢出漏洞分析
通过对enc关键字检索,检索到关键字符串”nvalid enc data length:” 应该是对enc长度进行处理的代码。通过交叉引用,定位到漏洞相关的代码。该段代码逻辑如下:
FortiGate多个堆溢出漏洞分析
计算S0=MD5(client_salt∣seed∣“GCC is the GNU Compiler Collection.”),获取enc十六进制参数长度,分配in_len/2 +1的空间。
FortiGate多个堆溢出漏洞分析
将十六进制的enc加密数据解码,存储到分配的空间alloc_spcae中。
FortiGate多个堆溢出漏洞分析
S0[0:2]和de_data[4:6]对应的两个字节进行异或,得到给出的长度given_len,判断给定的长度given_len必须小于in_len-5。
FortiGate多个堆溢出漏洞分析
S0后面的14个值与加密数据进行异或得到解密后数据,然后再次计算下一个秘钥与密文异或,解密数据不能大于given_len,解密完成在末尾置0。
根据上面的代码很容易就能看出漏洞出现的原因,在进行长度检查的时候,判定given_len必须小于in_len-5,也就是given的大小可以控制在in_len-5之下。在分配缓冲区的时候大小为in_len/2+1,后面与md5秘钥流进行解密,使用given_len来进行边界检查,即我们可以控制given_len溢出的长度不超过解密后数据的2倍。
越界写入数据:

由于该漏洞只能控制部分数据,那么如何顺序写入特定数据呢?根据动态调试,发现每次发送相同大小的数据,会重复分配在相同的地址,那么我们就可以反复触发该漏洞。我们知道数据解密是通过MD5秘钥流和堆空间的数据异或来进行,最后在末尾置0。而异或有一个特性,和相同的数据异或两次,不改变原始数据的内容,怎么利用这种特性呢?举个例子:假如我们要在偏移为1000的位置写入连续的数据。过程如下:

第一次传入size为999的enc数据,与密钥流异或后将1000偏移处的数据置为0;

第二次传入size为1000的enc数据,偏移为1000的数据0会和MD5中的某个字节进行异或,得到的结果也就是md5处的值。即通过爆破种子能够控制md5秘钥流中的这个字节的数据就能够成功写入。

循环该过程,因为前面写入的数据经过偶数次异或操作不会改变,那么就能在缓冲区写入连续的数据。下面是爆破种子的脚本。

#encoding:"UTF-8"import hashlibimport binasciiimport struct, reimport threading
magic = b"GCC is the GNU Compiler Collection."salt="2a52dee0".encode()given_len =0x1000def md5_loop(seed,loop_len): ks = hashlib.md5(salt + seed + magic).digest() for i in range(0,loop_len): ks = hashlib.md5(ks).digest() ks=binascii.hexlify(ks) return ks
def Blast_Md5(salt, given_len): for i in range(1,0xffffff): seed = 0x10000000 + i seed = format(seed, 'x') str_len=len(seed) if (str_len<8): seed="0"*(8-str_len) +seed seed = seed.encode() loop_len= int((given_len-14)/16+1) md5_result = md5_loop(seed,loop_len) print(md5_result) if(md5_result[14:16]==b'50'): length = struct.pack("<H", given_len) print("length",length) print("success seed:",seed) break
if __name__ == "__main__":    Blast_Md5(salt,given_len)

这是一个控制偏移为1000处数据为0x50的爆破脚本,因为md5运算很快,几秒钟就能得到合适的种子值(SEED),这里得到的值不唯一。

FortiGate多个堆溢出漏洞分析


3
漏洞修复
两个漏洞于最新发布的固件中修复,版本为7.2.5,7.0.12,6.4.13,6.0.17和6.2.15,建议受影响的用户及时更新。


参考链接:


[1]https://wzt.ac.cn/2023/05/29/CVE-2023-25610

[2]https://wzt.ac.cn/2022/12/15/CVE-2022-42475

[3]https://forum.butian.net/index.php/share/2166

[4]https://labs.watchtowr.com/xortigate-or-cve-2023-27997

[5]https://blog.lexfo.fr/xortigate-cve-2023-27997.html

[6]https://wzt.ac.cn/2023/03/02/fortios_padding

[7]https://docs.fortinet.com/document/fortigate-private-cloud/7.2.0/vmware-esxi-administration-guide/615472/configuring-port-1

[8]https://bestwing.me/CVE-2022-42475-FortiGate-SSLVPN-HeapOverflow.html?ref=www.ctfiot.com#






启明星辰积极防御实验室(ADLab)





ADLab成立于1999年,是中国安全行业最早成立的攻防技术研究实验室之一,微软MAPP计划核心成员,“黑雀攻击”概念首推者。截止目前,ADLab已通过CVE累计发布安全漏洞1100余个,通过 CNVD/CNNVD/NVDB累计发布安全漏洞近3000个,持续保持国际网络安全领域一流水准。实验室研究方向涵盖基础安全研究、移动与物联网安全研究、工控安全研究、信创安全研究、云安全研究、无线安全研究、高级威胁研究、攻防体系建设。研究成果应用于产品核心技术研究、国家重点科技项目攻关、专业安全服务等





FortiGate多个堆溢出漏洞分析

原文始发于微信公众号(ADLab):FortiGate多个堆溢出漏洞分析

版权声明:admin 发表于 2023年7月28日 下午5:09。
转载请注明:FortiGate多个堆溢出漏洞分析 | CTF导航

相关文章

暂无评论

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