- 目录
- 1. 序章
- 2. 计算机网络与协议
- 3. 信息收集
- 4. 常见漏洞攻防
- 5. 语言与框架
- 6. 内网渗透
- 7. 云安全
- 8. 防御技术
- 9. 认证机制
- 10. 工具与资源
- 11. 手册速查
- 12. 其他
12.5. Unicode
12.5. Unicode
12.5.1. 基本概念
12.5.1.1. BMP
BMP (Basic Multilingual Plane),译作基本多文种平面,是Unicode中的一个编码区块。
12.5.1.2. 码平面
Unicode编码点分为17个平面(plane),每个平面包含2^16(即65536)个码位。17个平面的码位可表示为从U+xx0000到U+xxFFFF,其中xx表示十六进制值从0016到1016,共计17个平面。
12.5.1.3. Code Point
Code Point也被称作Code Position,译作码位或编码位置,是指组成代码空间的数值。
12.5.1.4. Code Unit
指某种 Unicode 编码方式里编码一个 Code Point 需要的最少字节数,比如 UTF-8 需要最少一个字节,UTF-16 最少两个字节,UCS-2 两个字节,UCS-4 和 UTF-32 四个字节。
12.5.1.5. Surrogate Pair
Surrogate Pair 是用于 UTF-16 的以向后兼容 UCS-2 的,做法是取 UCS-2 范围里的 0xD800~0xDBFF (称为 high surrogates) 和 0xDC00~0xDFFF (称为 low surrogates) 的码位,一个 high surrogate 接一个 low surrogate 拼成四个字节表示超出 BMP 的字符,两个 surrogate range 都是 1024 个码位,所以 surrogate pair 可以表达 1024 x 1024 = 1048576 = 0x100000 个字符。
12.5.1.6. Combining Character
例如 He̊llö
含有重音符号之类的字符,进行组合会使用大量的码位。所以这种字符多用组合的方式来实现。
12.5.1.7. BOM
字节顺序标记(byte-order mark,BOM)是一个有特殊含义的统一码字符,码点为 U+FEFF
。当以UTF-16或UTF-32来将UCS字符所组成的字符串编码时,这个字符被用来标示其字节序。常被用于区分是否为UTF编码。
12.5.2. 编码方式
12.5.2.1. UCS-2
UCS-2 (2-byte Universal Character Set)是一种定长的编码方式,UCS-2仅仅简单的使用一个16位码元来表示码位,也就是说编码范围在0到0xFFFF的码位范围内。
12.5.2.2. UTF-8
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码。它可以用一至四个字节对Unicode字符集中的所有有效编码点进行编码,属于Unicode标准的一部分。编码方式如下
码点的位数 | 码点起值 | 码点终值 | 字节序列 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 |
---|---|---|---|---|---|---|---|---|---|
7 | U+0000 | U+007F | 1 | 0xxxxxxx | |||||
11 | U+0080 | U+07FF | 2 | 110xxxxx | 10xxxxxx | ||||
16 | U+0800 | U+FFFF | 3 | 1110xxxx | 10xxxxxx | 10xxxxxx | |||
21 | U+10000 | U+1FFFFF | 4 | 11110xxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | ||
26 | U+200000 | U+3FFFFFF | 5 | 111110xx | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | |
31 | U+4000000 | U+7FFFFFFF | 6 | 1111110x | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx |
12.5.2.3. UTF-16
UTF-16 (16-bit Unicode Transformation Format)是UCS-2的拓展,用一个或者两个16位的码元来表示码位,可以对0到0x10FFFF的码位进行编码。
12.5.3. 等价性问题
12.5.3.1. 简介
Unicode(统一码)包含了许多特殊字符,为了使得许多现存的标准能够兼容,提出了Unicode等价性(Unicode equivalence)。在字符中,有些在功能上会和其它字符或字符序列等价。因此,Unicode将一些码位序列定义成相等的。
Unicode提供了两种等价概念:标准等价和兼容等价。前者是后者的一个子集。例如,字符n后接着组合字符 ~ 会(标准和兼容)等价于Unicode字符ñ。而合字ff则只有兼容等价于两个f字符。
Unicode正规化是文字正规化的一种形式,是指将彼此等价的序列转成同一列序。此序列在Unicode标准中称作正规形式。
对于每种等价概念,Unicode又定义两种形式,一种是完全合成的,一种是完全分解的。因此,最后会有四种形式,其缩写分别为:NFC、NFD、NFKC、NFKD。对于Unicode的文字处理程序而言,正规化是很重要的。因为它影响了比较、搜索和排序的意义。
12.5.3.2. 标准等价
统一码中标准等价的基础概念为字符的组成和分解的交互使用。合成指的是将简单的字符合并成较少的预组字符的过程,如字符n和组合字符 ~ 可以组成统一码ñ。分解则是反向过程,即将预组字符变回部件。
标准等价是指保持视觉上和功能上的等价。例如,含附加符号字母被视为和分解后的字母及其附加符号是标准等价。换句话说,预组字符‘ü’和由‘u’及 ‘¨’所组成的序列是标准等价。相似地,统一码统合了一些希腊附加符号和外观与附加符号类似的标点符号。
12.5.3.3. 兼容等价
兼容等价的范围较标准等价来得广。如果序列是标准等价的话就会是兼容等价,反之则未必对。兼容等价更关注在于纯文字的等价,并把一些语义上的不同形式归结在一起。
例如,上标数字和其所使用的数字是兼容等价,但非标准等价。其理由为下标和上标形式虽然在某些时侯属于不同意义,但若应用程序将他们视为一样也是合理的(虽然视觉上可区分)。如此,在统一码富文件中,上标和下标就可以以比较不累赘地方式出现(见下一节)。
全角和半角的片假名也是一种兼容等价但不是标准等价。如同合字和其部件序列。其只有视觉上但没有语义上的区别。换句话说,作者通常没有特别宣称使用合字是一种意思,而不使用是另一种意思。相对地,这尽限于印刷上的选择。
文字处理软件在实现统一码字符串的搜索和排序时,须考虑到等价性的存在。如果没有此特性的话,用户在搜索时将无法找到在视觉上无法区分的字形。
统一码提供了一个标准的正规化算法,可将所有相同的序列产生一个唯一的序列。 其等价准绳可以为标准的(NF)或兼容的(NFK)。 既然可以任意选择等价类中的元素,对每一个等价标准有多个标准形式也是有可能的。 统一码为每一种等价准绳分别提供两种正规形式:合成用的NFC和NFKC以及分解用的NFD和NFKD。 而不论是组合的或分解的形式,都会使用标准顺序,以此限制正规形式只有唯一形式。
12.5.3.4. 正规化
为了比较或搜索统一码字符串,软件可以使用合成或分解形式其中之一。 只要被比较或搜索的字符串使用的形式是相同的,哪种选择都没关系。 另一方面,等价概念的选择则会影响到搜索结果。 譬如,有些合字如ffi(U+FB03)、罗马数字如Ⅸ(U+2168),甚至是上标数字如⁵(U+2075)有其个别统一码码位。 标准正规形式并不会影响这些结果。 但兼容正规形式会分解ffi成f、f、i。所以搜索U+0066(f)时,在NFKC中会成功,但在NFC则会失败。 同样地有在预组罗马数字Ⅸ 中搜索拉丁字母I(U+0049)。类似地,“⁵”会转成“5”。
对于浏览器,将上标转换成到基下划线未必是好的,因为上标的信息会因而消失。为了允许这种不同,统一码字符数据库句含了兼容格式标签,其提供了兼容转换的细节。在合字的情况下,这个标签只是 <compat>
,而在上标的情况下则为 <super>
。丰富文件格式如超文本置标语言则会使用兼容标签。例如,HTML使用自定义标签来将“5”放到上标位置。
12.5.3.5. 正规形式
- NFD Normalization Form Canonical Decomposition 以标准等价方式来分解
- NFC Normalization Form Canonical Composition 以标准等价方式来分解,然后以标准等价重组之。若是singleton的话,重组结果有可能和分解前不同。
- NFKD Normalization Form Compatibility Decomposition 以兼容等价方式来分解NFKC
- Normalization Form Compatibility Composition 以兼容等价方式来分解,然后以标准等价重组之
12.5.4. Tricks
- 部分语言的长度并不是字符的长度,一个UTF-16可能是两位。
- 部分语言在翻转UTF-16等多字节编码时,会处理错误。
12.5.5. 安全问题
12.5.5.1. Visual Spoofing
例如bаidu.com(此处的a为u0430)和baidu.com(此处的a为x61)视觉上相同,但是实际上指向两个不同的域名。
baidu.com(此处的a为uff41)和baidu.com(此处的a为x61)有一定的不同,但是指向两个相同的域名。
这种现象可以引起一些Spoofing或者WAF Bypass的问题。
12.5.5.2. Best Fit
如果两个字符前后编码不同,之前的编码在之后的编码没有对应,程序会尝试找最佳字符进行自动转换。
当宽字符变成了单字节字符,字符编码会有一定的变化。
这种现象可能引起一些WAF Bypass。
12.5.5.3. Syntax Spoofing
以下四个Url在语法上看来是没问题的域名,但是用来做分割的字符并不是真正的分割字符,而是U+2044( ⁄ ),可以导致一些UI欺骗的问题。
- http://macchiato.com/x.bad.com macchiato.com/x bad.com
- http://macchiato.com?x.bad.com macchiato.com?x bad.com
- http://macchiato.com.x.bad.com macchiato.com.x bad.com
- http://macchiato.com macchiato.com#x bad.com
12.5.5.4. Punycode Spoofs
- http://䕮䕵䕶䕱.com http://xn--google.com
- http://䁾.com http://xn--cnn.com
- http://岍岊岊岅岉岎.com http://xn--citibank.com
有些浏览器会直接显示puncode,但是也可以借助这种机制实现UI Spooof。
12.5.5.5. Buffer Overflows
在编码转换的时候,有的字符会变成多个字符,如Fluß → FLUSS → fluss这样可能导致BOF。
12.5.6. 常见载荷
12.5.6.1. URL
‥
(U+2025)︰
(U+FE30)。
(U+3002)⓪
(U+24EA)/
(U+FF0F)p
(U+FF50)ʰ
(U+02B0)ª
(U+00AA)
12.5.6.2. SQL注入
'
(U+FF07)"
(U+FF02)﹣
(U+FE63)
12.5.6.3. XSS
<
(U+FF1C)"
(U+FF02)
12.5.6.4. 命令注入
&
(U+FF06)|
(U+FF5C)
12.5.6.5. 模板注入
﹛
(U+FE5B)[
(U+FF3B)
12.5.7. 参考链接
12.5.7.1. 官方文档
12.5.7.2. RFC
- RFC 3629 UTF-8, a transformation format of ISO 10646
- RFC 2044 UTF-8, a transformation format of ISO 10646
- RFC 2279 UTF-8, a transformation format of ISO 10646
12.5.7.3. Tricks / Blogs
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论