IDA Pro > IDA Pro教程 > 技术问题 > 深入了解SolarWinds Serv-U SSH漏洞

深入了解SolarWinds Serv-U SSH漏洞

发布时间:2022-10-10 15: 57: 34

 几周前,微软检测到一个0-day远程代码执行漏洞被用来在有限且有针对性的攻击中攻击SolarWinds Serv-U FTP软件。微软威胁情报中心(MSTIC)根据观察到的受害者特征、策略和程序,高度自信地将这次攻击归咎于DEV-0322,这是一个在中国境外开展活动的组织。在此博客中,我们与SolarWinds分享了有关该漏洞的技术信息(编号为CVE-2021-35211),SolarWinds及时发布了安全更新以修复漏洞并缓解攻击。

 

 该分析由Microsoft进攻性研究与安全工程团队进行,该团队负责支持MSTIC等具有漏洞利用开发专业知识的团队。我们团队的职责是让计算更安全。为此,我们利用我们对攻击者技术和流程的知识,通过逆向工程、攻击创建和复制、漏洞研究和情报共享来构建和改进Windows和Azure中的保护。

 

 7月初,MSTIC向我们的团队提供了似乎表明针对SolarWinds Serv-U FTP服务器的SSH组件中新发现的漏洞的利用行为的数据。尽管intel包含有用的指标,但它缺少相关的漏洞利用,因此我们的团队着手重建漏洞利用,这需要首先找到并了解Serv-U SSH相关代码中的新漏洞。

 

 由于我们知道这是一个远程的预授权漏洞,我们很快构建了一个专注于SSH握手的预授权部分的模糊器,并注意到该服务捕获并通过了所有访问违规而不终止进程。很明显,Serv-U进程将使隐蔽、可靠的利用尝试变得容易完成。我们得出的结论是,被利用的漏洞是由Serv-U最初创建OpenSSL AES128-CTR上下文的方式引起的。反过来,这可能允许在解密连续的SSH消息期间使用未初始化的数据作为函数指针。因此,攻击者可以通过连接到开放的SSH端口并发送格式错误的预授权连接请求来利用此漏洞。

 

 我们通过Microsoft安全漏洞研究(MSVR)通过协调漏洞披露(CVD)与SolarWinds分享了这些发现以及我们创建的模糊器,并与他们一起解决了这个问题。这是情报共享和行业协作的示例,通过检测产品攻击和通过安全更新修复漏洞,从而为更广泛的社区提供全面保护。

 

 Serv-U实现SSH的漏洞

 Secure Shell(SSH)是一种广泛采用的协议,用于在不受信任的网络上进行安全通信。协议行为在多个评论请求(RFC)中定义,现有实现可在开源代码中获得;我们主要使用RFC 4253、RFC 4252和libssh作为此分析的参考。

 

 通过枚举对“SSH-”字符串的引用,可以找到Serv-U中SSH的实现,该字符串必须存在于发送到服务器的第一个数据中。此类代码最可能的实例如下:

图1.“SSH-”字符串的有希望的实例

 在上面的代码上设置断点并尝试使用SSH客户端连接到Serv-U证实了我们的假设,并导致断点被以下调用堆栈命中:

图2.由图1中代码设置的断点产生的调用堆栈

 此时,我们注意到Serv-U.dll和RhinoNET.dll都禁用了ASLR支持,这使得它们成为ROP小工具的主要位置,因为它们中的任何地址对于给定Serv在互联网上运行的任何服务器实例都是不变的-U版本。

 

 在逆向RhinoNET和Serv-U DLL中的相关代码后,我们可以在Serv-U处理它们时跟踪SSH消息的路径。为了处理传入的SSH连接,Serv-U.dll创建一个CSUSHSocket对象,该对象派生自RhinoNET!CRhinoSocket类。CSUSSHSocket对象的生命周期是TCP连接的长度——它可能在许多单独的TCP数据包中持续存在。底层CRhinoSocket为套接字提供缓冲接口,以便单个TCP数据包可以包含任意数量的字节。这意味着单个数据包可能包含任意数量的SSH消息(只要它们符合最大缓冲区大小),以及部分SSH消息。然后CSUSSHSocket::ProcessRecvBuffer函数负责从缓冲的套接字数据中解析SSH消息。

 

 CSUSSHSocket::ProcessRecvBuffer首先使用ParseBanner检查SSH版本。如果ParseBanner成功地从横幅中解析SSH版本,则ProcessRecvBuffer会循环ParseMessage,它会在套接字数据中获取指向当前消息的指针,并从消息中提取msg_id和长度字段(稍后将详细介绍ParseMessage函数)。

