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, 企业安全, 依赖管理, 兼容性, 安全漏洞, 安全补丁, 拒绝服务, 漏洞修复, 漏洞缓解, 演示项目, 网络安全培训, 网络资产管理