2017-07-19 102 views
6

我们在我们的应用程序中使用.NET Framework提供的System.Web.Security.AntiXss.AntiXssEncoder类(我们的目标是.NET Framework 4.5.2),但是它们遇到了包含阿拉伯字符的字段问题。如何防止阿拉伯字符被AntiXssEncoder重新编码?

下面的控制台应用程序演示,我们有问题:

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(); 
     } 
    } 
} 

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

这从应用程序输出显示此(未编码阿拉伯字符显示为在控制台“???”):

Hello World => Hello World 

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

blöd => blöd 

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

是否有任何的方法来防止这种情况?

我们目前采取用户输入并将其传递到编码器,然后将其保存在我们的数据库中,然后将此编码数据发送到前端并显示出来。如果用户编辑字符串并将其传回给我们的后端,我们再次对其进行编码,然后再保存它,所以我们得到了&符号的问题。

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

有什么方法可以让编码器不会像&#1575;那样将字符重新编码为&amp;#1575;,或者我们只是在做错什么?

+0

你必须知道一个字符串是否被编码,总是。防止双重编码问题的唯一方法是不重新编码您知道要编码的字符串。是的,数据库*应该*包含原始的,未转义的值,因为替代方案是当您尝试查找“على”时,数据库代码突然必须知道HTML编码。正确编码字符串以进行显示和传输始终是前端的责任。 –

+1

谢谢@jeroenmostert - 这是有道理的,我可以,我们正在做的只是错误的 –

回答

0

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

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

如何来解决这个问题:

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

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

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

请注意,HtmlEncode方法的常见用法是最终将其渲染为原始HTML - 取决于您使用的框架,可能有更好的方法来处理它。如果您使用的是ASP.Net MVC,只需定期@Model.Text将提供所有必要的编码。

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