图3.从CSUSSSHSocket::ProcessRecvBuffer处理循环中选择代码

 被迭代的套接字数据在概念上是伪C结构ssh_msg_t的数组,如下所示。消息数据包含在有效负载缓冲区中,其第一个字节被认为是msg_id:

 ProcessRecvBuffer然后根据msg_id分派对消息的处理。一些消息直接从消息解析循环处理,而另一些则传递给ssh_pkt_others,后者将消息发布到队列中,以供另一个线程提取和处理。

图4.CSUSSSHSocket::ProcessRecvBuffer中的Pre-auth可达处理程序

 如果msg_id被推迟到备用线程,CSSHSession::OnSSHMessage会处理它。此功能主要处理需要与Serv-U管理的用户配置文件数据交互的消息(例如,针对每个用户凭据的身份验证)和UI更新。CSSHSession::OnSSHMessage在漏洞搜寻方面被证明是无趣的,因为其中的大多数消息处理程序都需要成功的用户身份验证(初始遥测表明这是一个预身份验证漏洞),并且在其余处理程序中没有发现漏洞。

 

 当最初对带有调试器的Serv-U运行模糊器时,很明显应用程序正在捕获通常会使进程崩溃的异常(例如访问冲突),记录错误,修改状态足以避免进程终止,然后继续,好像没有问题一样。这种行为提高了文件服务器应用程序的正常运行时间,但也导致可能的内存损坏在进程中徘徊并随着时间的推移而累积。作为攻击者,这提供了诸如暴力破解代码地址或具有动态地址的数据的机会。

 

 这种对访问违规的挤压有助于利用,但对于模糊测试,我们过滤掉了由读/写访问违规产生的“无趣”异常,并让模糊器运行直到遇到RIP已损坏的错误。这很快导致了以下崩溃上下文:

图5.WinDbg显示来自fuzzer生成的SSH消息的崩溃上下文

 如上所示,libeay32.dll(OpenSSL的一部分)中的CRYPTO_ctr128_encrypt试图调用无效地址。使用的OpenSSL版本是1.0.2u,所以我们获得了源代码来阅读。下面展示了相关的OpenSSL功能:

 同时,下面显示了传递的结构:

 崩溃函数是通过以下路径从OpenSSL API边界到达的:EVP_EncryptUpdate->evp_EncryptDecryptUpdate->aes_ctr_cipher->CRYPTO_ctr128_encrypt。

 

 进一步查看调用堆栈,很明显Serv-U从CSUSSSHSocket::ParseMessage调用EVP_EncryptUpdate,如下所示:

图6.调用OpenSSL的位置,其中可能会调用攻击者控制的函数指针

 此时,我们手动最小化了fuzzer产生的TCP数据包缓冲区,直到只剩下触发崩溃所需的SSH消息。在RFC中使用的符号中,所需的SSH消息是:

 请注意,以下描述引用了当崩溃代码路径明显试图解密缓冲区时调用的“加密”函数。这不是错误:Serv-U使用加密OpenSSL API,虽然对于代码清晰度来说不是最佳的,但它在行为上是正确的,因为高级加密标准(AES)在计数器(CTR)模式下运行。

 

 在通过消息处理序列进行时间旅行调试跟踪和调试后,我们发现问题的根本原因是Serv-U最初使用如下代码创建了OpenSSL AES128-CTR上下文:

使用NULL密钥和/或IV调用EVP_EncryptInit_ex是有效的,并且Serv-U在这种情况下这样做是因为上下文是在处理KEXINIT消息时创建的,这是在密钥材料准备好之前。但是,在设置密钥之前不会执行AES密钥扩展,并且在执行密钥扩展之前,ctx->cipher_data结构中的数据保持未初始化状态。我们可以(正确地)推测我们的消息序列导致崩溃导致enc_algo_client_to_server->decrypt在初始化密钥材料之前调用。Serv-U KEXINIT处理程序为消息中给出的所有参数创建对象。

但是,在处理以下NEWKEYS消息之前,当前为连接活动的相应对象不会被新创建的对象替换。客户端总是在正常的SSH连接中完成密钥交换过程,然后再发出NEWKEYS消息。无论连接状态或密钥交换如何,Serv-U都会处理NEWKEYS(从而设置m_bCipherActive标志并替换密码对象)。由此,我们可以看出,我们的模糊序列中的最后一个消息类型无关紧要——在部分初始化的AES CTR密码对象被激活后,只需要在套接字缓冲区中处理一些数据即可触发解密。

 

开发

由于该漏洞允许从未初始化的内存中加载RIP,并且在过程中有一些没有ASLR的模块,因此利用并不那么复杂:我们可以找到一种方法来控制未初始化的cipher_data结构的内容,指向cipher_data->block函数指针在一些初始的ROP小工具上,并启动一个ROP链。由于异常处理程序会导致任何错误被忽略,我们不一定需要在第一个数据包上获得可靠的代码执行。可以重试利用,直到代码执行成功,但是这会在日志文件中留下痕迹,因此可能值得投入更多精力来避免记录日志的不同技术。第一步是找到密码数据分配,因为预填充缓冲区的最直接途径是喷射目标分配大小的分配并在尝试将地址回收为cipher_data之前释放它们。ctx->cipher_data在EVP_CipherInit_ex中使用以下行进行分配和分配:

使用调试器,我们可以看到我们案例中的ctx_size是0x108,并且这个分配器最终会调用ucrtbase!_malloc_base。从前面的逆向我们知道,CRhinoSocket和CSUSSSHSocket级别的数据包解析都调用operator new[]来分配空间来保存我们发送的数据包。幸运的是,这也以ucrtbase!_malloc_base结束,使用相同的堆。因此,预填充目标分配就像发送一个适当大小的TCP数据包或SSH消息然后关闭连接以确保它被释放一样简单。使用此路径进行喷洒不会触发其他相同大小的分配,因此我们不必担心会污染堆。

 

从调试器/反汇编中提取的另一个重要值是offsetof(EVP_AES_KEY,block),因为需要将喷射数据中的偏移量设置为初始ROP小工具。该值为0xf8。方便的是,EVP_AES_KEY结构的其余大部分可用于ROP链内容本身,并且在受控函数指针调用时,寄存器rbx、r8和r10中存在指向该结构基址的指针。

 

作为一个简单的概念证明,请考虑以下python代码:

以上结果在调试器中产生以下上下文:

图 7. 显示攻击者控制的 rcx、rdx 和 rip 的机器上下文

结论:负责任的披露和行业合作提高了所有人的安全性

我们的研究表明,Serv-U SSH服务器存在预授权远程代码执行漏洞,可以在默认配置中轻松可靠地利用该漏洞。攻击者可以通过连接到开放的SSH端口并发送格式错误的预授权连接请求来利用此漏洞。成功利用后,该漏洞可能允许攻击者安装或运行程序,例如我们之前报道的针对性攻击。

 

我们通过协调漏洞披露(CVD)将我们的发现分享给了SolarWinds。我们还分享了我们创建的模糊器。SolarWinds发布了一个咨询和安全补丁,我们强烈鼓励客户应用该补丁。如果您不确定您的系统是否受到影响,请在SolarWinds客户门户中打开支持案例。

 

除了与SolarWinds共享漏洞详细信息和模糊测试工具外,我们还建议为Serv-U进程中加载​​的所有二进制文件启用ASLR兼容性。启用ASLR是一个简单的编译时标志,默认情况下启用,并且从Windows Vista开始可用。ASLR是针对暴露于不受信任的远程输入的服务的关键安全缓解措施,它要求进程中的所有二进制文件都是兼容的,以便有效地防止攻击者在其漏洞利用中使用硬编码地址,这在Serv-U中是可能的。

 

我们要感谢SolarWinds的及时响应。该案例进一步强调了软件供应商、安全研究人员和其他参与者之间需要不断协作,以确保用户计算体验的安全性。

 

原文地址:https://www.microsoft.com/security/blog/2021/09/02/a-deep-dive-into-the-solarwinds-serv-u-ssh-vulnerability/

展开阅读全文

标签:IDA

读者也访问过这里:
邀请您进入交流群 点击扫码
400-8765-888 kefu@makeding.com

专业销售为您服务

