Author: 宁静之盾
01 漏洞背景
202 年 1 月 13 日,7 月 13 日,安全美国公文公司发布安全公告[1],文中情报黑客中心利用 0day 对美国公文公司美国军工部门进行了安全性的攻击,同日发布了安全公告-美国母公司solarwind 也发布了[ 1] 2],并针对最新大版本发布了[3]。
注意:目前发布的只能针对最新的 15.2.3 大版本,并且可以让用户下载安装,付费用户目前无法从官方获得非官方有效的优惠。
根据团队比较和fuzzer,小盾成功复现了该远程溢出漏洞,并能够在实战环境下成功利用。
截止 9 月 10 日,互联网上未发布任何与该漏洞相关的技术分析发现和 POC,也未发现更多新闻发布。
该漏洞是2003年Serv-U mdtm漏洞修复后出现的第一个RCE。
02 Serv-U软件说明
该软件是全球流行的商业源服务器软件,官方软件10W该全球用户,软件默认支持ftp(21跨端口/FTP端口)考虑ftp(2222端口显示)等,出于安全性使用对象主要端口(该端口在运行时使用非这些算法加密),主要端口在运行窗口中显示新版本为X程序,64个近端口号为X程序,22个端口的默认横幅信息包含详细版本,通过zoomeye搜索到的详细版本为13000全量为6.7W多)。

其中15.2.3大版本有1100台,最新版本152.3.742有900台,影响是Serv-U的版本<15.2.3 HF2(即15.2.3.742)。按照近年过去13000台,安装此漏洞释放台计算,现在全商业网状态至少有 90% 的旧Serv-U-U-Serv-U-Serv-U 有受此漏洞威胁(母公司应该是出于考虑版本未对大规模发布的内容,老版本升级到最新版本需要重新)。


横幅信息
03 漏洞分析与利用说明
综述
该漏洞是一个远程内存部署漏洞(可以稳定控制虚函数版本和指针),针对WINDOWS-U SFTP(22端口Serv)进行攻击,开启漏洞,输入IP和端口密码,只要版本号当日15.2.3.742,攻击成功率接近100%(单次成功率未达100%,但可以立即再次),利用成功获取系统权限SHELL。

3.1 比较
下载最新版本742和上一版本723,更新包文件
15.2.3.723 HF1 2021 年 5 月 14 日
由于 OpenSSL API 使用不正确,Serv-U 崩溃
<Serv-U-InstallDir>\Serv-U.dll
<Serv-U-InstallDir>\RhinoNET.dll
15.2.3.742 HF2 2021 年 7 月 12 日
* SSH协议中未经身份验证的远程代码执行
* <Serv-U-InstallDir>\Serv-U-RES.dll
* <Serv-U-InstallDir>\Serv-U-Tray.exe
* <Serv-U-InstallDir>\Serv-U.dll
* <Serv-U-InstallDir>\Serv-U.exe

可以看到三个主要修改文件,使用因为绑定比较了4个文件对这4个文件进行,最终可以去除Serv-U.exe、Serv-U-Tray.exe和Serv-U-RES.dll,这个文件非常小,普遍存在漏洞。

结合官方的报告,APT攻击中利用该漏洞可能会报错:
例外:C0000005;
CSUSSHSocket::ProcessReceive();
类型:30;
puchPayLoad = 0x041ec066;
nPacketLength = 76;
nBytesReceived = 80;
nBytesUncompressed = 156;
uchPaddingLength = 5
基本可以判断漏洞是一个SSH相关的内存类型漏洞。
使用 BINDIFF 和 IDA 对主 DLL 的分发情况比较如下:

出发为未完成变化的函数地址,正确为后来的函数地址

Serv-U.dll 中的发生对十个分析个有的函数,找出一个比较有 9 个函数的函数,发现为局部硬件编码的函数和函数增加了 4 个变化,或者判断值198h是否为、1、23、4或5等98h、或者判断为0、1、2、3、55等。

此时,需要利用 ID 试探了解这些值的价值位置,首先定位到该存储的位置,才能看到该存储的a1[0x198]。

然后,该搜索的所有值0x198找到位置。

就是,即使函数补补的位置与揣测发现的最终子,记录下来了。于是留下了另一种路径,很难从打出追踪的一直打下去的路,引用分析,会发现所有的函数向上0145070函数。
其他几个变化的函数主要是该函数的switch case分支里调用该函数的函数,下面我们具体分析函数,该函数其实是RhinoNET!CRhinoSocket:😛rocessReceiveBuffer,通过命名可以到是用于处理接收的数据BUF,在该函数入口点下断:

