2

我需要过滤一些非法字符串,例如“密码”,但我发现有人绕过了我的检查程序。他们输入了一个看起来完全是“密码”但不相等的字符串。我检查了它的Unicode,例如,“a”是8e61,而普通的“a”是61(十六进制)。我的 PHP 文件的编码、HTML 元 Content-Type 和 MySQL 编码是 utf-8。

这是怎么发生的?为什么视觉上相同的字符具有不同的代码?我想知道如何过滤这些字符。我把奇怪的字符串放在这里,请复制它以供研究:密码


出于某种原因,当我在这里复制有问题的“密码”时,它实际上显示的是 ASCII 码。

我在“密码”上使用 PHP 函数 bin2hex(),并得到以下信息:

50c28e61c28e73c28e73c28e776fc28e72c28e64c28e

而正常的是:

50617373776f7264.

为了简单起见,“a”的十六进制表示为:

c28e61

而正常的是:

61
4

2 回答 2

1

给定 hex string 50c28e61c28e73c28e73c28e776fc28e72c28e64c28e,你有一个有效的 UTF-8 字符串的编码:

0x50      = U+0050 = P
0xC2 0x8E = U+008E = SS2
0x61      = U+0061 = a
0xC2 0x8E = U+008E = SS2
0x73      = U+0073 = s
0xC2 0x8E = U+008E = SS2
0x73      = U+0073 = s
0xC2 0x8E = U+008E = SS2
0x77      = U+0077 = w
0x6F      = U+006F = o
0xC2 0x8E = U+008E = SS2
0x72      = U+0072 = r
0xC2 0x8E = U+008E = SS2
0x64      = U+0064 = d
0xC2 0x8E = U+008E = SS2

0xC2 0x8E 序列映射到 ISO 8859-1 0x8E,这是一个控制字符 SS2 或 Single Shift 2(参见Unicode 代码表)。SS2 没有定义的可见表示。该字符串明显不同于普通的“密码”。只要您不去除控制字符,您就应该能够发现差异,因为字符串比较不应将其视为与普通的“密码”相同。

于 2013-07-16T05:44:12.673 回答
0

您可能看到的(我无法确切地说出,因为您的问题的某些部分没有意义或不一致)是所谓的homoglyphs。这些字符看起来相同或非常相似,因此乍一看可能会出错。为了规避您的检查,人们可以使用西里尔字母a并逃脱惩罚。但坦率地说,这实际上不是问题,因为我知道没有密码破解者会真正尝试混合脚本,因为大多数密码都是仅 ASCII 的。

至于为什么,你可以看看为什么Unicode中有重复字符?.

于 2013-07-16T05:33:18.507 回答