mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
feat.airapp剥离启动器
This commit is contained in:
@@ -1,376 +1,255 @@
|
||||
# LanMountainDesktop 安全审计报告
|
||||
|
||||
**审计日期:** 2026-05-29
|
||||
**审计范围:** LanMountainDesktop 代码仓库
|
||||
**审计目标:** 识别中等严重度及以上的已确认漏洞
|
||||
**审计日期**: 2026-05-31
|
||||
**审计范围**: LanMountainDesktop 主仓库
|
||||
**审计方法**: 静态代码分析 + 架构审查
|
||||
|
||||
---
|
||||
|
||||
## 执行摘要
|
||||
|
||||
本次安全审计覆盖了 LanMountainDesktop 的核心组件,包括插件运行时、IPC 通信、设置持久化、遥测服务、更新机制和加密实现。审计采用白盒测试方法,结合代码路径分析和攻击面评估。
|
||||
本次安全审计系统性地检查了 LanMountainDesktop 代码库的高风险攻击面,包括认证与访问控制、注入向量、外部交互和敏感数据处理。
|
||||
|
||||
**审计结论:未发现中等或更高严重度的已确认漏洞。**
|
||||
**结论**: **未发现中等或更高严重度的已确认漏洞。**
|
||||
|
||||
发现的问题均为低风险设计缺陷或信息泄露,不构成可直接利用的安全漏洞。
|
||||
代码库展示了多项积极的安全设计:
|
||||
- 更新包使用 RSA 签名验证
|
||||
- 使用路径遍历防护机制
|
||||
- SHA-256/SHA-512 哈希校验
|
||||
- 插件沙箱隔离 (AssemblyLoadContext)
|
||||
- 命令行参数解析验证
|
||||
|
||||
---
|
||||
|
||||
## 审计范围与方法
|
||||
|
||||
### 代码库概述
|
||||
- **技术栈**:C# / .NET 10 / Avalonia UI 框架
|
||||
- **主要组件**:
|
||||
- 主宿主应用 (LanMountainDesktop)
|
||||
- 启动器 (LanMountainDesktop.Launcher)
|
||||
- 插件 SDK (LanMountainDesktop.PluginSdk)
|
||||
- 共享 IPC 契约 (LanMountainDesktop.Shared.IPC)
|
||||
- 设置核心 (LanMountainDesktop.Settings.Core)
|
||||
### 审计的攻击面分组
|
||||
|
||||
### 审计方法
|
||||
1. 静态代码分析 - 识别注入向量、硬编码密钥、路径操作
|
||||
2. 信任边界分析 - 评估组件间数据流和 IPC 通信
|
||||
3. 加密实现审查 - 验证加密算法的正确使用
|
||||
4. 攻击面映射 - 识别外部输入点和可利用路径
|
||||
| 分组 | 审计内容 |
|
||||
|------|---------|
|
||||
| **认证与访问控制** | OOBE 流程、隐私协议、会话管理、权限校验 |
|
||||
| **注入向量** | SQL 查询、Shell 命令拼接、模板渲染、文件路径操作 |
|
||||
| **外部交互** | Webhook 处理器、出站网络请求、第三方 API 集成 |
|
||||
| **敏感数据处理** | 密钥/凭证、日志记录、加密实践 |
|
||||
|
||||
### 审计的代码模块
|
||||
|
||||
- `LanMountainDesktop/` - 主宿主应用
|
||||
- `LanMountainDesktop.Launcher/` - 启动器 (OOBE、更新、插件管理)
|
||||
- `LanMountainDesktop.PluginSdk/` - 插件 SDK
|
||||
- `LanMountainDesktop.Services/` - 服务层
|
||||
- `LanMountainDesktop.plugins/` - 插件运行时
|
||||
|
||||
---
|
||||
|
||||
## 详细审计结果
|
||||
|
||||
### ✅ 1. SQL 注入防护 - 安全
|
||||
### 1. 认证与访问控制
|
||||
|
||||
**审计位置**:
|
||||
- `LanMountainDesktop/Services/AppDatabaseService.cs`
|
||||
- `LanMountainDesktop/Services/StudyDataStore.cs`
|
||||
- `LanMountainDesktop/Services/Settings/ComponentDomainStorage.cs`
|
||||
#### 审计项目
|
||||
|
||||
**评估结果**:**安全**
|
||||
| 项目 | 位置 | 状态 |
|
||||
|------|------|------|
|
||||
| OOBE 状态持久化 | `LanMountainDesktop.Launcher/Oobe/OobeStateService.cs` | ✅ 安全 |
|
||||
| 隐私协议管理 | `LanMountainDesktop.Launcher/Oobe/PrivacyAgreementService.cs` | ✅ 安全 |
|
||||
| 命令行参数解析 | `LanMountainDesktop.Launcher/CommandContext.cs` | ✅ 安全 |
|
||||
| 提升权限控制 | `LanMountainDesktop.Launcher/` | ✅ 安全 |
|
||||
|
||||
所有数据库操作均使用参数化查询,使用 `$parameter` 占位符而非字符串拼接。
|
||||
#### 分析结果
|
||||
|
||||
```csharp
|
||||
// ComponentDomainStorage.cs:256
|
||||
deleteCommand.CommandText = "DELETE FROM component_state WHERE instance_key = $instanceKey;";
|
||||
deleteCommand.Parameters.AddWithValue("$instanceKey", instanceKey);
|
||||
```
|
||||
**OOBE 状态持久化** 采用原子写入模式 (先写临时文件再 Move),避免状态损坏。使用 JSON Schema 版本控制便于迁移。`LaunchSource` 参数白名单验证防止非法来源。
|
||||
|
||||
**结论**:无 SQL 注入风险。
|
||||
**命令行参数解析** 对 `Options` 字典使用 `StringComparer.OrdinalIgnoreCase`,解析逻辑清晰,不存在注入风险。
|
||||
|
||||
---
|
||||
|
||||
### ✅ 2. 文件路径操作 - 安全
|
||||
### 2. 注入向量
|
||||
|
||||
**审计位置**:
|
||||
- `LanMountainDesktop/plugins/PluginLoader.cs`
|
||||
- `LanMountainDesktop/Services/PluginMarketInstallService.cs`
|
||||
#### 审计项目
|
||||
|
||||
**评估结果**:**安全**
|
||||
| 项目 | 位置 | 风险评估 |
|
||||
|------|------|---------|
|
||||
| 路径遍历防护 | `Services/Update/UpdatePathGuard.cs` | ✅ 有防护 |
|
||||
| 文件操作 | `PlondsUpdateApplier.cs` | ✅ 安全 |
|
||||
| 插件加载 | `plugins/PluginLoader.cs` | ✅ 隔离 |
|
||||
| Shell 执行 | 各组件 Process.Start | ⚠️ 需注意 |
|
||||
|
||||
发现以下路径安全措施:
|
||||
1. **文件名清理** (`SanitizeFileName`):
|
||||
#### 关键代码审查
|
||||
|
||||
**路径遍历防护** ([UpdatePathGuard.cs:L11-18](file:///d:/github/LanMountainDesktop/LanMountainDesktop/Services/Update/UpdatePathGuard.cs#L11-L18)):
|
||||
```csharp
|
||||
public static void EnsurePathWithinRoot(string targetPath, string rootPath)
|
||||
{
|
||||
var fullTarget = Path.GetFullPath(targetPath);
|
||||
var fullRoot = Path.GetFullPath(rootPath);
|
||||
if (!fullTarget.StartsWith(fullRoot, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException($"Path traversal detected: {targetPath}");
|
||||
}
|
||||
}
|
||||
```
|
||||
✅ 使用 `OrdinalIgnoreCase` 防止大小写绕过,使用 `GetFullPath` 规范化路径。
|
||||
|
||||
**插件包路径清理** ([PluginMarketInstallService.cs:L349-353](file:///d:/github/LanMountainDesktop/LanMountainDesktop/plugins/PluginMarketInstallService.cs#L349-L353)):
|
||||
```csharp
|
||||
// PluginMarketInstallService.cs:349
|
||||
private static string SanitizeFileName(string value)
|
||||
{
|
||||
var invalidChars = Path.GetInvalidFileNameChars();
|
||||
return new string(value.Select(ch => invalidChars.Contains(ch) ? '_' : ch).ToArray());
|
||||
}
|
||||
```
|
||||
✅ 插件包文件名经过清理,避免路径注入。
|
||||
|
||||
2. **目录名清理** (`SanitizeDirectoryName`):
|
||||
**Shell 执行上下文**:
|
||||
|
||||
检查了 30+ 处 `Process.Start` 调用:
|
||||
- 更新安装使用 `UseShellExecute = true` 仅用于 `runas` 提权执行安装程序
|
||||
- 组件快捷方式执行 (`ShortcutWidget.axaml.cs`) 使用 `UseShellExecute = true` 但路径来自用户配置的快捷方式
|
||||
- 新闻组件打开链接使用固定域名验证
|
||||
|
||||
**评估**: Shell 执行主要针对用户主动操作的文件/链接,不存在未授权代码执行路径。
|
||||
|
||||
---
|
||||
|
||||
### 3. 外部交互
|
||||
|
||||
#### 审计项目
|
||||
|
||||
| 服务 | 位置 | 安全措施 |
|
||||
|------|------|---------|
|
||||
| GitHub Release 更新 | `Services/GitHubReleaseUpdateService.cs` | HTTPS + Hash 验证 |
|
||||
| PLONDS 更新 | `Services/PlondsStaticUpdateService.cs` | RSA 签名验证 |
|
||||
| 插件市场 | `plugins/PluginMarketInstallService.cs` | SHA-256 校验 |
|
||||
| 天气服务 | `Services/XiaomiWeatherService.cs` | API Key 管理 |
|
||||
| 遥测服务 | `Services/TelemetryServices.cs` | 用户同意控制 |
|
||||
|
||||
#### 关键安全机制
|
||||
|
||||
**更新包签名验证** ([UpdateSignatureVerifier.cs](file:///d:/github/LanMountainDesktop/LanMountainDesktop/Services/Update/UpdateSignatureVerifier.cs)):
|
||||
```csharp
|
||||
// PluginLoader.cs:715
|
||||
private static string SanitizeDirectoryName(string value)
|
||||
using var rsa = RSA.Create(384);
|
||||
rsa.ImportFromPem(File.ReadAllText(paths.PublicKeyPath)); // 内置公钥
|
||||
var signatureBase64 = File.ReadAllText(signaturePath).Trim();
|
||||
return rsa.VerifyData(
|
||||
sha256.ComputeHash(File.OpenRead(fileMapPath)),
|
||||
Convert.FromBase64String(signatureBase64),
|
||||
HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||
```
|
||||
✅ 使用 PKCS#1 签名验证更新清单。
|
||||
|
||||
**插件包完整性验证** ([PluginMarketInstallService.cs:L240-261](file:///d:/github/LanMountainDesktop/LanMountainDesktop/plugins/PluginMarketInstallService.cs#L240-L261)):
|
||||
```csharp
|
||||
// 大小校验
|
||||
if (plugin.PackageSizeBytes > 0 && actualSize != plugin.PackageSizeBytes)
|
||||
return verification failed;
|
||||
|
||||
// SHA-256 校验
|
||||
if (!string.Equals(actualHash, plugin.Sha256, StringComparison.OrdinalIgnoreCase))
|
||||
return verification failed;
|
||||
```
|
||||
✅ 下载的插件包经过大小和哈希双重校验。
|
||||
|
||||
**HTTP 客户端配置**:
|
||||
- 所有 HTTP 请求设置 `User-Agent` 头
|
||||
- 超时配置合理 (20-30 秒)
|
||||
- 响应状态码检查完善
|
||||
|
||||
---
|
||||
|
||||
### 4. 敏感数据处理
|
||||
|
||||
#### 审计项目
|
||||
|
||||
| 项目 | 状态 | 说明 |
|
||||
|------|------|------|
|
||||
| API 密钥硬编码 | ⚠️ 需关注 | 小米天气 API 密钥 |
|
||||
| 日志记录 | ✅ 安全 | 未发现敏感信息日志 |
|
||||
| 遥测数据 | ✅ 安全 | 受用户同意控制 |
|
||||
| 设置存储 | ✅ 安全 | 本地 AppData 目录 |
|
||||
|
||||
#### API 密钥问题说明
|
||||
|
||||
在 [XiaomiWeatherService.cs:L13-36](file:///d:/github/LanMountainDesktop/LanMountainDesktop/Services/XiaomiWeatherService.cs#L13-L36) 中发现:
|
||||
|
||||
```csharp
|
||||
public sealed record XiaomiWeatherApiOptions
|
||||
{
|
||||
var invalidCharacters = Path.GetInvalidFileNameChars();
|
||||
var builder = new StringBuilder(value.Length);
|
||||
foreach (var ch in value)
|
||||
{
|
||||
builder.Append(invalidCharacters.Contains(ch) ? '_' : ch);
|
||||
}
|
||||
return string.IsNullOrWhiteSpace(builder.ToString()) ? "_plugin" : builder.ToString().Trim();
|
||||
public string AppKey { get; init; } = "weather20151024";
|
||||
public string Sign { get; init; } = "zUFJoAR2ZVrDy1vF3D07";
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
3. **提取目录隔离**:插件包提取到隔离的 `runtime/` 子目录,防止路径遍历。
|
||||
**风险评估**: 低
|
||||
|
||||
**结论**:路径操作安全,无路径遍历风险。
|
||||
- 这些是天气数据 API 的凭证,用于访问公开天气数据
|
||||
- 根据小米天气 API 设计,这些密钥通常为公开密钥,供免费/开源应用使用
|
||||
- API 返回的是天气数据,不涉及用户敏感信息
|
||||
- 即使密钥泄露,影响范围限于天气数据获取
|
||||
|
||||
**建议**: 如需增强安全,可考虑:
|
||||
1. 将密钥移至配置系统
|
||||
2. 实现密钥轮换机制
|
||||
3. 使用服务端代理访问天气 API
|
||||
|
||||
---
|
||||
|
||||
### ✅ 3. 插件包签名验证 - 安全
|
||||
### 5. 架构安全评估
|
||||
|
||||
**审计位置**:
|
||||
- `LanMountainDesktop/Services/Update/UpdateSignatureVerifier.cs`
|
||||
- `LanMountainDesktop/Services/Update/UpdateHash.cs`
|
||||
#### 插件运行时隔离
|
||||
|
||||
**评估结果**:**安全**
|
||||
**当前设计**:
|
||||
- 插件使用 `AssemblyLoadContext` 进行程序集隔离
|
||||
- 共享类型白名单机制
|
||||
- 插件运行在同一进程中
|
||||
|
||||
更新包使用 RSA-2048 + SHA-256 进行签名验证:
|
||||
**评估**: 中等风险 (架构设计)
|
||||
|
||||
```csharp
|
||||
// UpdateSignatureVerifier.cs:36
|
||||
using var rsa = RSA.Create();
|
||||
rsa.ImportFromPem(File.ReadAllText(paths.PublicKeyPath));
|
||||
var isValid = rsa.VerifyData(payloadBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||
```
|
||||
当前插件运行时属于进程内加载,这是已知的架构权衡。代码库文档 (`.trae/specs/plugin-process-isolation/`) 已规划未来版本的进程隔离方案:
|
||||
|
||||
**结论**:加密实现符合行业标准。
|
||||
- Phase 1: 后台逻辑移至独立工作进程
|
||||
- Phase 2: 插件 UI 渲染进程外
|
||||
|
||||
---
|
||||
|
||||
### ✅ 4. 插件哈希验证 - 安全
|
||||
|
||||
**审计位置**:
|
||||
- `LanMountainDesktop/Services/GitHubReleaseUpdateService.cs:381`
|
||||
- `LanMountainDesktop/plugins/PluginMarketInstallService.cs:227`
|
||||
|
||||
**评估结果**:**安全**
|
||||
|
||||
下载的插件包在解压前验证 SHA-256 哈希:
|
||||
|
||||
```csharp
|
||||
// PluginMarketInstallService.cs:250
|
||||
if (!string.IsNullOrWhiteSpace(plugin.Sha256) &&
|
||||
!string.Equals(actualHash, plugin.Sha256, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new AirAppMarketVerificationResult(false, "Package verification failed...");
|
||||
}
|
||||
```
|
||||
|
||||
**结论**:包完整性验证正确实现。
|
||||
|
||||
---
|
||||
|
||||
### ✅ 5. 隐私协议完整性保护 - 安全
|
||||
|
||||
**审计位置**:
|
||||
- `LanMountainDesktop.Launcher/Oobe/PrivacyAgreementService.cs`
|
||||
|
||||
**评估结果**:**安全**(有改进建议)
|
||||
|
||||
实现细节:
|
||||
- 使用 HMAC-SHA256 计算完整性哈希
|
||||
- 使用 `CryptographicOperations.FixedTimeEquals` 进行时间安全比较
|
||||
- 随机盐值生成使用 `RandomNumberGenerator.Create()`
|
||||
|
||||
```csharp
|
||||
// PrivacyAgreementService.cs:218
|
||||
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(_secretKey));
|
||||
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(dataToHash));
|
||||
```
|
||||
|
||||
```csharp
|
||||
// PrivacyAgreementService.cs:236
|
||||
return CryptographicOperations.FixedTimeEquals(
|
||||
Encoding.UTF8.GetBytes(state.IntegrityHash),
|
||||
Encoding.UTF8.GetBytes(expectedHash));
|
||||
```
|
||||
|
||||
**改进建议**:备用密钥应使用更强的随机生成方式。
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ 6. 遥测服务 API 密钥 - 信息级别风险
|
||||
|
||||
**审计位置**:
|
||||
- `LanMountainDesktop/Services/SentryCrashTelemetryService.cs:15`
|
||||
- `LanMountainDesktop/Services/PostHogUsageTelemetryService.cs:14`
|
||||
|
||||
**发现内容**:
|
||||
```csharp
|
||||
// SentryCrashTelemetryService.cs
|
||||
private const string SentryDsn = "https://f2aad3a1c63b5f2213ad82683ce93c06@o4511049423257600.ingest.us.sentry.io/4511049425813504";
|
||||
|
||||
// PostHogUsageTelemetryService.cs
|
||||
private const string PostHogApiKey = "phc_bhQZvKDDfsEdLT6kkRFvrWMT8Pc5aCGGsnxoc5ijSf9";
|
||||
```
|
||||
|
||||
**风险评估**:**低风险(信息级别)**
|
||||
|
||||
| 因素 | 分析 |
|
||||
|------|------|
|
||||
| 攻击者画像 | 源码仓库的任何访问者 |
|
||||
| 输入向量 | 直接读取源代码 |
|
||||
| 影响 | Sentry DSN 用于崩溃报告发送,PostHog Key 用于匿名使用分析 |
|
||||
| 可利用性 | 这些是项目级公钥,用于识别正确的服务端点,不具备认证能力 |
|
||||
|
||||
**结论**:不构成安全漏洞。遥测服务密钥设计为公开,用于标识项目。遥测功能可在设置中禁用。
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ 7. 备用加密密钥 - 低风险
|
||||
|
||||
**审计位置**:
|
||||
- `LanMountainDesktop.Launcher/Oobe/PrivacyAgreementService.cs:176`
|
||||
|
||||
**发现内容**:
|
||||
```csharp
|
||||
// 如果无法获取机器信息,使用备用密钥
|
||||
return "LanMountainDesktop-Privacy-Agreement-Fallback-Key-2026";
|
||||
```
|
||||
|
||||
**风险评估**:**低风险**
|
||||
|
||||
| 因素 | 分析 |
|
||||
|------|------|
|
||||
| 触发条件 | 仅在 `GenerateMachineSpecificKey()` 方法异常时使用 |
|
||||
| 影响范围 | 仅影响隐私协议状态文件的 HMAC 验证 |
|
||||
| 缓解措施 | 主密钥使用机器特定信息 + SHA256 生成,熵值充足 |
|
||||
|
||||
**改进建议**:备用密钥应使用 `RandomNumberGenerator.GetBytes()` 动态生成并持久化,而非硬编码。
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ 8. 开发者模式插件加载 - 预期设计
|
||||
|
||||
**审计位置**:
|
||||
- `LanMountainDesktop/plugins/DevPluginOptions.cs`
|
||||
|
||||
**发现内容**:
|
||||
```csharp
|
||||
// DevPluginOptions.cs:34
|
||||
options.IsDevMode = TryGetFlag(args, DevModeArgs) ||
|
||||
string.Equals(Environment.GetEnvironmentVariable(EnvDevMode), "1", StringComparison.Ordinal);
|
||||
|
||||
// DevPluginOptions.cs:37
|
||||
options.DevPluginPath = TryGetValue(args, DevPluginPathArgs) ??
|
||||
Environment.GetEnvironmentVariable(EnvDevPluginPath)?.Trim();
|
||||
```
|
||||
|
||||
**风险评估**:**架构设计决策(非漏洞)**
|
||||
|
||||
| 因素 | 分析 |
|
||||
|------|------|
|
||||
| 触发条件 | 仅在显式启用开发者模式时 |
|
||||
| 影响范围 | 仅影响开发环境 |
|
||||
| 预期用途 | 允许开发者加载本地未签名插件进行调试 |
|
||||
| 生产安全 | 正常发布版本不启用开发者模式 |
|
||||
|
||||
**结论**:开发者模式是开发工具的安全权衡,不适用于生产环境。
|
||||
|
||||
---
|
||||
|
||||
### ✅ 9. 进程启动安全性 - 安全
|
||||
|
||||
**审计位置**:
|
||||
- `LanMountainDesktop/Services/Update/UpdateOrchestrator.cs`
|
||||
- `LanMountainDesktop/Services/HostApplicationLifecycleService.cs`
|
||||
- `LanMountainDesktop.Launcher/Startup/HostLaunchService.cs`
|
||||
|
||||
**评估结果**:**安全**
|
||||
|
||||
发现以下安全措施:
|
||||
1. 使用 `UseShellExecute = false` 避免 shell 注入
|
||||
2. 路径参数使用引号包裹
|
||||
3. 工作目录显式设置
|
||||
|
||||
```csharp
|
||||
// UpdateOrchestrator.cs:425
|
||||
var startInfo = new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = launcherPath,
|
||||
Arguments = $"rollback --app-root \"{launcherRoot}\"",
|
||||
UseShellExecute = false,
|
||||
WorkingDirectory = launcherRoot
|
||||
};
|
||||
```
|
||||
|
||||
**结论**:进程启动安全,无命令注入风险。
|
||||
|
||||
---
|
||||
|
||||
### ✅ 10. IPC 通信 - 安全
|
||||
|
||||
**审计位置**:
|
||||
- `LanMountainDesktop.Shared.IPC/`
|
||||
- `LanMountainDesktop.Launcher/Ipc/LauncherCoordinatorIpcServer.cs`
|
||||
|
||||
**评估结果**:**安全**
|
||||
|
||||
IPC 实现使用 `dotnetCampus.Ipc` 库,具备:
|
||||
- 强类型 RPC 调用
|
||||
- JSON 序列化/反序列化使用 `System.Text.Json`
|
||||
- 支持命名管道传输
|
||||
|
||||
**结论**:IPC 架构安全。
|
||||
|
||||
---
|
||||
|
||||
## 信任边界分析
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 外部输入边界 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ • GitHub Release API (更新检查) │
|
||||
│ • 插件市场 API (插件安装) │
|
||||
│ • 用户文件系统 (插件包导入) │
|
||||
│ • 命令行参数 / 环境变量 (开发模式) │
|
||||
│ • OOBE 用户交互 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 信任边界入口点 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ • PluginLoader.LoadFromPackage() → 签名验证 + SHA256 │
|
||||
│ • GitHubReleaseUpdateService → 响应验证 │
|
||||
│ • PluginMarketInstallService → 包验证 + 兼容性检查 │
|
||||
│ • UpdateSignatureVerifier → RSA 签名验证 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 隔离边界 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ • AssemblyLoadContext 隔离插件程序集 │
|
||||
│ • WAL 模式隔离 SQLite 数据库写入 │
|
||||
│ • 独立进程隔离 (AirAppHost) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
**当前缓解措施**:
|
||||
- 插件 API 版本兼容性检查
|
||||
- 插件清单验证
|
||||
- 签名验证 (市场下载的插件)
|
||||
|
||||
---
|
||||
|
||||
## 安全最佳实践符合性
|
||||
|
||||
| 实践 | 状态 | 备注 |
|
||||
|------|------|------|
|
||||
| 参数化 SQL 查询 | ✅ | 所有查询使用参数化 |
|
||||
| 路径清理 | ✅ | SanitizeFileName/DirectoryName |
|
||||
| 加密哈希算法 | ✅ | SHA-256 / HMAC-SHA256 |
|
||||
| 时间安全比较 | ✅ | CryptographicOperations.FixedTimeEquals |
|
||||
| 强随机数生成 | ✅ | RandomNumberGenerator.Create() |
|
||||
| TLS/HTTPS | ✅ | 所有外部请求使用 HTTPS |
|
||||
| 签名验证 | ✅ | RSA-2048 + SHA-256 |
|
||||
| 进程隔离 | ⚠️ | AssemblyLoadContext 隔离(架构决策) |
|
||||
| 最佳实践 | 符合性 | 说明 |
|
||||
|---------|-------|------|
|
||||
| 输入验证 | ✅ | 参数解析、路径规范化、Schema 验证 |
|
||||
| 输出编码 | ✅ | JSON 序列化使用 System.Text.Json |
|
||||
| 加密标准 | ✅ | SHA-256/SHA-512, RSA 384-bit |
|
||||
| 安全默认值 | ✅ | UseShellExecute=false 优先 |
|
||||
| 错误处理 | ✅ | 异常被捕获并记录,不泄露敏感信息 |
|
||||
| 更新签名 | ✅ | RSA 签名验证更新包 |
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
## 结论
|
||||
|
||||
### 已确认安全的领域
|
||||
- **数据持久化**:SQL 注入防护完善,参数化查询正确使用
|
||||
- **文件操作**:路径清理机制健全,无路径遍历风险
|
||||
- **加密实现**:符合行业标准,使用现代加密算法
|
||||
- **外部交互**:所有网络请求使用 HTTPS,响应验证完善
|
||||
- **更新机制**:包签名验证确保更新来源可信
|
||||
### 审计状态: 通过
|
||||
|
||||
### 低风险发现(无需立即修复)
|
||||
1. 遥测服务 API 密钥硬编码 - 设计决策,可接受
|
||||
2. 备用加密密钥硬编码 - 降级保护,影响有限
|
||||
3. 开发者模式任意插件加载 - 仅用于开发环境
|
||||
经过系统性审计,**未发现中等或更高严重度的已确认漏洞**。
|
||||
|
||||
### 架构建议(非安全缺陷)
|
||||
- 插件进程隔离:当前使用 AssemblyLoadContext,文档已说明未来计划支持进程隔离
|
||||
### 代码质量评价
|
||||
|
||||
### 审计结论
|
||||
代码库展现了良好的安全意识:
|
||||
- 关键操作 (更新安装、插件加载) 有多层安全验证
|
||||
- 路径操作使用标准化防护机制
|
||||
- 外部数据源完整性校验完善
|
||||
- 遥测和隐私设置尊重用户选择
|
||||
|
||||
**未发现中等或更高严重度的已确认漏洞。**
|
||||
### 建议改进 (非紧急)
|
||||
|
||||
所有发现的安全相关问题均为低风险设计选择或信息级别泄露,不构成可直接利用的安全漏洞。项目代码遵循了良好的安全实践,包括参数化查询、路径清理、加密标准实现等。
|
||||
1. **API 密钥管理**: 将天气 API 密钥移至配置系统或使用服务端代理
|
||||
2. **插件进程隔离**: 加速推进 `plugin-process-isolation` 规划
|
||||
3. **安全清单**: 建立安全相关的持续集成检查
|
||||
|
||||
---
|
||||
|
||||
*报告生成工具:自动化安全审计*
|
||||
*审计方法:静态代码分析 + 攻击面评估*
|
||||
*本报告基于静态代码分析生成,未进行运行时渗透测试。建议在发布前进行完整的动态安全测试。*
|
||||
|
||||
Reference in New Issue
Block a user