如何删除危险字符(即脚本标签)?

Posted

技术标签:

【中文标题】如何删除危险字符(即脚本标签)?【英文标题】:How to remove dangerous characters(ie script tags)? 【发布时间】:2011-02-27 01:40:02 【问题描述】:

我想知道是否有任何类型的 C# 类或 3rd 方库可以删除脚本标签等危险字符?

我知道你可以使用正则表达式,但我也知道人们可以用多种方式编写他们的脚本标签,以至于你可以欺骗正则表达式认为它是可以的。

我还听说html Agility Pack 很好,所以我想知道是否有任何脚本删除类针对它?

编辑

http://htmlagilitypack.codeplex.com/Thread/View.aspx?ThreadId=24346

我在他们的表格上找到了这个。但是我不确定这是否是完整的解决方案,因为这家伙没有任何测试来备份它,如果这是在某个网站上,每天都有很多人使用这个脚本来测试是否有任何东西会更好由。

很好的例子(几乎),谢谢!一些 让我看到的更强大的方法, 不过:

1) 在以下情况下使用不区分大小写的搜索 寻找带有“javascript:”的链接, “vbscript:”,“jscript:”。例如, 原始示例不会删除 HTML:

<a href="JAVAscRipt:alert('hi')">click> me</a>

2) 删除任何样式属性 包含表达式规则。互联网 Explorer 评估 CSS 规则 表达为脚本。例如, 以下将产生一个消息框:

<div style="width:expression(alert('hi'));">bad> code</div>

3) 同时删除标签

我真的不知道为什么 “表达式”尚未从 IE - 我认为的主要缺陷。 (尝试 Internet Explorer 中的 div 示例 你会明白为什么 - 甚至是 IE8。)我 只希望有一个更简单/标准 清理来自 a 的 html 输入的方法 用户。

以下是使用这些改进更新的代码。如果您发现任何错误,请告诉我:

    public string ScrubHTML(string html)
    
        HtmlDocument doc = new HtmlDocument();
        doc.LoadHtml(html);

        //Remove potentially harmful elements
        HtmlNodeCollection nc = doc.DocumentNode.SelectNodes("//script|//link|//iframe|//frameset|//frame|//applet|//object|//embed");
        if (nc != null)
        
            foreach (HtmlNode node in nc)
            
                node.ParentNode.RemoveChild(node, false);

            
        

        //remove hrefs to java/j/vbscript URLs
        nc = doc.DocumentNode.SelectNodes("//a[starts-with(translate(@href, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'javascript')]|//a[starts-with(translate(@href, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'jscript')]|//a[starts-with(translate(@href, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'vbscript')]");
        if (nc != null)
        

            foreach (HtmlNode node in nc)
            
                node.SetAttributeValue("href", "#");
            
        


        //remove img with refs to java/j/vbscript URLs
        nc = doc.DocumentNode.SelectNodes("//img[starts-with(translate(@src, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'javascript')]|//img[starts-with(translate(@src, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'jscript')]|//img[starts-with(translate(@src, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'vbscript')]");
        if (nc != null)
        
            foreach (HtmlNode node in nc)
            
                node.SetAttributeValue("src", "#");
            
        

        //remove on<Event> handlers from all tags
        nc = doc.DocumentNode.SelectNodes("//*[@onclick or @onmouseover or @onfocus or @onblur or @onmouseout or @ondoubleclick or @onload or @onunload]");
        if (nc != null)
        
            foreach (HtmlNode node in nc)
            
                node.Attributes.Remove("onFocus");
                node.Attributes.Remove("onBlur");
                node.Attributes.Remove("onClick");
                node.Attributes.Remove("onMouseOver");
                node.Attributes.Remove("onMouseOut");
                node.Attributes.Remove("onDoubleClick");
                node.Attributes.Remove("onLoad");
                node.Attributes.Remove("onUnload");
            
        

        // remove any style attributes that contain the word expression (IE evaluates this as script)
        nc = doc.DocumentNode.SelectNodes("//*[contains(translate(@style, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'expression')]");
        if (nc != null)
        
            foreach (HtmlNode node in nc)
            
                node.Attributes.Remove("stYle");
            
        

        return doc.DocumentNode.WriteTo();
     

【问题讨论】:

可以使用这里提到的HTML转义功能:***.com/questions/1005264/escape-text-for-html 你到底想做什么?您只是想清理用户输入,还是在抓取网页? 清理危险标签,但不处理 html 标签,如粗体和其他丰富的 html 标签。 【参考方案1】:

string value = "Here alert('hello') 我们走了。访问" + "http://west-wind.com'>西风网站。" + "http://west-wind.com/images/new.gif' /> "; string safestring = Microsoft.Security.Application.Sanitizer.GetSafeHtmlFragment(value);

以上代码将从字符串中删除脚本标签

【讨论】:

【参考方案2】:

Encoder.HtmlEncode 怎么样? VS 2010 在尝试使用 AntiXss.HtmlEncode 时建议使用它

【讨论】:

【参考方案3】:

我们遇到了同样的问题:用户输入 HTML,我们想在 XHTML 页面中显示它。请注意,它们输入的是 HTML 片段而不是完整的文档。我在 2010 年对此进行了研究,使用单元测试来测试许多不同的案例。

解决方案:

    使用 Microsoft 反跨站点脚本库删除所有内容 被认为是不安全的(主要是脚本)。请注意,此工具不会关闭这些标签:img、hr、br,有时它会以错误的顺序关闭标签。 使用 Tidy.Net 创建几乎有效的 XHTML。 删除 Tidy.Net 倾向于创建的 html、head 和 body 标签。 删除 Tidy.Net 在“pre”标签中创建的额外换行符。

这将删除所有 JS 并创建在大多数情况下有效的 XHTML 片段。它还将删除所有样式标签。

我试过的工具有这些问题:

Microsoft 反跨站点脚本库: 不会关闭这些标签:img、hr、br,有时它会以错误的顺序关闭标签。遗憾的是无法自定义。

Tidy.Net: 在 pre 标记内创建额外的换行符。 (可以在运行工具后手动修复。)

TidyForNet: 不稳定。有时会给你“blabla.c 中的断言失败”

用 VB6 制作的 Tidy (C-DLL) COM 包装器: 至少可以说是不切实际的。您必须注册 COM DLL。

HtmlAgilityPack:偶尔插入额外的换行符。从 pre 标记中删除换行符。

Majestic12 HTML-parser:不会关闭这些标签:img、hr、br,有时它会以错误的顺序关闭标签。

AntiSamy.Net:不切实际,因为它使用了用过时的 J# 编写的组件。因此,它不能在 64 位环境中运行。从好的方面来说,它是非常可定制的关于允许哪些标签和属性值。

【讨论】:

【参考方案4】:

我会使用内置方法。正如我所看到的,如果用户想要破坏你的程序,他们会找到一种方法来做到这一点。但是,如果您结合使用多种清理用户输入的方法,您的程序只会更加安全。

例如,对于名为“myString”的字符串变量,为了安全起见,我会将 REGEX 字符剥离与常规手动字符剥离结合起来。

这将删除所有非字母数字。

myString = Regex.Replace(myString, "[^a-z0-9]", "", RegexOptions.CaseInsensitive);
myString = myString.replace("/","");
myString = myString.replace("<","");

等等

您还可以通过删除“”字符之间以及“>”和“

我不喜欢使用外部第三方库 - 除非我必须 - 因为您还必须分发库,您依赖其他人的程序来确保自己的安全,并且如果他们的软件存在漏洞你的也很脆弱。

【讨论】:

另一方面,如果我使用第三方库,我通常可以获得他们解决方案的所有健壮性和能力,而无需花费大量时间编写不完整的解决方案,因为我对问题的细微差别。选择合适的第三方库是另一个问题。 有效点。关于第 3 方包的另一个问题是该包是否需要任何外部库等。由于未指定部署环境,因此您无法真正假设什么是最好的。但是如果我在一个拥有数百台机器的 IT 部门,如果我必须在所有这些机器上安装一个 3rd 方库以及其他组件才能运行该库,我可能会有点抓狂。 Soo.....浪费时间开发自己的解决方案与浪费时间部署别人的大声笑 我宁愿使用在该领域有更多知识的人制作的东西。似乎只需更改一个空格就可以使脚本标签通过。我认为编写脚本标签有很多创造性的方法,我没有时间去弄清楚它们都是什么,然后在所有情况下测试它是否会通过。如果成功了,为什么要重新发明***?另外,如果他们有漏洞,那么它就在您的身上。那么你最好不要使用任何东西,即使是来自 C# 的内置安全性东西,比如加密。它可能是有缺陷的,但如果是它,它会比你的发现更快找到 您的脚本可能拥有的威望。 这是一个有效的点。但是,如果有人想破坏您的应用程序,他们会找到方法。这不是是否的问题,而是何时的问题。对于我的应用程序,我设置了足够的安全性来阻止临时用户和程序员破坏它。但是,如果有人要反编译、解混淆并弄清楚我是如何实现上述安全性以破坏我的应用程序的——这对我来说很好,原因有两个……1,他们是比我更好的程序员,2,我做了一些值得让他们集中注意力的东西。 :)

以上是关于如何删除危险字符(即脚本标签)?的主要内容,如果未能解决你的问题,请参考以下文章

如何从字符串中删除 \n 和 \r

那些危险的docker删除命令

Php - 如何在 QueryPath 中删除/删除带有特定字符串的标签?

如何从字符串中删除跨度标签?

Linux rm危险命令误删除文件如何恢复

如何通过危险的HTML函数返回我的数据字符串以呈现粗体标签?