180145070的调用栈如下:
RhinoNET!CRhinoSocket::ProcessReceiveBuffer+0x33
RhinoNET!CRhinoSocket::OnReceive+0x170
RhinoNET!CRhinoProductSocket::OnReceive+0x3e
RhinoNET!CAsyncSocketX::DoCallBack+0x107
RhinoNET!CAsyncSocketX::ProcessAuxQueue+0x53
RhinoNET!CSocketWndX::OnSocketNotify+0x13
mfc140u!CWnd::OnWndMsg+0xba9
mfc140u!CWnd::WindowProc+0x3f
mfc140u!AfxCallWndProc+0x123
mfc140u!AfxWndProc+0x54
mfc140u!AfxWndProcBase+0x49
USER32!UserCallWinProcCheckWow+0x1ad
USER32!DispatchMessageWorke+0x3b5
Serv_U_180000000!CUPnPNotifyEvent::SetTimeout+0x30d85
Serv_U_180000000!CUPnPNotifyEvent::SetTimeout+0x30dfd
ucrtbase!crt_at_quick_exit+0x7d
kernel32!BaseThreadInitThunk+0xd
ntdll!RtlUserThreadStart+0x1d
仔细观察该函数的,一个外部大循环的内部结构。case,明显是加了协议的内部响应,配合关键字符串SSH_MS_IGORE,没有结果:
函数sub_180145070实现了部分或完整的SSH轻松协议。

通过使用 SSH 的处理方式,主要用于处理 MS 的功能:处理 MS
10045070处理10的味精(100节)
20 SSH_MSG_KEXINIT
30 SSH_MSG_ECDH 密钥交换初始化!案例 28
21 SSH_MSG_NEWKEYS
5 SSH_MSG_SERVICE_REQUEST
50 SSH_MSG_USERAUTH_REQUEST
90 SSH_MSG_CHANNEL_OPEN
98 SSH_MSG_CHANNEL_REQUEST
94 SSH_MSG_CHANNEL_DATA
上图:switch(v21)中v21就是SSH协议中的消息码,标识了消息类型。

通过文档[4]:
http://www.snailbook.com/docs/assigned-numbers.txt ,可查到相关SFTP协议的规范。
发送后的程序,主要修复了20,30,21三个MSG,其中在这些MSG中处理CLIENT支持的SSH加密算法处多调用了SSH库578,530和538做检查(EVP_Deaes_128_ctr,EVP_EncryptInit_ex和EVP_cryptInit_ex)
通过事务处理,对MS后继的程序进行排序,然后按顺序完成!
该漏洞利用是一个灵活的分配机制处理的逻辑处理错误,导致SSH协议的地方发生错误,因此就找不到传统的分配能力造成比较基本的COPY时间要求和限制。复现这个漏洞就需要对 Serv-U 的 SSH 握手过程进行 FUZZER。
3.2 FUZZER SSH招式过程
上面有的信息,便可以写一个发包FUZZ(不断生成码去测试),通过模拟SSH相似脚本的数据交换来模糊测试Serv-U服务器15.2.3.723。

脚本运行后,发现了一个崩溃,通过分析该崩溃可以确认我们完成20号消息后,不发送30号消息,直接发送21号消息,是造成-U崩溃的原因,打上奖励后不会产生该问题。那么说明很可能找到漏洞点。
该漏洞的强大功能可以利用,因为Serv-U.dll没有开启AS,而我们拥有远程控制EIP的能力,所以配合ROP便可以执行了。
如下图,可以看到函数的函数指针也被覆盖为了AAAAAA……,就是我们可以利用可控的数据覆盖一个虚函数函数,我们可以控制函数执行流程执行的ShellCode。

崩溃时的调用栈如下:

崩溃的最终位置不在 Serv-U.dll 里,而是在 libeay32.dll,动态链接是 OpenSSL 用于加解密的一个组件。通过被跟踪调试,发现可操作数据AAAAAA…的最后一个字节8 数据库libayay 错误地处理函数调用调用 32.dll,然后触发了崩溃。

该崩溃时发送的数据通信包打乱了SSH发现正常的数据包(招包乱序),因此顺应中的硬值0、1、2、3、4、5等为限制了数据的发送顺序,即发送了包20之后的30个,最多发送MSG包该包MSG漏洞。
3.3 漏洞利用
通过数据包流程分析和ServU的SSH处理过程通信-通过网络发现该漏洞,导致Serv-U的SSH处理流程乱序导致的未初始化漏洞。 :
SSH通信正常的处理过程为
密钥交换初始化(申请N字节内存,每个可能不同);
密钥协商算法交换参数,例如ECDH(填充N字节内存:在内存块内填充函数地址等);
加密码(中文名称为内存中的函数地址)

触发漏洞的过程为
密钥初始化(申请N字节内存);
加密码;加密码(中文名称为内存中的函数地址)
可以看到漏电触发过程省略了ECDH密钥交换这一步。

触发触发利用过程
发包占坑布局N字节空间,并释放;
密钥优先初始化(申请N字节内存,内存已被提前布局)
; 加密码触发装置(因为用密封的一块内部的键盘布置)

练习原理
使用中断限制了SSH通信过程,所以不会再执行函数中指针被攻击者提前安排并利用的情况。
通过分析该故障,确定了该漏洞的大启用链-U.U.能够利用,因为Serv并没有ASLR,为提供了除此DLL之外的我们的指令,上面所说的CALL位置在CALL条件下。 ,这让我们有更大的能力可以控制自己的位置。同时拥有更多的IP代码之后,就可以正确地ROP链上执行指定的指定。

Serv Serv 中并没有导入Protect 函数但导入了另外一个执行的函数ShellExecuteExW,所以它的目标就是构造ROP 链代码,需要调用ShellExecW 的参数。

首先使用capstone编写小工具提取ROP,获取所需指令的地址。

然后弹出这些指令,达到执行ShellExecuteExW的目标,具体步骤是:切换栈+布局参数+调用函数。

切换栈是前期过程,但该使用xchg、修改、mov以及lea等指令rsp启动。布局参数是Exec中最简单的,因为函数ShelluteExW整体只有一个参数,为一个结构体,而体内部的字符串指针执行命令的核心,所以这里涉及到多级指针的控制但又不是一个栈。出现错误,一定要慎重。

由于参数好之后,再次控制EIP跳转到导入表内的函数执行。由于函数SheuteExWll执行完毕,就代表用户已经着装执行完毕,但栈已经损坏,主程序也将执行终止。
如果不使用ShellExecuteExW位置也可以使用显示的代码,自行获取下图的VirtualProtect函数地址:

(上图地址DLL版本为15.2.3.723)
04 现有补充说明
截止 9 月 10 日,发布的更新情况如下:
| 版本号 | 发布时间 | 有无漏 |
| ----------------- | ---------- | ---------- |
| <15.2.3.717 | ---- | 有 |
| 15.2.3.717 | 2021/04/20 | 有 |
| 15.2.3.723 高频 1 | 2021/05/14 | 有 |
| 15.2.3.742 高频 2 | 2021/07/12 | 无(最新版) |
05 漏洞利用工具说明
5.1 软件版本
SSH-2.0-Serv-U_15.1.6.25至SSH-2.0-Serv-U_15.2.3.723
备注:SSH-2.0-Serv-U_15.6.25版本为2017年发布,更早的版本肯定也发放,目前测试的版本为2017年。SSH -2.0-Serv-U_15.2.3.723版本为最新版本的前一个版本。
5.2 远程利用限制条件
Serv-U需要以服务方式启动才能利用成功,不过Serv-U默认安装本来就是以服务方式启动的。如果以非服务方式启动则无法利用成功。

5.3 远程利用执行演示效果及特殊情况说明
1.利用成功后,目标机器的Serv-U.exe执行我们的ShellCode程序会启动一个PowerShell子进程-U(父进程为Serv.exe),并通过PowerShell回连我们设置的IP和端口,获取的SHELL权限为SYSTEM权限;
2.ShellCode的程序和执行的程序命令可以通过修改代码自行启动设置;
3.上述第2点提到的ShellCode执行的程序命令有长度限制,不能超过500个字节;
4.如果利用成功Serv-U.exe程序会崩溃并自动重启(不会弹框,因为是服务启动所以会自动重启),所以可以无限次远程重复利用的方式;
5.如果利用失败,测试执行完成后稍等十秒再进行下一次测试,一直执行成功;
6.每次的攻击成功率大概在20-50%;
7.单次攻击发出的网络数据包大小在2-3M左右,注意;
8.每个Serv-U版本都需要有ROP顺序,所以每个单独的小版本的Serv-U都需要定制化开发的攻击代码(程序有DEP,但关键DLL无ASLR)。
- 本文作安全技术分析,为用户提供无法获得奖励的漏洞和细节分析,所以不只是提供任何 POC。
参考链接:
[1] https://www.microsoft.com/security/blog/2021/07/13/microsoft-discovers-threat-actor-targeting-solarwinds-serv-u-software-with-0-day-exploit/
[2] https://www.solarwinds.com/trust-center/security-advisories/cve-2021-35211

[3] https://support.solarwinds.com/SuccessCenter/s/article/Serv-U-15-2-3-HotFix-2?language=en_US
[4] http://www.snailbook.com/docs/assigned-numbers.txt