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

cho*_*bo2 7 .net javascript c# security asp.net-mvc

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

我知道你可以使用正则表达式,但我也知道人们可以编写脚本标签的方法很多,你可以欺骗正则表达式认为它没问题.

我还听说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>
Run Code Online (Sandbox Code Playgroud)

2)删除包含表达式规则的所有样式属性.Internet Explorer将CSS规则表达为脚本.例如,以下内容将生成一个消息框:

<div style="width:expression(alert('hi'));">bad> code</div>
Run Code Online (Sandbox Code Playgroud)

3)同时删除标签

老实说,我不知道为什么"表达"还没有从IE中删除 - 我认为这是一个重大缺陷.(尝试在Internet Explorer中的div示例,你会明白为什么 - 甚至IE8.)我只是希望有一种更简单/标准的方法来清理用户的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();
    } 
Run Code Online (Sandbox Code Playgroud)

Jef*_*ern -2

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

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

这将删除所有非字母数字的内容。

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

ETC。

您还可以通过删除“<”和“>”字符之间以及“>”和“<”之间的文本来进一步扩展此功能。

我不想使用外部第三方库 - 除非必须 - 因为你也必须分发该库,你依赖别人的程序来保证你的安全,如果他们的软件存在漏洞,你的软件也很容易受到攻击也。

  • 另一方面,如果我使用第三方库,我通常可以获得他们解决方案的所有稳健性和能力,而无需花费大量时间编码由于我对问题的细微差别缺乏完全理解而导致的不完整的解决方案。选择正确的第三方库是另一个问题。 (3认同)