FortiGate SSLVPN CVE-2024-21762漏洞利用分析
一、漏洞简介 FortiGate二月份发布版本更新,修复多个中高危漏洞,其中一个严重级别漏洞是SSL VPN的未授权越界写漏洞,漏洞预警称该漏洞可能被在野利用。本文将介绍笔者分析利用该漏洞,实现远程代码执行的过程。 二、漏洞分析 本文漏洞分析使用的环境是FGT_VM64-v7.4.2.F-build2571。 2.1 diff patch 对修复版本的二进制进行对比(7.4.2和7.4.3),分析发现修复代码位于函数sub_18F4980(7.4.2)。 分析该函数不难发现,该函数逻辑是读取HTTP POST请求的body数据。同时根据Transfer-Encoding请求头判断是按照chunk格式读取,还是根据Content-Length读取。根据控制流图对比结果,存在两处代码修改: 解析chunk格式时,调用ap_getline读取分块长度,检查ap_getline的返回值是否大于16,大于16认为是非法的chunk length。 读取chunk trailer时,写入\r\n的偏移line_off的赋值来源,修复前line_off的值来源于*(_QWORD *)(a1 + 744),修复后line_off为ap_getline的返回值。 继续向前回溯,可以找到*(_QWORD *)(a1 + 744)的值正是第一处校验的chunk length字段的长度 同时阅读代码可以得知,当chunk length字段经过hex解码后值为0时,就会进入到chunk trailer读取的逻辑。 2.2 触发越界写 经过对patch的分析,我们可以得到以下结论: 1、解析chunk时,如果chunk length字段hex解码后值为0,则开始chunk trailer的读取。 2、调用ap_getline读取chunk trailer后,会根据chunk length字段的长度向缓冲区中写入\r\n。 因此,如果chunk length字段传入很多个0,0的长度大于剩余缓冲区长度的1/2时,就会触发越界写入\r\n。通过调试可知目标缓冲区位于栈上(函数sub_1A111E0),偏移0x2028的位置保存了返回地址。如果在偏移0x202e的位置写入\r\n,当函数返回执行ret指令恢复rip时就会因地址非法产生崩溃。 Crash PoC: pkt = b"""\ GET / HTTP/1.1 Host: %s Transfer-Encoding: chunked %s\r\n%s\r\n\r\n""" % (hostname.encode(), b"0"*((0x202e//2)-2), b"a") ssock = create_ssock(hostname, port) ssock.send(pkt) ssock.recv(4096) 崩溃现场: 三、漏洞利用 通过分析漏洞成因可知,利用该漏洞可以实现栈上越界写\r\n两个字节,越界范围接近0x2000。由于写入的内容非常有限,无法通过直接劫持rip实现RCE。因此需要把目光放在栈上保存的内存指针上。 3.1 失败的尝试 比较容易想到的是劫持rbp,通过覆盖rbp的低字节,使rbp刚好指向可控的内存区域。当上一级函数返回执行leave ret指令时,就可以完全劫持rip。然而验证时发现即使覆盖了栈上的rbp,也无法劫持rsp和rip,甚至程序不会产生崩溃。继续向上回溯,找到sub_1A111E0的父函数sub_1A26040,该函数在返回时并没有调用leave ret来恢复rsp,而是直接add rsp, 0x18,因此无法达到预期的效果。...