辉克's Blog

创造机会的人是勇者;等待机会的人是愚者

Unicode transformation issues原理

0x01. 漏洞介绍
Unicode transformation issues含义为Unicode转换问题。在Unicode在转换时,由于超长字节序列和错误格式引起子序列的安全问题。通过特殊的编码格式绕过程序对恶意字符的检测,可以用在SQL注入、XSS等。
0x02. 漏洞原理
一、简要编码说明
1. ASCII码
ASCII 码使用指定的7 位或8 位二进制数组合来表示128 或256 种可能的字符。标准ASCII 码也叫基础ASCII码,使用一个字节的后面7 位二进制数来表示所有的大写和小写字母,数字0 到9、标点符号,以及在美式英语中使用的特殊控制字符,最前面的的1位统一规定为0。
2. Unicode编码
统一码的编码方式与ISO 10646的通用字符集概念相对应。目前实际应用的统一码版本对应于UCS-2,使用16位的编码空间。也就是每个字符占用2个字节。这样理论上一共最多可以表示216(即65536)个字符。基本满足各种语言的使用。实际上当前版本的统一码并未完全使用这16位编码,而是保留了大量空间以作为特殊使用或将来扩展。
上述16位统一码字符构成基本多文种平面。基本多文种平面的字符的编码为U+hhhh,其中每个h代表一个十六进制数字,与UCS-2编码完全相同。而其对应的4字节UCS-4编码后两个字节一致,前两个字节则所有位均为0。
Unicode的实现方式不同于编码方式。一个字符的Unicode编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。Unicode的实现方式称为Unicode转换格式(Unicode Transformation Format,简称为UTF)
例如,如果一个仅包含基本7位ASCII字符的Unicode文件,如果每个字符都使用2字节的原Unicode编码传输,其第一字节的8位始终为0。这就造成了比较大的浪费。对于这种情况,可以使用UTF-8编码,这是一种变长编码,它将基本7位ASCII字符仍用7位编码表示,占用一个字节(首位补0)。而遇到与其他Unicode字符混合的情况,将按一定算法转换,每个字符使用1-3个字节编码,并利用首位为0或1进行识别。这样对以7位ASCII字符为主的西文文档就大大节省了编码长度(具体方案参见UTF-8)。
3. UTF-8编码
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部份修改,即可继续使用。
UTF-8使用一至四个字节为每个字符编码:

  1. 128个US-ASCII字符只需一个字节编码(Unicode范围由U+0000至U+007F)。
  2. 带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及它拿字母则需要二个字节编码(Unicode范围由U+0080至U+07FF)。
  3. 其他基本多文种平面(BMP)中的字符(这包含了大部分常用字)使用三个字节编码。
  4. 其他极少使用的Unicode 辅助平面的字符使用四字节编码。

代码范围

十六进制

标量值(scalar value)

二进制

UTF-8

二进制/十六进制

注释

000000-00007F128个代码 00000000 00000000 0zzzzzzz 0zzzzzzz(00-7F) ASCII字符范围,字节由零开始
七个z 七个z
000080-0007FF1920个代码 00000000 00000yyy yyzzzzzz 110yyyyy(C0-DF) 10zzzzzz(80-BF) 第一个字节由110开始,接着的字符有10开始
三个y;二个y;六个z 五个y;六个z
000800-00D7FF00E000-00FFFF61440个代码 00000000 xxxxyyyy yyzzzzzz 1110xxxx(E0-EF) 10yyyyyy 10zzzzzz 第一个字节由1110开始,接着的字节由10开始
四个x;四个y;二个y;六个z 四个x;六个y;六个z
010000-10FFFF1048576个代码 000wwwxx xxxxyyyy yyzzzzzz 11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz 将由11110开始,接着的字节由10开始
三个w;二个x;四个x;四个y;二个y;六个z 三个w;六个x;六个y;六个z

Unicode和UTF-8之间的转换关系表

UCS-4编码

UTF-8字节流

U+00000000 – U+0000007F 0xxxxxxx
U+00000080 – U+000007FF 110xxxxx 10xxxxxx
U+00000800 – U+0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
U+00010000 – U+001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U+00200000 – U+03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U+04000000 – U+7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

