撇号通过了C#中的过滤器
本文关键字:过滤器 通过了 | 更新日期: 2023-09-27 17:58:14
我真的很抱歉这么做,但这个问题代表了我工作的网站上可能存在可利用的安全问题,所以我用一个新帐户发布了这个问题。
我们有一个接受用户评论的脚本(所有评论都是英文的)。我们在两年内收集了大约3000000条评论。我正在查看评论表中是否有恶意行为的迹象,这次我扫描了撇号。在所有情况下,都应该将其转换为HTML实体('
),但我发现有18条记录(在300万条记录中)保留了该字符。真正让我头疼的是,在这18条评论中的一条评论中,一个撇号实际上被成功转换了——另一个幸存了下来。
这向我表明,我们可能存在XSS漏洞。
我的理论是,用户在使用非西方代码页的计算机系统上点击页面,而他们的浏览器忽略了我们页面的utf-8字符集规范,他/她的输入在到达数据库之前不会被转换到服务器的本地代码页(因此C#没有将该字符识别为撇号,因此无法转换,但当它试图将其写入LATIN1表时,数据库会将其转换)。但这完全是猜测。
以前有人遇到过这种情况吗?或者知道发生了什么?
更重要的是,有人知道我如何测试我的脚本吗?转移到HttpUtility
可能会解决这种情况,但在我知道这是怎么发生的之前,我不知道问题已经解决。我需要能够测试这一点,以了解我们的解决方案是否有效。
编辑
哇。已经20分了,所以我可以编辑我的问题。
我在一条评论中提到,我发现几个角色似乎有问题。它们包括:0x2019、0x02bc、0x02bb、0x02ee、0x055a、0xa78c。这些直接通过我们的过滤器。不幸的是,它们也直接通过了所有HttpUtility编码方法。但一旦它们被插入数据库,它们就会被转换为实际的撇号或"?"。
在回顾中,我认为问题在于这些字符本身不会构成威胁,所以HttpUtility没有理由转换它们。在一个Javascript块中,它们是无害的。在HTML块中,它们只是字符数据,是无害的。在SQL块中,它们是无害的(如果数据库共享相同的代码页)。我们面临的问题是,因为我们在数据库中使用的代码页不同,所以在数据库中的插入过程包括将这些"不可打印"的字符转换为"已知等效字符"(在本例中为"坏")和"未知等效字符"(呈现为"?")。这完全是盲目的,我对MS没有在其HttpUtility编码函数中构建更多内容感到有点失望。
我认为解决方案是更改受影响表的排序规则。但如果其他人有更好的想法,请在下面发帖。
IMHO,您在错误的地方进行了过滤。数据库应该包含用户输入的实际字符。您应该将HTML的转义留给表示层,表示层更了解如何执行。
这听起来像是DBMS中的存储使用非unicode列类型,而.net使用unicode。
您可以在.net中首先将unicode转换为dbms的排序规则,然后再转换回unicode,以在应用程序级别删除任何不受支持的字符,而不是将其留给dbms/连接器。
var encoding = Encoding.GetEncoding("Latin1") //this should be matched to the column's collation
foo = encoding.GetString (encoding.GetBytes (foo)); // couldn't see a more efficient way to do this.
尽管如前所述,理想情况下,您应该将实际字符存储在DBMS中,并将编码留给表示步骤。其中,您可以尝试以一种不会忘记对字符串数据进行编码的方式来设置框架,例如asp.net 4使用<%: %>
,JSON使用JSON.net而不是字符串串联,用于XML XLINQ等。
虽然尝试和过滤用户内容总是很好的,但假设您可以可靠、安全地"全部捕获"并不是现实。
始终假设你的数据库中的用户数据被破坏、黑客入侵,包含纯HTML或其他你不知道的浏览器特定代码,并确保所有用户数据的输出都被安全编码。
就像在-HtmlEncode()中一样,所有数据首先呈现到页面上,并对用户可以编辑的每个字段进行处理。甚至是基本的名字字段等,而不仅仅是注释体数据。
此外,单引号不是XSS问题,它允许标记和浏览器特定的代码是问题所在,您可以显示任意多的单引号,而不会出现完全未编码的问题,因此您无法形成XSS攻击。然而,您可以使用没有任何单引号(甚至双引号)的标记轻松地进行XSS攻击。我认为您可能混淆了SQL注入问题(SQL字符串中的单引号)和XSS问题