欢迎添加好友,了解更多IDA优惠信息,领逆向工程学习资料礼包1份!
热门文章
exe反编译工具哪个好?反编译能力强的工具盘点
随着软件技术的发展,exe(可执行文件)已经成为了电脑、手机等多个平台上的主要软件运行格式,而对于exe文件的反编译也成为了逆向工程中不可缺少的一个步骤。本文将介绍一些常用的exe反编译工具,并评价其优缺点,帮助读者选择合适的工具。
2023-04-12
idapro怎么改为中文
IDA Pro是一款功能强大的反汇编和反编译工具,广泛应用于逆向工程和软件开发领域。在使用IDA Pro时,如果我们不习惯英文界面,可以将其改为中文界面。本文将介绍IDA Pro怎么改为中文界面。IDA Pro界面改成中文主要有两种方法,下面是详细介绍。
2023-04-19
c++反编译工具有哪些
反编译C++代码的工具一般是针对可执行文件和库文件的反汇编和逆向分析工具。本文将给大家介绍c++反编译工具有哪些的内容。市面说的c++反编译工具有很多,下面介绍几款使用认识较多的软件。
2023-04-23
ida怎么查找字符串 ida字符串窗口快捷键
在数字化时代,逆向工程作为解密软件和分析程序的关键技术,正日益受到广泛关注。在逆向分析的过程中,IDA(Interactive DisAssembler)是一款备受推崇的工具,它为逆向工程师们提供了强大的功能和灵活的操作。本文将带您深入探讨如何在IDA中查找字符串,优化字符串窗口的使用,并探讨IDA如何将变量转换成字符串,帮助您更加熟练地驾驭这一工具,为逆向分析的世界增添一抹精彩。
2023-09-27
ida如何转伪代码 ida伪代码怎么看
IDA Pro是一款常用的反汇编和反编译工具,可以帮助我们分析二进制文件的实现细节和执行过程,以便更好地理解程序的执行过程和逻辑。在进行逆向工程的过程中,我们经常需要将反汇编结果转换为伪代码,以便更好地进行分析和修改。本文将介绍如何使用IDA Pro转换为伪代码,并简单讲解ida伪代码怎么看。
2023-04-14
最新文章
ida设置断点怎么运行 ida断点在键盘上的使用方法
在使用IDA pro进行逆向分析的过程中,断点设置是最基础也是最常用的调试手段之一。尤其是在处理复杂的汇编逻辑或定位关键执行点时,合理地设置并运行断点,能够极大提升分析效率与准确度。本文将围绕ida设置断点怎么运行,ida断点在键盘上的使用方法两个关键问题展开,详细介绍IDA pro中的断点操作方式、快捷键使用逻辑及其在多架构平台上的适配特性,帮助用户在实战中更加高效掌控IDA pro的调试能力。
2025-09-28
IDA调试MBR切换到16位模式 IDA调试Apk修改寄存器v0
在逆向分析中,MBR和APK分别代表底层引导机制与上层移动应用的典型研究对象。前者常涉及16位实模式与汇编流程控制的深入理解,后者则要求熟练掌握Smali代码、寄存器模拟与调试器调用。IDA pro作为广泛应用的逆向工具,不仅支持对MBR类二进制的低位调试,也能在APK分析中发挥符号识别与寄存器控制优势。本文将围绕IDA调试MBR切换到16位模式和IDA调试Apk修改寄存器v0两个核心主题展开操作细节讲解。
2025-09-28
IDA逆向QT控件应用程序 qt获取窗口内所有控件
在逆向分析跨平台图形界面程序的实践中,QT框架的广泛应用对逆向人员提出了更高要求。QT采用信号与槽、动态UI加载等机制,传统Windows API分析手段难以适配。利用IDA pro进行QT应用程序的逆向分析,结合符号信息、vtable结构及动态控件创建逻辑,可以有效提取界面控件层级、信号连接机制等核心信息。同时,若拥有源码或调试权限,还可以通过QT原生函数如`findChildren`等方式实现对窗口中所有控件的枚举与分析。本文将围绕IDA逆向QT控件应用程序和qt获取窗口内所有控件两大主题进行详细讲解。
2025-09-28
IDA pro修改so教程 IDA pro修改exe
在逆向分析与二进制安全研究中,IDA pro作为主流静态分析工具,其强大的反汇编与重构能力,广泛应用于ELF格式的so库与PE格式的exe文件修改。通过IDA pro修改so文件,可用于Android应用补丁、破解函数逻辑、绕过验证;而对exe文件的修改则常用于Windows下的补丁、功能改写与程序定制。掌握IDA pro修改so与exe的流程,不仅能提升分析效率,更是逆向工程技能的基础能力。以下内容将系统讲解IDA pro修改so教程,IDA pro修改exe两大操作场景的具体步骤,帮助用户完整掌握二进制修改流程。
2025-09-28
IDA pro中修改remote GDB路径 IDA pro修改加载地址
在进行逆向分析或调试远程目标设备时,IDA pro作为静态与动态分析的核心工具,配合GDB远程调试功能可以实现对嵌入式、IoT系统乃至裸机程序的高效控制。而在不同项目中,经常会需要变更remote GDB路径或重新设定加载地址,这些操作看似简单,实则涉及IDA pro配置逻辑、GDB插件加载机制、调试环境变量等多个技术细节。本文将围绕IDA pro中修改remote GDB路径,IDA pro修改加载地址两大关键点 ,以助于用户更好掌控IDA pro调试行为。
2025-09-28
ida反汇编成c语言的三个步骤 怎样将反汇编代码转换成c语言代码
在逆向工程、安全分析以及老旧系统维护的实践中,如何借助IDA将汇编语言转化为C语言,是许多技术人员迫切关注的主题。IDA作为目前最成熟的反汇编工具之一,配合Hex-Rays Decompiler插件,可以将目标二进制程序自动生成接近C语言语义的伪代码,从而帮助开发者更快速理解程序逻辑、重构核心功能。本文围绕“ida反汇编成c语言的三个步骤,怎样将反汇编代码转换成c语言代码”这一主题,从实际操作出发,详细讲解整个转化过程。
2025-09-28

通过微信咨询我们

欢迎添加好友,了解更多IDA优惠信息,领取逆向工程学习资料礼包1份!

读者也喜欢这些内容: