mganss/HtmlSanitizer
GitHub: mganss/HtmlSanitizer
一个 .NET HTML 清洗库,通过白名单机制过滤危险标签、属性与样式来防御 XSS 攻击。
Stars: 1702 | Forks: 226
# HtmlSanitizer
[](https://badge.fury.io/nu/HtmlSanitizer)
[](https://ci.appveyor.com/project/mganss/htmlsanitizer/branch/master)
[](https://codecov.io/github/mganss/HtmlSanitizer?branch=master)
[](https://sonarcloud.io/dashboard?id=mganss_HtmlSanitizer)
[](https://img.shields.io/badge/netstandard-2.0-brightgreen.svg)
[](https://img.shields.io/badge/net-462-brightgreen.svg)
[](https://img.shields.io/badge/net-461-brightgreen.svg)
HtmlSanitizer 是一个 .NET 库,用于清除 HTML 片段和文档中可能导致 [XSS 攻击](https://en.wikipedia.org/wiki/Cross-site_scripting)的构造。
它使用 [AngleSharp](https://github.com/AngleSharp/AngleSharp) 来解析、操作和渲染 HTML 与 CSS。
由于 HtmlSanitizer 基于健壮的 HTML 解析器,它还可以保护您免受故意或意外的
“标签污染(tag poisoning)”,即某个片段中的无效 HTML 可能会破坏整个文档,导致布局或样式错乱。
为了满足不同的使用场景,HtmlSanitizer 可以在多个层面上进行自定义配置:
- 通过 `AllowedTags` 属性配置允许的 HTML 标签。所有其他标签将被移除。
- 通过 `AllowedAttributes` 属性配置允许的 HTML 属性。所有其他属性将被移除。
- 通过 `AllowedCssProperties` 属性配置允许的 CSS 属性名称。所有其他样式将被移除。
- 通过 `AllowedAtRules` 属性配置允许的 CSS [at-rules](https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule)。所有其他 at-rules 将被移除。
- 通过 `AllowedSchemes` 属性配置允许的 URI scheme。所有其他 URI 将被移除。
- 通过 `UriAttributes` 属性配置包含 URI 的 HTML 属性(例如 "src"、"href" 等)。
- 提供一个基础 URI,用于解析相对 URI。
- 在移除标签、属性或样式之前,会引发可取消的事件。
## 用法
安装 [HtmlSanitizer NuGet 包](https://www.nuget.org/packages/HtmlSanitizer/)。然后:
```
using Ganss.Xss;
var sanitizer = new HtmlSanitizer();
var html = @"test `
- `
Test![]()
";
var sanitized = sanitizer.Sanitize(html, "https://www.example.com");
var expected = @""
+ @"Test![]()
";
Assert.Equal(expected, sanitized);
```
这里有一个[在线演示](https://xss.ganss.org/),另外还有一个供您试用的 [.NET Fiddle](https://dotnetfiddle.net/892nOk)。
更多示例代码和可用选项的描述可以在 [Wiki](https://github.com/mganss/HtmlSanitizer/wiki) 中找到。
### 默认允许的标签
`a`,
`abbr`,
`acronym`,
`address`,
`area`,
`article`,
`aside`,
`b`,
`bdi`,
`big`,
`blockquote`,
`body`,
`br`,
`button`,
`caption`,
`center`,
`cite`,
`code`,
`col`,
`colgroup`,
`data`,
`datalist`,
`dd`,
`del`,
`details`,
`dfn`,
`dir`,
`div`,
`dl`,
`dt`,
`em`,
`fieldset`,
`figcaption`,
`figure`,
`font`,
`footer`,
`form`,
`h1`,
`h2`,
`h3`,
`h4`,
`h5`,
`h6`,
`head`,
`header`,
`hr`,
`html`,
`i`,
`img`,
`input`,
`ins`,
`kbd`,
`keygen`,
`label`,
`legend`,
`li`,
`main`,
`map`,
`mark`,
`menu`,
`menuitem`,
`meter`,
`nav`,
`ol`,
`optgroup`,
`option`,
`output`,
`p`,
`pre`,
`progress`,
`q`,
`rp`,
`rt`,
`ruby`,
`s`,
`samp`,
`section`,
`select`,
`small`,
`span`,
`strike`,
`strong`,
`sub`,
`summary`,
`sup`,
`table`,
`tbody`,
`td`,
`textarea`,
`tfoot`,
`th`,
`thead`,
`time`,
`tr`,
`tt`,
`u`,
`ul`,
`var`,
`wbr`
### 默认允许的属性
`abbr`,
`accept-charset`,
`accept`,
`accesskey`,
`action`,
`align`,
`alt`,
`autocomplete`,
`autosave`,
`axis`,
`bgcolor`,
`border`,
`cellpadding`,
`cellspacing`,
`challenge`,
`char`,
`charoff`,
`charset`,
`checked`,
`cite`,
`clear`,
`color`,
`cols`,
`colspan`,
`compact`,
`contenteditable`,
`coords`,
`datetime`,
`dir`,
`disabled`,
`draggable`,
`dropzone`,
`enctype`,
`for`,
`frame`,
`headers`,
`height`,
`high`,
`href`,
`hreflang`,
`hspace`,
`ismap`,
`keytype`,
`label`,
`lang`,
`list`,
`longdesc`,
`low`,
`max`,
`maxlength`,
`media`,
`method`,
`min`,
`multiple`,
`name`,
`nohref`,
`noshade`,
`novalidate`,
`nowrap`,
`open`,
`optimum`,
`pattern`,
`placeholder`,
`prompt`,
`pubdate`,
`radiogroup`,
`readonly`,
`rel`,
`required`,
`rev`,
`reversed`,
`rows`,
`rowspan`,
`rules`,
`scope`,
`selected`,
`shape`,
`size`,
`span`,
`spellcheck`,
`src`,
`start`,
`step`,
`style`,
`summary`,
`tabindex`,
`target`,
`title`,
`type`,
`usemap`,
`valign`,
`value`,
`vspace`,
`width`,
`wrap`
_注意:_ 为了防止 [classjacking](https://html5sec.org/#123) 以及与待集成清理片段的类发生冲突,默认情况下不允许使用 `class` 属性。
可以按如下方式添加它:
```
var sanitizer = new HtmlSanitizer();
sanitizer.AllowedAttributes.Add("class");
var sanitized = sanitizer.Sanitize(html);
```
### 默认允许的 CSS 属性
`align-content`,
`align-items`,
`align-self`,
`all`,
`animation`,
`animation-delay`,
`animation-direction`,
`animation-duration`,
`animation-fill-mode`,
`animation-iteration-count`,
`animation-name`,
`animation-play-state`,
`animation-timing-function`,
`backface-visibility`,
`background`,
`background-attachment`,
`background-blend-mode`,
`background-clip`,
`background-color`,
`background-image`,
`background-origin`,
`background-position`,
`background-position-x`,
`background-position-y`,
`background-repeat`,
`background-repeat-x`,
`background-repeat-y`,
`background-size`,
`border`,
`border-bottom`,
`border-bottom-color`,
`border-bottom-left-radius`,
`border-bottom-right-radius`,
`border-bottom-style`,
`border-bottom-width`,
`border-collapse`,
`border-color`,
`border-image`,
`border-image-outset`,
`border-image-repeat`,
`border-image-slice`,
`border-image-source`,
`border-image-width`,
`border-left`,
`border-left-color`,
`border-left-style`,
`border-left-width`,
`border-radius`,
`border-right`,
`border-right-color`,
`border-right-style`,
`border-right-width`,
`border-spacing`,
`border-style`,
`border-top`,
`border-top-color`,
`border-top-left-radius`,
`border-top-right-radius`,
`border-top-style`,
`border-top-width`,
`border-width`,
`bottom`,
`box-decoration-break`,
`box-shadow`,
`box-sizing`,
`break-after`,
`break-before`,
`break-inside`,
`caption-side`,
`caret-color`,
`clear`,
`clip`,
`color`,
`column-count`,
`column-fill`,
`column-gap`,
`column-rule`,
`column-rule-color`,
`column-rule-style`,
`column-rule-width`,
`column-span`,
`column-width`,
`columns`,
`content`,
`counter-increment`,
`counter-reset`,
`cursor`,
`direction`,
`display`,
`empty-cells`,
`filter`,
`flex`,
`flex-basis`,
`flex-direction`,
`flex-flow`,
`flex-grow`,
`flex-shrink`,
`flex-wrap`,
`float`,
`font`,
`font-family`,
`font-feature-settings`,
`font-kerning`,
`font-language-override`,
`font-size`,
`font-size-adjust`,
`font-stretch`,
`font-style`,
`font-synthesis`,
`font-variant`,
`font-variant-alternates`,
`font-variant-caps`,
`font-variant-east-asian`,
`font-variant-ligatures`,
`font-variant-numeric`,
`font-variant-position`,
`font-weight`,
`gap`,
`grid`,
`grid-area`,
`grid-auto-columns`,
`grid-auto-flow`,
`grid-auto-rows`,
`grid-column`,
`grid-column-end`,
`grid-column-gap`,
`grid-column-start`,
`grid-gap`,
`grid-row`,
`grid-row-end`,
`grid-row-gap`,
`grid-row-start`,
`grid-template`,
`grid-template-areas`,
`grid-template-columns`,
`grid-template-rows`,
`hanging-punctuation`,
`height`,
`hyphens`,
`image-rendering`,
`isolation`,
`justify-content`,
`left`,
`letter-spacing`,
`line-break`,
`line-height`,
`list-style`,
`list-style-image`,
`list-style-position`,
`list-style-type`,
`margin`,
`margin-bottom`,
`margin-left`,
`margin-right`,
`margin-top`,
`mask`,
`mask-clip`,
`mask-composite`,
`mask-image`,
`mask-mode`,
`mask-origin`,
`mask-position`,
`mask-repeat`,
`mask-size`,
`mask-type`,
`max-height`,
`max-width`,
`min-height`,
`min-width`,
`mix-blend-mode`,
`object-fit`,
`object-position`,
`opacity`,
`order`,
`orphans`,
`outline`,
`outline-color`,
`outline-offset`,
`outline-style`,
`outline-width`,
`overflow`,
`overflow-wrap`,
`overflow-x`,
`overflow-y`,
`padding`,
`padding-bottom`,
`padding-left`,
`padding-right`,
`padding-top`,
`page-break-after`,
`page-break-before`,
`page-break-inside`,
`perspective`,
`perspective-origin`,
`pointer-events`,
`position`,
`quotes`,
`resize`,
`right`,
`row-gap`,
`scroll-behavior`,
`tab-size`,
`table-layout`,
`text-align`,
`text-align-last`,
`text-combine-upright`,
`text-decoration`,
`text-decoration-color`,
`text-decoration-line`,
`text-decoration-skip`,
`text-decoration-style`,
`text-indent`,
`text-justify`,
`text-orientation`,
`text-overflow`,
`text-shadow`,
`text-transform`,
`text-underline-position`,
`top`,
`transform`,
`transform-origin`,
`transform-style`,
`transition`,
`transition-delay`,
`transition-duration`,
`transition-property`,
`transition-timing-function`,
`unicode-bidi`,
`user-select`,
`vertical-align`,
`visibility`,
`white-space`,
`widows`,
`width`,
`word-break`,
`word-spacing`,
`word-wrap`,
`writing-mode`,
`z-index`
### 默认允许的 CSS at-rules
`namespace`, `style`
`style` 指的是其他 at-rules(如 `@media`)内的样式声明。在允许其他类型的 at-rules 时不允许 `@namespace` 可能会导致错误。
`@font-face` 和 `@viewport` 中的属性声明不会被清理。
_注意:_ 默认情况下不允许使用 `style` 标签。
### 默认允许的 URI scheme
`http`, `https_注意:_ 默认情况下允许[协议相对 URL](https://en.wikipedia.org/wiki/Wikipedia:Protocol-relative_URL)(例如 //github.com)(其他相对 URL 也是如此)。
要允许 `mailto:` 链接:
```
sanitizer.AllowedSchemes.Add("mailto");
```
### 默认包含 URI 的属性
`action`, `formaction`, `background`, `dynsrc`, `href`, `lowsrc`, `src`
### 线程安全
`Sanitize()` 和 `SanitizeDocument()` 方法是线程安全的,即您可以在不同线程中使用单个共享实例调用这些方法,前提是您没有同时设置实例或静态属性。典型的使用场景是,您首先从单个线程准备一个 `HtmlSanitizer` 实例(即设置所需的属性,如 `AllowedTags` 等),然后从多个线程调用 `Sanitize()`/`SanitizeDocument()`。
### 文本内容不一定会原样保留
请注意,由于输入是由 AngleSharp 的 HTML 解析器解析然后再渲染输出的,因此即使没有移除任何元素或属性,您也不能期望文本内容会与输入完全一致地保留。示例:
- `4 < 5` 变为 `4 < 5`
- `test` 变为 `test`
- `test` 变为 `test`
另一方面,尽管解析器修复了一些损坏的 HTML,但输出结果可能仍然包含无效的 HTML。示例:
- `- test
test
` ## 许可证 [MIT 许可证](https://en.wikipedia.org/wiki/MIT_License)标签:HTML处理, Syscall, Web开发, XSS防护, 代码安全, 多人体追踪, 数据清洗, 漏洞枚举