如何防止AntiXssEncoder重新编码阿拉伯字符?

时间:2017-07-19 14:40:18

标签: c# .net asp.net-web-api encoding xss

我们在我们的应用程序中使用.NET Framework提供的System.Web.Security.AntiXss.AntiXssEncoder类(我们的目标是.NET Framework 4.5.2),但是遇到包含阿拉伯字符的字段的问题。

以下控制台应用程序演示了我们遇到的问题:

using System;
using System.Collections.Generic;
using System.Web.Security.AntiXss;

namespace EncodingTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var source = new List<string> { "Hello World", "على", "blöd", "&#1575;&#1604;&#1605;" };

            foreach (var testString in source)
            {
                var antiXssEncoded = AntiXssEncoder.HtmlEncode(testString, false);
                Console.WriteLine($"{testString} => {antiXssEncoded}");

                Console.WriteLine();
            }

            Console.ReadKey();
        }
    }
}

第二个列表项中的阿拉伯字符已正确编码,但如果第四个元素中已编码的字符通过编码器,那么&#39;&amp;&#39;字符第二次编码到&amp;,然后在网页上无法正确显示。

应用程序的这个输出显示了这个(未编码的阿拉伯字符在控制台中显示为&#39; ???&#39;)

Hello World => Hello World

??? => &#1593;&#1604;&#1609;

blöd => blöd

&#1575;&#1604;&#1605; => &amp;#1575;&amp;#1604;&amp;#1605;

有没有办法阻止这种情况?

我们目前接受用户输入并将其传递给编码器,然后将其保存在我们的数据库中 - 然后将此编码数据发送到前端并显示。如果用户编辑了字符串并将其传递回我们的后端,我们会在保存之前再次对其进行编码,因此我们会遇到&符号的问题。

我在其他问题上看到了一些评论,说用户输入应该保存在数据库中,然后在发送显示之前通过编码器;我们可以做到这一点,但必须确保在数据输出的所有不同位置编码。它也不会帮助解决从前端返回的编辑数据的问题 - 我们仍然不知道数据是否已经编码,并且只会在下次发送数据时对其进行重新编码显示。

是否有某种方法可以让编码器不将&#1575;等字符重新编码为&amp;#1575;,或者我们只是做错了什么?

1 个答案:

答案 0 :(得分:0)

这是预期的行为,你不应该试图阻止它。

传递给HtmlEncode的字符串通常由程序的用户提供,并且最终应以HTML的形式出现在传递给该方法的精确方式中。这意味着需要对所有&(和类似情况)进行编码。例如。如果用户输入了类似"use '&amp;' to represent '&' in HTML"的内容,那么您在呈现的HTML中确实不会期望"use '&' to represent '&' in HTML"

如何解决问题:

您确实必须知道您正在使用的字符串内容的编码内容。绝对没有办法知道字符串是完全是HTML编码还是多少次。这同样适用于url编码(也称为%-encoding,如?q=search%20alot)和JavaScript-string-value编码(如I said \"Hi Matt\"\nin this is long & winded post)。

这意味着您需要存储具有一致编码的字符串或存储应用于sting的编码类型以及每个字符串(即DB中的下一列)。以下是我用于不同情况的描述:“这是纯文本,非编码”,“这是准备呈现HTML,消毒”,“这是用户提供的原始HTML,非消毒”,“这是纯文本编码为JavaScript字符串(使用\n)“。

将字符串错误分类为“准备呈现HTML,不要使用HtmlEncode”存在很大的危险 - 您可以轻松地将恶意用户的输入呈现为HTML并导致跨站点脚本(XSS)漏洞。您获得的过度编码行为更安全也可能产生无用的输出 - 因此要求字符串数据具有明确定义的编码。

请注意,HtmlEncode方法的常见用法是最终将其呈现为原始HTML - 根据您使用的框架,可能有更好的方法来处理它。如果您使用的是ASP.Net MVC,则常规@Model.Text将提供所有必要的编码。

作为指定编码的方法之一,您可以使用HtmlString类声明“字符串值表示可以按原样在HTML中安全呈现的原始HTML”。将HtmlEncode的输出存储在类型HtmlString的变量/属性中可能是个好主意,这样每个人都知道该值已被清理并且应该直接呈现。