历史
在1963年,计算机的使用尚不广泛,那时使用的是7-bit的ASCII码,范围为0-127作为字符的编码,只支持少部分的字符,但是随着计算机的普及,不同的国家地区开始自己制造自己的编码规范,这导致了互相不兼容,成为一个问题。
为了解决问题,ISO开始尝试制定包含大部分字母和符号的编码,为UCS也就是unicode编码。
unicode编码
unicode实际上是一个字符与数字之间的映射关系表,并没有实际的编码方案,因此制定了UTF标准,包括UTF-8,UTF-16,UTF-32等,Unicode是一个设计图,而UTF为理论的实现。
Code point 与 code unit
Code point是unicode标准里字符的编号,目前unicode使用0~0x10FFFF编码范围,通过U+xxxx表示某个字符。
Code unit是unicode编码里一个code point需要的最少字节数,UTF-8至少需要一个字节,UTF-16,UCS-2至少需要2个字节,UCS-4,UTF-32为四个字节,后面三个为定长编码。
问题
由于包含了众多的编码,容易造成各种各样的问题:
视觉欺骗
有的字符看起来非常相似,这导致了视觉上的问题,例如аррӏе.com(ӏ为U+04CF)与apple.com,为了解决这一问题chrom使用punycode域名编码,即对域名进行编码,以xn--开头,例如аррӏе.com,chrom检测到可能有视觉欺骗情况时,对其编码为xn--80ak6aa92e.com(只会对知名网站视觉欺骗转换),firefox并没有此功能。(python的idna库便是实现此功能的库)
然而punycode也存在视觉欺骗例如:䕮䕵䕶䕱.com编码为xn--google.com
双向显示
由于阿拉伯和希伯来语是从右往左读,加入unicode控制字符后可能存在问题,例如txt.exe变为exe.txt
数字显示
孟加拉语0-9为০ ১ ২ ৩ ৪ ৫ ৬ ৭ ৮ ৯ 这里的৪(U+09EA)实际上为4
等价形式
在WAF类处理时,会注意到一些等价意义的字符并进行过滤,例如LocalHost等同于localhost,但是另外还有ⓛocaⓛhost也等同,这种情况容易忽略
字符删除
在\x3c\x73\x63\x72\xc2\x69\x70\x74\x3e字符串中,\xc2不是一个有效的字串,在一些逻辑处理中可能会删除,这可能导致为题
字符替换
在一些情况下,U+FFFF会被替换成?,这会导致问题
缓冲区溢出
在进行大小写转换时,可能字符会变多,例如'ß'.toUpperCase()会变成SS,如果长度检查在大小写转换之前,就可能存在缓冲区溢出问题。