例如:希伯来语字母aleph(?)的Unicode代码是U+05D0,按照以下方法改成UTF-8:

  1. 按照上面列表此字母属于U+0080到U+07FF区域,说明它使用双字节,110yyyyy 10zzzzzz
  2. 十六进制0x05D0换算成二进制为101-1101-0000
  3. 将这二进制数字按顺序放入“y”和“z”的两部分中:11010111 10010000
  4. 最后结果就是双字节,用十六进制表示为0xD7 0x90,这就是字符aleph(?)的UTF-8编码

二、漏洞原理
根据漏洞描述可以确定是由于Unicode转码引起的安全问题,从Unicode官网可以获得信息存在此安全问题的Unicode版本为3.0,并在Unicode 3.1时修复此漏洞。从三点分析:Best-Fit Mappings,Overlong Byte sequences和Ill-Formed Subsequences。
1. Best-Fit Mappings
当一个字符X转码为另一个完全不同的字符Y时,可能发生“最佳匹配映射”现象。可能发生在以下地方:
a) 框架API转换输入字符为默认编码
b) 数据从宽字节转为非宽字节
c) 源编码字符编码不在目标内容的编码中
2. Overlong Byte sequences
根据上面编码转换表,传入“non-shortest form”(非最短形式)的字符串,如果是一个存在安全问题的Unicode转码,超长字节序列可能解析成其他特殊字符串。
3. Ill-Formed Subsequences
UTF-8对某字符串编码。遍历UTF-8转换器中输入的UTF-8字节,然后输出字符的编码。如果出现错误格式,如U+FFFD,SUB,“?”,空格等字符,它不能消耗下一个有效的字节。
例如: X = <… 41 C0 3E 42 …>
有一个错误格式的字节序列,其中包含了一个错误格式的子序列<C2>,按照前面的编码转换内容应该属于000080-0007FF范围内,也就是110yyyyy(C0-DF) 10zzzzzz(80-BF),C2字节在C0-DF中,但是3E字节不在80-BF中,就不能消耗3E字节与其组成2个字节字符。这时如果继续编码则删除C2字节或暂停解码。但是如果Unicode可以解释“non-shortest form”(非最短形式),那么C2和3E组成两个字节的字符0xC2 0x3E,按照上面例子逆向装换如下:

  1. 将0xC2 0x3E转换成二进制:11000010 10111110,注意第二个字节
  2. 双字节字符格式为110yyyyy 10zzzzzz,获取“y”和“z”两部分组成字符的二进制为:000-1011-1110
  3. 将得到的二进制转换成十六进制Unicode编码为:U+BE

这样在存在此安全问题的Unicode转换UTF-8的时就会出现错误的格式,从而可能使用双字节的Unicode字符转换UTF-8编码时合成特殊字符。
4
0x03. 测试环境
没找到合适的,只在测试中发现过一次
0x04. 漏洞EXP
明文:”/><script>alert(/Ends/)</script>
2字节编码:%C0%A2%C0%AF%C0%BE%C0%BC%C1%B3%C1%A3%C1%B2%C1%A9%C1%B0%C1%B4%C0%BE%C1%A1%C1%AC%C1%A5%C1%B2%C1%B4%C0%A8%C0%AF%C1%85%C1%AE%C1%A4%C1%B3%C0%AF%C0%A9%C0%BC%C0%AF%C1%B3%C1%A3%C1%B2%C1%A9%C1%B0%C1%B4%C0%BE
0x05. 修补建议
1、 升级Unicode版本至官方最新稳定版本http://www.unicode.org
2、 Unicode转化UTF-8编码后,对转换后进行安全检测,对特殊字符过滤或进行安全编码后输出。
0x06. 样例截图
5
0x07. 参考资料

  1. http://www.unicode.org/reports/tr36/
  2. http://www.acunetix.com/blog/news/acunetix-20130308-new-tests/
  3. http://zh.wikipedia.org/wiki/UTF-8
  4. http://zh.wikipedia.org/wiki/Unicode#Unicode.E5.AD.97.E7.AC.A6.E5.B9.B3.E9.9D.A2.E6.98.A0.E5.B0.84
  5. http://www.ietf.org/rfc/rfc3987.txt
  6. http://www.blackhat.com/presentations/bh-usa-09/WEBER/BHUSA09-Weber-UnicodeSecurityPreview-PAPER.pdf
  7. http://www.casaba.com/files/Chris_Weber_Character%20Transformations%20v1.7_IUC33.pdf
  8. http://websecuritytool.codeplex.com/

发表回复