我真的很抱歉这样做,但是这个问题在我工作的网站上代表了一个可能被利用的安全问题,所以我发布了一个新帐户。
我们有一个接受用户评论的脚本(所有评论都是英文的)。我们在两年内积累了大约3,000,000条评论。我正在检查评论表中是否有任何恶意行为的迹象,这次我对撇号进行了扫描。在所有情况下,这应该已经转换为HTML实体('
),但我找到了18个记录(300万个中),其中角色幸免于难。真正打破我头脑的是,在这18条评论中的一条中,一条撇号实际上已成功转换 - 另一条幸存下来。
这向我表明我们可能存在XSS漏洞。
我对正在发生的事情的理论是,用户正在使用非西方代码页的计算机系统上访问该页面,并且他们的浏览器忽略了我们页面的utf-8字符集规范,他/她的输入没有得到转换到服务器的本地代码页,直到它到达数据库(因此C#没有将该字符识别为撇号,因此无法转换它,但数据库是在它尝试将其写入LATIN1表时)。但这是一个完全猜测。
之前是否有人遇到此事或知道发生了什么?
更重要的是,有谁知道我如何测试我的脚本?转移到HttpUtility
可能会解决问题,但在我知道这是怎么发生之前,我不知道问题是否已解决。我需要能够对此进行测试,以了解我们的解决方案是否有效。
修改
哇。已经20分,所以我可以编辑我的问题。
我在其中一条评论中提到,我发现有几个字符似乎有问题。它们包括:0x2019,0x02bc,0x02bb,0x02ee,0x055a,0xa78c。这些通过我们的过滤器。不幸的是,它们也通过了所有HttpUtility编码方法。但是一旦它们被插入到数据库中,它们就会转换成实际的撇号或“?”。
在回顾中,我认为问题是这些角色本身并不构成威胁,因此HttpUtility没有理由转换它们。在一个Javascript块中,它们是无害的。在HTML块中,它们只是字符数据并且是无害的。在SQL块中,它们是无害的(如果数据库共享相同的代码页)。对我们来说问题是因为我们在数据库中使用的代码页是不同的,数据库中的插入过程涉及将这些“不可打印”的字符转换为“已知的等价物”(在这种情况下是“坏”)和“未知等价物“(将其呈现为”?“)。这完全是盲目的我们,我对MS没有进一步构建其HttpUtility编码函数感到有些失望。
我认为解决方案是更改受影响表的排序规则。但如果其他人有更好的想法,请在下面发布。
答案 0 :(得分:3)
你在错误的地方过滤,恕我直言。数据库应包含用户输入的实际字符。你应该将HTML的转义留给表示层,它更好地了解如何操作。
答案 1 :(得分:1)
这听起来像你的DBMS中的存储使用非unicode列类型,而.net正在使用unicode。
你可以在.net中最初将unicode转换为dbms'排序规则,然后返回unicode以删除应用程序级别的任何不受支持的字符,而不是将其留给dbms / connector。
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等等。
答案 2 :(得分:0)
尽管尝试过滤用户内容总是好的,但假设您能够可靠而安全地“抓住所有内容”并不是现实。
始终假设数据库中的用户数据已损坏,被黑客攻击,包含纯HTML或其他您不了解的浏览器特定代码,而是确保所有用户数据的输出都是安全编码的。
在-HtmlEncode()中,将所有数据呈现给页面以进行开始,并为用户可以编辑的每个字段执行此操作。甚至是基本的名字字段等,而不仅仅是评论正文数据。
单引号也不是XSS问题,它允许标签和浏览器特定代码是问题,你可以显示任意数量的单引号,没有完全未编码的问题,你不能形成一个XSS攻击。但是,您可以使用不带任何单引号(甚至双引号)的标签轻松地进行XSS攻击。我认为你可能会混淆SQL注入问题(SQL字符串中的单引号)和XSS问题