按框架
ASP.NET Core 安全 — 生产环境加固实务参考
ASP.NET Core 生产环境加固参考:优先级清单,外加生产环境错误、密钥(User Secrets/Key Vault)、NuGet CVE、授权、over-posting、反序列化与 SSRF。以防御为主,不含攻击步骤。
面向:在 ASP.NET Core 上运营应用或 API 的人。这里不讲攻击步骤——这是一份用于加固的实务参考:优先级排序的清单、分领域指引、以及自查。要看跨框架的全局,请参阅 按框架的安全防护入口。
优先级排序的加固清单
按此表自上而下执行。P0 是前提,P1 是最频繁的事故来源,P2 是持续的运营卫生。
P0 ── 前提(先做这个)
生产环境不显示详细错误 / 把密钥外置 / 快速为 NuGet 依赖 CVE 打补丁
P1 ── 最主要的事故来源
授权([Authorize]、默认拒绝、所有者)/ over-posting 防御(DTO/[Bind])
P2 ── 运营卫生
不安全的反序列化 / HTTPS、响应头、antiforgery / SSRF
| 优先级 | 控制项 | 具体做法(ASP.NET Core) |
|---|---|---|
| P0 | 生产环境错误 | UseExceptionHandler。生产环境不显示 Developer Exception Page/详情(正确的环境判断) |
| P0 | 密钥外置 | 不要硬编码在 appsettings.json。开发 = User Secrets,生产 = 环境变量/Key Vault |
| P0 | NuGet 依赖 CVE | 用 dotnet list package --vulnerable/osv-scanner 监控;以运行中的版本判定,快速打补丁 |
| P1 | 显式授权 | [Authorize] + 默认拒绝(回退策略)+ 基于资源/所有者的检查 |
| P1 | over-posting 防御 | 绑定到 DTO,而非直接绑定实体。用 [Bind] 限制接受的字段 |
| P2 | 反序列化 | 不要用 BinaryFormatter。不要用不安全的格式还原不受信任的数据 |
| P2 | HTTPS/响应头/CSRF | UseHttpsRedirection、UseHsts、antiforgery(CSRF)、Cookie 属性 |
| P2 | SSRF | 服务端取回用允许列表 + 阻断内部 IP/元数据 |
1. 生产环境错误暴露(P0)
- 在生产环境,通过
UseExceptionHandler切换到通用的错误页,并不显示 Developer Exception Page/详情(把环境判断做对,例如ASPNETCORE_ENVIRONMENT=Production)。 - 不要把堆栈跟踪或内部结构泄露到外部。
2. 把密钥外置(P0)
- 不要把连接字符串或密钥硬编码在 appsettings.json 里。开发环境用 User Secrets,生产环境用环境变量或云端密钥管理器(Key Vault)。
- appsettings.json 容易经由误提交或暴露而泄露。不要把它提交到仓库,也不要放进公开目录(→ 不要把密钥放进公开目录)。泄露时及时轮换。
3. NuGet 依赖 CVE(P0)
- 用
dotnet list package --vulnerable或 osv-scanner 机器监控已知 CVE,以运行中的版本判定,并快速打补丁(→ 监控依赖包的 CVE · 漏洞应对实务)。 - 让 .NET 保持在受支持的版本,不要放着 EOL 版本不管。
4. 授权(P1 — 最主要的来源)
常见(危险)
- 在端点上忘了加
[Authorize] - 已认证,但没有所有者检查
- 默认倾向“允许”,未认证也能通过
- 没有角色/策略设计,检查零零散散
正确
[Authorize]+ 通过回退策略实现默认拒绝- 基于角色/策略 + 基于资源的授权以确认所有权
- 在每一条读取/更新/删除路径上核验
- 授权显式构建,不交给默认值
参阅 IDOR 是什么。认证和授权是两回事;在靠近数据的地方做授权。
5. over-posting(P1)
- **不要直接绑定实体。**绑定到一个仅供输入的 DTO,只接受你需要的字段。
- 或者用
[Bind]显式限制接受的字段。不要让某个权限标志被外部输入覆写。
6. 不安全的反序列化与输入(P2)
- 不要用
BinaryFormatter(过时/不安全)。不要用不安全的格式还原不受信任的数据(在特定条件下可能导致 RCE)(→ RCE 是什么)。 - 在使用前,用**模型校验(data annotations 等)**校验输入的类型/范围/允许值。
7. HTTPS、响应头、antiforgery(P2)
- 用
UseHttpsRedirection+UseHsts强制 HTTPS,并把 Cookie 标记为 secure/httponly/samesite。 - 在表单/会更改状态的请求上使用 antiforgery 令牌(CSRF 防御)(→ CSRF 是什么)。
- 加上安全响应头(用 安全响应头检查器 检查你自己的站点)。
8. SSRF 与服务端取回(P2)
- 服务端(
HttpClient等)取回用户提供的 URL 时,应把目标限制在允许列表,并阻断到内部 IP/元数据的访问(→ SSRF 是什么)。校验上传,并把它们存放在公开面之外。
验证:你的 ASP.NET Core 真的加固了吗
做完不算完——检查过才算完成。以下是针对你自己环境的防御性自查。
生产环境没有 Developer Exception Page
密钥不在配置/仓库里
appsettings.json 里,且仓库里没有任何密钥。授权是否有效
依赖与 HTTPS/响应头
dotnet list package --vulnerable/osv 干净,并通过响应头检查器确认 HTTPS/HSTS 存在。本站的视角:即便地基稳固,配置和授权仍归你自己
ASP.NET Core 在认证、授权和 Data Protection 方面机制稳固,但生产环境配置和把授权落地,是你必须按环境、按端点逐一做对的东西。本站是另一套技术栈,但原则是一样的:生产环境不泄露内部信息、把密钥放在配置之外、在所有对外入口都写好授权、并监控依赖的 CVE。稳固的地基,只有配上正确的配置和显式的授权才能兑现价值。
接下来读
- 入口:按框架的安全防护 · Spring Boot 安全(同为企业级,依赖/授权形态相似)
- 实操:漏洞应对实务 · 监控依赖包的 CVE · 不要把密钥放进公开目录
- 术语:IDOR 是什么 · RCE 是什么 · CSRF · SSRF
- 工具:安全响应头检查器
FAQ
Q要保护 ASP.NET Core,第一步该做什么?
P0 的三件事:(1) 生产环境不显示 Developer Exception Page / 详细错误(UseExceptionHandler,正确的环境判断);(2) 把密钥外置,而非硬编码在 appsettings.json 里(开发用 User Secrets,生产用环境变量或 Key Vault);(3) 用机器监控 NuGet 依赖 CVE 并快速打补丁,以运行中的版本判定。接着再进入授权([Authorize]、默认拒绝)与 over-posting 防御。
Q密钥(连接字符串、API 密钥)应该放在哪里?
规则是:不要硬编码在 appsettings.json 里。开发环境用 User Secrets;生产环境从环境变量或云端密钥管理器(Key Vault)加载。appsettings.json 往往最终会进入仓库,并容易经由公开目录或误提交而泄露。一旦泄露,请及时轮换连接字符串或密钥。
Q如何防止忘记加授权特性?
在控制器或端点上忘了加 [Authorize],任何人都能未经认证就访问它。把默认倾向设为拒绝(用回退策略拒绝未认证的请求),用基于角色/策略的授权把权限写明确,并编写资源所有者检查(基于资源的授权)。不要止步于“已登录=允许”——还要验证目标对象的所有者。
Q什么是 over-posting?
如果模型绑定把每个字段都接收进实体,用户发送的意料之外的字段(比如某个权限标志)就可能被覆写——这就是 over-posting。修复办法是绑定到一个仅供输入的 DTO,或用 [Bind] 显式限制接受的字段。不要直接绑定实体。
Q为什么不安全的反序列化很危险?
用像 BinaryFormatter 这样不安全的反序列化器还原不受信任的数据,在特定条件下可能导致远程代码执行(RCE)。BinaryFormatter 已被视为过时/不安全——不要使用它。要核实外部来源数据的出处,必要时限制为一种安全的格式(例如配置得当的 JSON)。