ASP.NET Core 默认 HTML 编码仅对 Razor 输出有效,无法覆盖 @Html.Raw()、JS 内联脚本、URL 属性、JSON 嵌入等场景;需结合 @Json.Serialize()、HtmlSanitizer 和 CSP 多层防护。

ASP.NET Core 默认的 HTML 编码是否足够防 XSS?
默认情况下,Razor 视图引擎会对 @Model.Property 这类表达式自动进行 HTML 编码(即转义 、&、"、'),这能拦截大部分反射型和存储型 XSS。但这个保护仅限于 Razor 输出上下文,且不覆盖所有场景。
容易踩的坑包括:
- 使用
@Html.Raw()或IHtmlContent手动绕过编码,一旦拼接了用户输入就直接触发 XSS - JavaScript 中通过
innerHTML、document.write()插入未净化的内容 - URL 参数或属性值中未做上下文感知编码(比如写进
href="javascript:..."或onerror="") - JSON 数据嵌入 HTML 时未用
@Json.Serialize()而是直接@Newtonsoft.Json.JsonConvert.SerializeObject()后@Html.Raw()
如何安全地向 JavaScript 传递用户数据?
不要把用户输入拼进内联脚本字符串里,例如 @($"var name = '{Model.Name}';") —— 单引号、反斜杠、 都可能逃逸。
正确做法是:
- 用
@Json.Serialize(Model.Name)(来自Microsoft.AspNetCore.Mvc.ViewFeatures),它会生成带引号、转义双引号和控制字符的安全 JSON 字符串 - 在 JS 中统一用
JSON.parse()解析,避免 eval 或字符串拼接 - 如果必须动态生成 script 标签,优先走 API 接口获取数据,而不是服务端渲染到页面
示例:
<script> const userData = @Json.Serialize(Model.UserData); </script>—— 此时
Model.UserData 是任意字符串,@Json.Serialize() 保证输出合法 JSON。
需要手动过滤输入时,别用正则“删标签”,改用 HtmlSanitizer
对富文本(如用户提交的带格式评论)不能简单用 Regex.Replace(input, @"]*>", ""),这种规则极易被绕过(注释、CDATA、畸形标签、UTF-7 编码等)。
推荐用成熟库 HtmlSanitizer(由 vschmidt/HtmlSanitizer 维护):
- 只允许白名单标签(如
p、strong、a)和属性(如href,且自动校验协议为https?) - 自动清理
on*事件、javascript:、vbscript:等危险内容 - 支持配置 CSS 白名单,防止
expression()或url(javascript:...)
安装后简单用法:
var sanitizer = new HtmlSanitizer();
sanitizer.AllowedTags.Add("p");
sanitizer.AllowedAttributes.Add("href");
string clean = sanitizer.Sanitize(userHtml);
Content-Security-Policy 是最后一道防线,但不能替代服务端防护
CSP 能大幅降低 XSS 成功后的危害(比如禁止内联脚本、限制 eval、限定资源加载域),但它不阻止恶意 payload 进入页面,也不解决 DOM XSS 的根本成因。
在 ASP.NET Core 中启用方式:
- 通过中间件添加响应头:
app.Use(async (ctx, next) => { ctx.Response.Headers.Append("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline'"); await next(); });(注意:生产环境慎用'unsafe-inline') - 更推荐用
NetEscapades.AspNetCore.SecurityHeaders库,它提供强类型配置和自动 nonce 支持 - 关键点:CSP 的
script-src若含'unsafe-inline',仍可能被onclick类属性型 XSS 利用;必须配合服务端彻底清除不可信内容
最易被忽略的是:CSP 不影响服务端模板渲染逻辑,只要 Razor 输出了恶意 onclick,浏览器照样执行——所以 CSP 是补充,不是替代。









