标题 | 简介 | 类型 | 公开时间 | ||||||||||
|
|||||||||||||
|
|||||||||||||
详情 | |||||||||||||
[SAFE-ID: JIWO-2025-3499] 作者: ShYLie 发表于: [2025-02-05]
本文共 [3] 位读者顶过
关于PAN-OS DoS(CVE-2024-3393)的研究
[出自:jiwo.org] 前段时间Palo Alto发布了一项漏洞通告[1],看漏洞信息是PAN-OS数据平面处理流量时产生DoS,其实之前PAN-OS也有过这样的DoS漏洞。但令笔者好奇的是,这次居然会影响Prisma Access,这款产品是Palo Alto公司实现零信任的关键组件,遂准备花些时间去做一下相关的复现。 (一)漏洞描述分析 从描述中可以看出这是一个由DNS安全检测产生的漏洞,并且官方明确表示只有开启DNS Security才会产生。但不幸的是,这个功能需要购买相关的DNS Security License才能激活,这个暂且不做讨论,后续会有绕过的办法。而且,还关注到最重要的一点
它需要开启DNS Security Logging,也就是说很大概率是因为某些log记录时出现了fault。 1.首先这是防火墙数据平面处理流量产生的问题,并不涉及之前的Web管理口(CVE-2024-0012,CVE-2024-9474),VPN口(CVE-2024-3400)等其他服务。
2.其次是DNS安全检测产生的,并且有可能时处理DNS Security Log产生的。
根据上面的影响版本,笔者这里选择了PAN-OS 10.2.9-h19和PAN-OS 10.2.9-h18进行diff,可以看到新版本也只修复这一个CVE
1. 防火墙设置首先需要设置DNS Security相关配置,主要在Anti-Spyware Profile中设置,如下图,重点是log serverity,这个就是漏洞描述中log部分。 ![]()
之后把这个用到策略上就可以
上述防火墙配置就完成了,当然还有一些网口配置这些都是最基础的,可以自行配置。 2. shell获取
由于采用虚拟机,所以获取shell还是比较容易的,这里采用patch vm mem的方法。
Find:
这里注意替换字节要一样,否在虚拟机就起不来了。最终效果如下图,之后改了root密码,就可以用远程22端口登录了。 ![]()
(三)diff分析 首先需要找到处理数据平面的进程,从[2][3][4]可以得到PAN_OS各个进程的信息,虽然版本有点老,但一些关键进程还是没有改变的。
从图中可以看出,data plane的主要处理进程就是pan_task。在虚拟机中也可以找到相应的进程。
之后就可以直接进行diff了,这里用bindiff,也可以用Diaphora等diff工具,具体结果如下。
看到有一个log函数改动较大,并且非常符合漏洞的描述,打开IDA,反汇编看一下。
发现对内存操作进行较大改动,如果会产生dos,那么很大概率是计算size的时候出现了问题,但实际上旧版本size反汇编的结果很抽象,经过了一系列运算才得出一个结果,接下来就需要去逆向了。 (四)逆向分析
首先需要触发这个流程。但前文提到DNS security需要license,这里发现这个DNS Security的开关会由pan_task结构体中的一个数据影响。
在pan_task中会通过cfg_data获取相关DNS License。
默认没有license时,图中cloud_dns_license的值为0,当图中cfg_data的cloud_dns_license的值为1时,DNS Security将会开启,当我们发送一个解析恶意地址的DNS数据包就会拦截。 target_dns_server = "8.8.8.8" dns_request = IP(dst=target_dns_server) / UDP(dport=53, sport=RandShort()) / DNS( rd=1, qd=DNSQR(qname="test-grayware.testpanw.com", qtype="A") ) send(dns_request)
最终我们可以在威胁中定位到相关dns包被拦截:
之后在pan_task中打函数断点pan_log_send_threat_log也可以停下来,说明走进了正确流程。
从gdb调试中不难看到,filename或者url其实就是我们解析的域名,并且在后续内存操作中,也是对这两个变量操作的地方进行了patch,那么考虑一下如果域名过长会不会导致crash。
from scapy.all import *
跑完一轮之后发现并没有crash,其实熟悉DNS协议的人可能一眼就看到了其中问题,当DNS域名过长时,实际的DNS数据包发送的数据并不是我们想要的域名。 ![]()
可以看到实际发送的域名并不是我们想要发送的域名。 ![]()
◆域名以标签的形式编码。每个标签的第一个字节是该标签的长度,后跟标签的内容。标签的长度最大为 63 字节,标签和标签之间使用长度字节进行分隔。 ◆域名的结尾使用00来标示,表示这是域名的结束。
◆例如,www.example.com会被表示为:03 77 77 77 07 65 78 61 6D 70 6C 65 03 63 6F 6D 00。
所以按如下构造poc,那么产生的域名应该是足够长的。
from scapy.all import *
) 最终导致了memcpy溢出
1. POC分析那么问题来了,这个size是如何产生的? ![]()
断点打到000055555574F3DB,发现rax=0也就是v39=0,实际上应该是filename_len+1
继续往上看发现v39 = 0xff + 1 = 0x100
但查看汇编时发现了不一样的东西
这里v39 = eax + 1 = 0xff + 1 = 0x100,但在下一个汇编只是移动了al,那么v39 = 0x00 = 0,所以下面的size变成0 - 1 = 0xffffffff也就顺理成章了,至此分析完毕。
2. 漏洞模式
所以这个漏洞本质上是由于整数溢出导致size计算错误而后续溢出。 3. patch分析在新版本中更新了size的大小为uint16
由于这个漏洞不仅会影响防火墙,还会影响Prisma Access,个人认为影响还是比较大的。毕竟Prisma Access是云上服务产品,如果一个公司使用该产品构建整个网络,那么通过这个漏洞就可以让云上产品直接崩溃,导致公司内网瘫痪。 此外我们可以发现以往的漏洞都是出现在管理口和VPN口,或许数据平面也是一个不错的攻击面? |