seal-sec-demo-2/seal-security-nuget-demo-net7
GitHub: seal-sec-demo-2/seal-security-nuget-demo-net7
面向.NET 7的Seal Security产品演示,展示如何在不升级NuGet包主版本的情况下通过就地补丁修复Newtonsoft.Json和log4net中的已知高危漏洞。
Stars: 0 | Forks: 0
# 浏览器 + CLI 演示 (NuGet/C#) — .NET 7 版本
## 为什么需要一个 .NET 7 分支?
这是规范的 [`seal-security-nuget-demo`](https://github.com/seal-sec-demo-2/seal-security-nuget-demo)(针对 `net9.0`)的重新定向分支。漏洞利用的故事、控制器以及加封的包列表完全相同——**唯一的区别在于 `TargetFramework`**。
它的存在是因为大多数企业客户无法按需迁移到最新的 .NET SDK。**.NET 7 已于 2024 年 5 月 14 日停止支持**,但真正的生产环境出于兼容性、认证或运维原因,仍在使用它。这正是 Seal Security 设计旨在解决的场景:当客户不能(或不愿意)进行主版本升级时,Seal 会在相同版本下**就地修补**易受攻击的依赖项,无需更改公共 API,也无需客户修改应用代码。这个演示允许在客户实际的运行技术栈上进行沟通,而不是要求他们先安装 net8/net9。
该分支通过 `global.json` 将 SDK 固定到 `7.0.x`,以防止在演示过程中意外升级混入其中。
## 概述
这个演示应用是一个简单的 ASP.NET Core 欢迎页,它使用 **Newtonsoft.Json 12.0.2** 将用户输入解析为配置对象。应用有一个名称字段——输入你的名字,点击 Go,它会显示 **"Welcome, alice!"**。在底层,它通过 Newtonsoft.Json 的 `JsonConvert.DeserializeObject()` 传递输入。就是这样——完全是对一个流行 JSON 库的标准使用。
问题在于,Newtonsoft.Json 12.0.2(以及 13.0.1 之前的版本)存在 **CVE-2024-21907**——一个高危的拒绝服务漏洞,**CVSS 评分为 7.5 (HIGH)**。这个演示展示了 Seal Security 如何在不要求主版本升级的情况下,就地修补该漏洞。
## 漏洞:CVE-2024-21907
### 什么是该漏洞?
Newtonsoft.Json 的 `JsonConvert.DeserializeObject()` 方法可以通过构造深度嵌套的 JSON 负载来被利用。在反序列化为类型化对象(POCO)时,该库的 `JsonSerializerInternalReader` 会执行真正的递归调用(`CreateValueInternal → CreateObject → PopulateObject → SetPropertyValue → CreateValueInternal`),从而导致**堆栈溢出**,进而导致应用程序崩溃(拒绝服务)。
### 漏洞利用是如何运作的
应用程序接收用户输入并通过 Newtonsoft.Json 进行解析。如果输入是一个 URL,应用程序会首先获取其内容——这是配置加载器、API 测试器和 webhook 接收器使用的真实模式:
```
public class NestedConfig
{
[JsonProperty("n")]
public NestedConfig? N { get; set; }
}
var config = JsonConvert.DeserializeObject(name);
```
**正常输入:** 输入 `alice` → 显示 "Welcome, alice!"
**漏洞利用:** 将此 URL 粘贴到名称字段中并点击 **Go**:
```
https://raw.githubusercontent.com/seal-sec-demo-2/json-payload/main/payload.json
```
应用检测到这是一个 URL,获取 [json-payload](https://github.com/seal-sec-demo-2/json-payload)(深度嵌套的 JSON `{"n":{"n":{...}}}`),并通过 Newtonsoft.Json 将其反序列化为递归的 `NestedConfig` 类——从而触发堆栈溢出。
`JsonSerializerInternalReader` 针对每一个嵌套层级在 `CreateValueInternal → CreateObject → PopulateObject → SetPropertyValue` 之间循环递归。在深度达到约 5,000 层时,这将耗尽线程堆栈,应用程序会因 `StackOverflowException` 而崩溃——进程会立即死亡(无法进行优雅的错误处理)。
### 现实世界的影响
利用此漏洞,攻击者可以:
- 通过发送恶意 JSON 负载**使应用程序崩溃**
- 造成影响所有用户的**拒绝服务**
- 通过反复利用**耗尽服务器资源**
- **绕过速率限制**,因为每个请求都会导致进程崩溃
### 为什么不直接升级到 Newtonsoft.Json 13.0.1?
公开发布的修复需要升级到 13.0.1 版本。然而,主版本升级通常会带来:
- 序列化行为中的**破坏性 API 变更**
- 与期望特定版本的其他库产生**兼容性问题**
- 对所有序列化/反序列化代码路径产生**大量的测试需求**
- 生产环境中**运行时行为发生变化的风险**
这使得“直接升级”的修复方案很容易成为一个需要花费**数周开发者时间**的项目——从而在此期间让漏洞一直处于开放状态。
### Seal Security 如何修复它
Seal 的修补版本(`12.0.2-sp1`)在不更改任何公共 API 的情况下增加了**递归深度保护**。该补丁:
1. 添加默认的 `MaxDepth` 限制以防止无界递归
2. 通过抛出适当的异常来优雅地处理深度嵌套,而不是引发堆栈溢出
3. **不更改任何公共 API**——现有代码无需修改即可继续工作
这与 Newtonsoft.Json 13.0.1 中应用的缓解策略相同,只是被向后移植到了 12.0.2 作为直接替代方案。
## 其他易受攻击的依赖项
本演示还包含其他 Seal Security 可以修补的易受攻击的 NuGet 包:
### log4net 2.0.5 - CVE-2018-1285 (CVSS 9.8 CRITICAL)
log4net 的 XML 配置解析中存在 **XML 外部实体 (XXE) 漏洞**。可以控制 log4net 配置文件的攻击者能够:
- 从服务器读取任意文件
- 执行服务器端请求伪造 (SSRF)
- 导致拒绝服务
## 前置条件
- **.NET 7.0 SDK** ([从 Microsoft 下载](https://dotnet.microsoft.com/download/dotnet/7.0))
- 用于 Windows x64 的 **Seal Security CLI v0.3.238** ([直接下载](https://github.com/seal-community/cli/releases/download/v0.3.238/seal-windows-amd64-v0.3.238.exe))
- Seal Security 令牌(来自 Seal 面板)
详细的 Windows Server 安装及运行指南在 [`README-WINDOWS-SERVER.md`](README-WINDOWS-SERVER.md) 中。下面的快速入门以简明扼要的形式涵盖了相同的步骤。
## 快速入门 (本地 Windows Server)
### 1. 设置环境变量
PowerShell:
```
$env:SEAL_TOKEN = "your-seal-token-here"
$env:SEAL_PROJECT = "nuget-demo-net7"
```
### 2. 运行易受攻击的应用程序 (Seal 修复前)
```
cd seal-security-nuget-demo-net7
# Restore (从 nuget.org 和 Seal feed 拉取 — 参见 nuget.config)
dotnet restore
# Build and run
dotnet build
dotnet run
```
打开 [http://localhost:5000](http://localhost:5000)——应用程序正在使用易受攻击的依赖项运行。
#### 使用正常输入进行测试
在名称字段中输入 `alice`,点击 **Go**。你应该会看到:**"Welcome, alice!"**
#### 使用漏洞利用负载进行测试
将以下 URL 粘贴到名称字段中并点击 **Go**:
```
https://raw.githubusercontent.com/seal-sec-demo-2/json-payload/main/payload.json
```
**未修补的结果:** 浏览器显示一个错误/连接重置——应用程序因 `JsonSerializerInternalReader.CreateValueInternal` 中的 `StackOverflowException` 而崩溃。进程已死亡。
### 3. 应用 Seal Security 修复
```
# (可选 — 已在上方完成) 首先 Restore dependencies
dotnet restore
# 运行 Seal CLI 以修复漏洞
seal fix . --mode remote -v
# 再次 Restore 以拉取 sealed 版本
dotnet restore
# Build 并运行修补后的 app
dotnet build
dotnet run
```
应用程序现在使用已修补的版本(`Newtonsoft.Json 12.0.2-sp1`、`log4net 2.0.5-sp1`)。
**修补后的结果:** 粘贴相同的漏洞利用 URL → 页面显示 **"Blocked by Seal patch: MaxDepth of 64 has been exceeded."**——Newtonsoft.Json 修补后的递归限制拒绝了该深度负载。服务器继续正常运行。
### 4. 验证已修补版本
```
dotnet list package
```
你应该会看到带有 `-sp1` 后缀的包,表明这些是 Seal Security 的补丁。
## Seal Security CLI 集成
### 黄金法则
CLI 步骤必须添加在**依赖项安装完毕之后**,但在**最终构建之前**。
```
# 1. Restore dependencies
dotnet restore
# 2. <--- 在此处运行 Seal CLI
$env:SEAL_TOKEN = "your-seal-token-here"
$env:SEAL_PROJECT = "nuget-demo-net7"
seal fix . --mode remote -v
# 3. 再次 Restore (以获取 sealed 版本)
dotnet restore
# 4. Build
dotnet build
```
### 修复模式
| 模式 | 描述 |
|------|-------------|
| `all` | 自动应用所有可用的修复 |
| `remote` | 仅应用在 Seal UI 中批准的修复 |
| `local` | 仅应用在 `.seal-actions.yml` 中定义的修复 |
此代码库中的 `.seal-actions.yml` 已经列出了用于 `local` 模式的三个密封覆盖项,因此 `seal fix . --mode local -v` 可以离线工作(但仍需要令牌来访问制品服务器)。
## 配置制品服务器
### nuget.config 设置
`nuget.config` 已预配置为使用环境变量的 Seal Security:
```
```
### 必需的环境变量
| 变量 | 描述 |
|----------|-------------|
| `SEAL_TOKEN` | 你的 Seal Security 访问令牌 |
| `SEAL_PROJECT` | 项目 ID(例如 `nuget-demo-net7`) |
### 网络白名单 (适用于受限环境)
Seal CLI 需要通过出站 HTTPS (TCP 443) 访问:
- `cli.sealsecurity.io` — 扫描/修复配置
- `authorization.sealsecurity.io` — 令牌验证
- `nuget.sealsecurity.io` — 密封的 `.nupkg` 下载
- `d2zko6i8myndc4.cloudfront.net` — 提供实际密封制品的 CDN(`.sealsecurity.io` 主机名重定向至此)
- `api.nuget.org` / 标准的 nuget.org 端点 — 用于未密封的依赖项
在防火墙开放后,从 PowerShell 进行验证:
```
Test-NetConnection cli.sealsecurity.io -Port 443
Test-NetConnection authorization.sealsecurity.io -Port 443
Test-NetConnection nuget.sealsecurity.io -Port 443
Test-NetConnection d2zko6i8myndc4.cloudfront.net -Port 443
```
所有项都应报告 `TcpTestSucceeded: True`。
## .NET 7 特别说明
| 项目 | 为什么重要 |
|------|----------------|
| `global.json` 使用 `rollForward: latestFeature` 将 SDK 固定到 `7.0.x` | 防止安装了 net8/net9 并列的计算机在演示中途静默切换 SDK。 |
| `System.Configuration.ConfigurationManager` 固定到 **7.0.0** | 规范的 net9 演示使用的是 8.0.0,它仅针对 net8,并且在 net7 上无法还原。7.0.0 具有与 log4net 需求相同的 API 接口。 |
| csproj 中抑制了 `NU1701` | `log4net 2.0.5` 声明了一个 .NET 7 在运行时可以接受但在还原时会发出警告的旧版 `net4x` TFM。该警告只是表面现象;对其进行抑制可让演示过程中的构建输出保持干净。 |
| 适用于 Windows x64 的 Seal CLI **v0.3.238** | 提供了 Windows 二进制文件的最后一个版本;完全支持 NuGet 修复。在此版本之后,Windows 二进制文件已停止发布,因此请勿建议使用更新的版本。 |
## 演示谈话要点
* **无需代码更改**——应用程序代码与未修补版本完全相同。仅交换了 NuGet 包版本。
* **相同的 API**——`12.0.2-sp1` 是 `12.0.2` 的二进制兼容直接替代品。
* **针对客户的实际技术栈**——net7.0,而不是 net9.0。无需进行 SDK 升级。
* **深度防御**——保护所有代码路径,包括传递依赖。
* **公开补丁**——所有补丁均是开源且可审计的。
* **已停止支持的 .NET 仍可获得补丁**——这是核心价值所在:Microsoft 不再为 .NET 7 提供安全更新,但 Seal 仍能保持客户现有依赖项接口的安全。
## 可用的密封 NuGet 包
**此演示**使用的包:
| 包 | 易受攻击的版本 | 密封版本 | CVE | CVSS |
|---------|-------------------|----------------|-----|------|
| Newtonsoft.Json | 12.0.2 | 12.0.2-sp1 | CVE-2024-21907 | 7.5 HIGH |
| log4net | 2.0.5 | 2.0.5-sp1 | CVE-2018-1285 | 9.8 CRITICAL |
可从 Seal 源获取的其他密封 NuGet 包(不在本演示中,列出以供参考):
| 包 | 易受攻击的版本 | 密封版本 | CVE | CVSS |
|---------|-------------------|----------------|-----|------|
| log4net | 2.0.0 | 2.0.0-sp1 | CVE-2018-1285 | 9.8 CRITICAL |
| System.Net.Http | 4.3.0 | 4.3.0-sp1 | CVE-2017-0249 | 7.3 HIGH |
| Snappier | 1.1.0 | 1.1.0-sp1 | CVE-2023-28638 | 7.0 HIGH |
| jQuery.Validation | 1.17.0 | 1.17.0-sp1 | CVE-2021-21252 | 7.5 HIGH |
## 许可证
MIT License - 详见 LICENSE 文件。
标签:ASP.NET Core, CVE-2024-21907, CVSS 7.5, DoS, JSON反序列化, .NET 7, Newtonsoft.Json, NuGet, Seal Security, 企业安全, 依赖管理, 兼容性, 安全漏洞, 安全补丁, 拒绝服务, 漏洞修复, 漏洞缓解, 演示项目, 网络安全培训, 网络资产管理