mganss/HtmlSanitizer

GitHub: mganss/HtmlSanitizer

一个 .NET HTML 清洗库,通过白名单机制过滤危险标签、属性与样式来防御 XSS 攻击。

Stars: 1702 | Forks: 226

# HtmlSanitizer [![NuGet version](https://badge.fury.io/nu/HtmlSanitizer.svg)](https://badge.fury.io/nu/HtmlSanitizer) [![Build status](https://ci.appveyor.com/api/projects/status/418bmfx643iae00c/branch/master?svg=true)](https://ci.appveyor.com/project/mganss/htmlsanitizer/branch/master) [![codecov.io](https://codecov.io/github/mganss/HtmlSanitizer/coverage.svg?branch=master)](https://codecov.io/github/mganss/HtmlSanitizer?branch=master) [![Sonarcloud Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=mganss_HtmlSanitizer&metric=alert_status)](https://sonarcloud.io/dashboard?id=mganss_HtmlSanitizer) [![netstandard2.0](https://img.shields.io/badge/netstandard-2.0-brightgreen.svg)](https://img.shields.io/badge/netstandard-2.0-brightgreen.svg) [![net46](https://img.shields.io/badge/net-462-brightgreen.svg)](https://img.shields.io/badge/net-462-brightgreen.svg) [![net8.0](https://img.shields.io/badge/net-8.0-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
"; 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
    ` - `

    test

    ` ## 许可证 [MIT 许可证](https://en.wikipedia.org/wiki/MIT_License)
    标签:HTML处理, Syscall, Web开发, XSS防护, 代码安全, 多人体追踪, 数据清洗, 漏洞枚举