如何防范Unicode安全漏洞

3

"五个关于Unicode的事情,每个人都应该知道"是一篇博客文章,展示了Unicode字符如何成为网站攻击向量的例子。

这种现实世界中的攻击的主要例子是一个假的WhatsApp应用程序,提交到Google Play商店,使用开发者名称中的Unicode不可打印空格,使名称独特,并允许其通过Google的过滤器。蒙古语元音分隔符(U+180E)就是这样一个不可打印的空格字符。

enter image description here

另一个漏洞是使用外观相似的替代Unicode字符。Mimic工具展示了这种方法的工作原理。
我可以想到的一个例子是在注册新用户时保护用户名。您不希望两个用户名相同,或者它们看起来相同
如何防范这种情况?是否有这些字符的列表可用?是否应该将所有这些类型的字符从所有表单输入中删除是通行做法?

1
你想要多么“包容”?如果你将有效输入限制为ASCII字符,那么这个问题就很小了。你想允许的越多,它就变得越棘手。 - deceze
1
是的,ASCII 是最简单的选项,但如果您的用户名是多语言的呢?我正在尝试研究 Twitter 的做法。 - Muhammad Rehan Saeed
4个回答

2
您所说的被称为同形攻击。Unicode有一份“可混淆字符”列表,可以在此处查看,也可以参考这个网站。应该已经有基于这些或其他数据库的库了。其中一个库是这个,可在Java或Javascript中使用。其他语言也应该有相似的库,或者您自己写一个。

我认为重要的是不要拥有自己的数据库——基于好的数据很容易做出库或服务。

至于是否应该过滤类似的用户名——我认为这取决于情况。如果用户试图模仿对方的用户名,可能会有兴趣,对于许多其他类型的数据,也许没有必要这样做。我认为没有通用的最佳实践,除了您应该评估应用程序中的风险和数据点。

另外,针对不同的问题可以采用不同的方法,但对于Unicode输入验证,常用的方法是正则表达式中的\w单词字符,如果您的正则表达式引擎支持Unicode。在这样的引擎中,\w应该匹配所有语言中字母、修饰符和连接符的Unicode类,但不匹配其他字符(没有特殊字符)。这不能保护您免受同形攻击,但可以在保持应用程序支持Unicode的情况下防止某些注入。


0

这个问题可以用多种方法来解决,但每种方法可能会增加虚假阳性的数量,从而引起合法用户的烦恼。此外,即使将它们组合起来,也没有一种方法能够100%地奏效。它们只会增加一个额外层次。

其中一种方法是使用包含相似字符的表,并检查是否存在重复名称。在许多情况下,“相似”是主观的,因此建立这样的列表可能会很棘手。该方法可能在某些场合产生错误结果。

此外,颠倒某些字母的顺序可能会欺骗许多用户。使用像Jaro-Winkler和Levenshtein距离这样的算法可以实现检查变位词或非常相似的名称(例如,检查类似的用户名/公司名称是否已经存在)。然而,有时这可能是由于某个单词在某个地区的不同拼写(例如,“centre”与“center”),或者某个公司的名称可能故意包含一个变位词。这种方法可能会进一步增加误报的数量。

此外,正如Jonathan所提到的那样,清理数据也是一种好方法,但它可能无法防止变位词,并给想要使用某些特殊字符的合法用户带来问题。

正如OP所提到的,特殊字符也可以被剥离。名称的其他部分也可能需要被剥离,例如常见的名称如“Inc.”、“.com”等。

最后,名称可以限制只包含一个语言中的字符,而不是来自各种语言的混合字符(更宽松的版本可能不允许在同一个单词中混合使用字符-但如果用空格分隔,则允许)。使用大写字母作为首字母并将其余字母小写可以进一步改善此方法,因为某些小写字母(如“l”)在使用某些字体时可能看起来像大写字母(如“I”)。排除某些符号(如“|”)将进一步增强此方法。这种解决方案将增加某些用户的烦恼程度,他们将无法使用某些名称。

还可以使用一些/全部前述方法的组合。选择方法以及如何应用它们(例如,您可以选择禁止相似的名称,或要求管理员批准,以防名称相似,或不采取任何行动,而只是警告管理员/版主)取决于您试图解决的情况。


0

我可能有一个关于用户名问题的创新解决方案。显然,您希望允许ASCII字符,但在某些特殊情况下,将使用其他字符(如您所说的不同语言)。

我认为一种直观的方法是允许使用ASCII和其他字符作为用户名,并同时保护免受“Unicode漏洞”的影响,具体做法如下:

允许所有ASCII字符,并禁止使用其他字符,除非用户名中有x个或更多这些特殊字符(用户名是另一种语言)。

以此为例:

Whatsapp, Inc + (U+180E) - 不允许,只有1个特殊字符。

элч + (U+180E) - 允许!它有多于x个特殊字符(例如3个)。它可以使用蒙古语分隔符,因为它是蒙古语。

显然,这并不能百分之百地保护您免受此类漏洞的影响,但这是一种非常有效的方法,我一直在使用,特别是如果您不在“登录”或“注册”页面上提到此算法的存在,因为攻击者可能会发现您有一个保护网站免受这些攻击的算法,但不提及它,以便他们无法反向工程它并找到绕过它的方法。

如果这不是您要寻找的答案,那我很抱歉,只是分享我的想法。

编辑:或者您可以使用 RNN(递归神经网络)AI来检测语言并允许该语言的特定字符。


安全靠混淆并不是真正的安全。 - Gabor Lengyel

0

当您拥有已知安全值的白名单,并排除所有其他值时,所有卫生工作最有效。

ASCII是其中一组字符。


1
ASCII是一个例子,但世界并不仅限于使用英语。也许需要列出一份安全的Unicode字符列表。 - Muhammad Rehan Saeed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接